Compare commits

...

1124 Commits

Author SHA1 Message Date
Chocobozzz
0fb216c2fc Fix video password access 2025-11-24 16:50:40 +01:00
Chocobozzz
3cd38da9bf Correctly hide new feature popup 2025-11-24 13:10:26 +01:00
Chocobozzz
3785cdf947 Fix section title margin 2025-11-24 10:44:08 +01:00
Chocobozzz
bbb356e284 Update translations 2025-11-20 16:23:43 +01:00
Milo Ivir
22d6117b0a Translated using Weblate (Croatian)
Currently translated at 100.0% (271 of 271 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/hr/
2025-11-20 16:21:11 +01:00
Milo Ivir
9f05d6fdeb Translated using Weblate (Croatian)
Currently translated at 74.7% (2225 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hr/
2025-11-20 16:21:11 +01:00
Jeff Huang
f2f1e82b0a Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2977 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-11-20 16:21:11 +01:00
Oliwier Jaszczyszyn
970a48af95 Translated using Weblate (Polish)
Currently translated at 94.1% (2803 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-11-20 16:21:11 +01:00
Milo Ivir
ae727d5cf7 Translated using Weblate (Croatian)
Currently translated at 74.6% (2222 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hr/
2025-11-20 16:21:11 +01:00
Fjuro
5e3b3ad52c Translated using Weblate (Czech)
Currently translated at 100.0% (272 of 272 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/cs/
2025-11-20 16:21:11 +01:00
Milo Ivir
e33116253f Translated using Weblate (Croatian)
Currently translated at 74.2% (2209 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hr/
2025-11-20 16:21:11 +01:00
Fjuro
916949988b Translated using Weblate (Czech)
Currently translated at 100.0% (277 of 277 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/cs/
2025-11-20 16:21:11 +01:00
Milo Ivir
383fda3968 Translated using Weblate (Croatian)
Currently translated at 100.0% (271 of 271 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/hr/
2025-11-20 16:21:11 +01:00
Milo Ivir
ba81c3fdc9 Translated using Weblate (Croatian)
Currently translated at 100.0% (275 of 275 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/hr/
2025-11-20 16:21:11 +01:00
Milo Ivir
4877cfa901 Translated using Weblate (Croatian)
Currently translated at 73.4% (2188 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hr/
2025-11-20 16:21:11 +01:00
Oliwier Jaszczyszyn
77be18cd7d Translated using Weblate (Polish)
Currently translated at 92.8% (2765 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-11-20 16:21:11 +01:00
Ghost of Sparta
c87f8ef77a Translated using Weblate (Hungarian)
Currently translated at 100.0% (270 of 270 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/hu/
2025-11-20 16:21:11 +01:00
Wuzzy
cb16611275 Translated using Weblate (German)
Currently translated at 100.0% (270 of 270 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/de/
2025-11-20 16:21:11 +01:00
Wuzzy
d541d686e1 Translated using Weblate (German)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/de/
2025-11-20 16:21:11 +01:00
Ghost of Sparta
25b8fe8ee7 Translated using Weblate (Hungarian)
Currently translated at 100.0% (277 of 277 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/hu/
2025-11-20 16:21:11 +01:00
Wuzzy
14ea459dfe Translated using Weblate (German)
Currently translated at 100.0% (277 of 277 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/de/
2025-11-20 16:21:11 +01:00
Leif-Jöran Olsson
fbc61c7f61 Translated using Weblate (Swedish)
Currently translated at 100.0% (2977 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-11-20 16:21:11 +01:00
Wuzzy
7ec529ebb4 Translated using Weblate (German)
Currently translated at 100.0% (2977 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-11-20 16:21:10 +01:00
Hồ Nhất Duy
514e753918 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (269 of 269 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/vi/
2025-11-20 16:21:10 +01:00
Hồ Nhất Duy
49afa3cb65 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/vi/
2025-11-20 16:21:10 +01:00
Hồ Nhất Duy
f062d88b75 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (277 of 277 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/vi/
2025-11-20 16:21:10 +01:00
Hồ Nhất Duy
5bfbf0dcb3 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2977 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-11-20 16:21:10 +01:00
fran secs
c095185192 Translated using Weblate (Catalan)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/ca/
2025-11-20 16:21:10 +01:00
fran secs
2f89f92989 Translated using Weblate (Catalan)
Currently translated at 100.0% (2977 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-11-20 16:21:10 +01:00
Tibbe Debats
7ebca3451e Translated using Weblate (Dutch)
Currently translated at 99.2% (268 of 270 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/nl/
2025-11-20 16:21:10 +01:00
Wuzzy
27abb4e3fb Translated using Weblate (German)
Currently translated at 100.0% (270 of 270 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/de/
2025-11-20 16:21:10 +01:00
B
db8c989334 Translated using Weblate (Dutch)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/nl/
2025-11-20 16:21:10 +01:00
Tibbe Debats
de57482336 Translated using Weblate (Dutch)
Currently translated at 90.8% (2705 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-11-20 16:21:10 +01:00
Wuzzy
3e6789064c Translated using Weblate (German)
Currently translated at 99.9% (2976 of 2977 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-11-20 16:21:10 +01:00
Chocobozzz
49dbf33dd8 Fix mobile buttons 2025-11-20 16:20:40 +01:00
Chocobozzz
2a97758a3e Fix header height 2025-11-20 16:15:49 +01:00
Chocobozzz
60f92d55de Add new feature modal info 2025-11-20 16:06:41 +01:00
Chocobozzz
94c2e8bdf6 UI improvements 2025-11-20 12:34:56 +01:00
Chocobozzz
7b7f00434d Ensure migration is finished 2025-11-20 10:54:49 +01:00
Chocobozzz
e5ea728fc4 Prevent associated actor data deletion 2025-11-20 09:39:54 +01:00
Chocobozzz
0ec8b1cb3e More robust user deletion 2025-11-20 06:40:19 +01:00
Chocobozzz
ccc0f7c7b7 Fix hooks order 2025-11-20 06:27:59 +01:00
Chocobozzz
af29d2a8af Fix actor table associations
With the new method, the actor row is automatically deleted and saved in
another table. It's cleaner and prevent phantom rows
2025-11-19 17:57:21 +01:00
Hannes Mehnert
c337d399e8 Update README.md: adjust copyright year to 2025 2025-11-19 15:46:32 +01:00
Chocobozzz
b1ae23b33d Translate RSS feed titles 2025-11-18 07:06:13 +01:00
Chocobozzz
95a010b6c4 Fix quota calculation 2025-11-18 07:05:28 +01:00
Chocobozzz
3ddddc1b72 Remove deprecated fields
* Remove filename from VideoSource
 * Remove commentsEnabled from REST API & ActivityPub
 * Remove redundancies.files from VideoRedundancy
 * Correctly deprecate captionPath from VideoCaption
 * Correctly deprecate path from ActorImage
 * Correctly deprecate storyboardPath from Storyboard
2025-11-18 07:04:15 +01:00
Chocobozzz
d68dfe349a Remove some FIXME 2025-11-17 10:10:49 +01:00
Chocobozzz
3d3240ae01 Add player settings URL to channel object 2025-11-17 10:01:20 +01:00
Chocobozzz
822fe3e1d9 Include channels/playlists with languages prefs 2025-11-17 09:41:33 +01:00
Chocobozzz
6c6da1c512 Prefer INNER JOIN 2025-11-14 16:29:04 +01:00
Chocobozzz
b127e10e85 Prevent too much logging 2025-11-14 16:28:57 +01:00
Chocobozzz
0185cbdedc Update translations 2025-11-14 15:07:14 +01:00
Chocobozzz
bc19e94f3a Fix bitrate format 2025-11-14 15:07:07 +01:00
Chocobozzz
4e3df6159d Merge remote-tracking branch 'weblate/develop' into develop 2025-11-14 14:52:23 +01:00
Chocobozzz
db1dfc6756 Painfully upgrade dependencies 2025-11-14 14:52:17 +01:00
Tibbe Debats
ff936ec7f1 Translated using Weblate (Dutch)
Currently translated at 98.8% (267 of 270 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/nl/
2025-11-14 06:19:11 +01:00
fran secs
9d5923abbc Translated using Weblate (Catalan)
Currently translated at 100.0% (271 of 271 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/ca/
2025-11-14 06:19:11 +01:00
fran secs
3c45157272 Translated using Weblate (Catalan)
Currently translated at 100.0% (277 of 277 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/ca/
2025-11-14 06:19:11 +01:00
Tibbe Debats
b4007c906e Translated using Weblate (Dutch)
Currently translated at 90.6% (2694 of 2972 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-11-14 06:19:10 +01:00
fran secs
230c7321d6 Translated using Weblate (Catalan)
Currently translated at 100.0% (2972 of 2972 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-11-14 06:19:09 +01:00
Leif-Jöran Olsson
d8eb89a84a Translated using Weblate (Swedish)
Currently translated at 100.0% (270 of 270 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sv/
2025-11-13 15:18:15 +01:00
Besnik Bleta
1208c3a08f Translated using Weblate (Albanian)
Currently translated at 97.7% (264 of 270 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sq/
2025-11-13 15:18:15 +01:00
Besnik Bleta
0050786a36 Translated using Weblate (Albanian)
Currently translated at 100.0% (275 of 275 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/sq/
2025-11-13 15:18:15 +01:00
Leif-Jöran Olsson
f4d42b745d Translated using Weblate (Swedish)
Currently translated at 100.0% (277 of 277 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/sv/
2025-11-13 15:18:15 +01:00
Leif-Jöran Olsson
ad82d333fd Translated using Weblate (Swedish)
Currently translated at 100.0% (2972 of 2972 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-11-13 15:18:15 +01:00
Phongpanot
2c8326d02d Translated using Weblate (Thai)
Currently translated at 100.0% (269 of 269 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/th/
2025-11-13 15:18:15 +01:00
Jeff Huang
d38142e9b2 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2972 of 2972 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-11-13 15:18:15 +01:00
HugeFrog24
bbb2c96cde feat: add resend verification email functionality to admin users list (#7272)
* feat: add resend verification email functionality to admin users list

- Add resendVerificationEmail methods to UserAdminService for individual and bulk operations
- Add 'Resend verification email' action to user moderation dropdown
- Add bulk 'Resend verification emails' action to admin users list
- Reuse existing /api/v1/users/ask-send-verify-email endpoint
- Add proper error handling and success notifications
- Addresses GitHub Issue #5381

* Refactor

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-11-13 15:18:11 +01:00
Shalabh Agarwal
9ed63f5e37 feat: add new video password api (#7044)
* add new video password api

* replace patch with post request

* Styling

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-11-13 14:40:44 +01:00
Chocobozzz
3b97d1afda Add ability to display email with auth plugin 2025-11-13 14:17:04 +01:00
Chocobozzz
675bb86cf6 Cleanup headings 2025-11-13 13:19:28 +01:00
Chocobozzz
00b930d7d9 Simplify watch page CSS 2025-11-13 10:20:09 +01:00
Chocobozzz
3c316a7736 Keep videos order on user import/export 2025-11-13 10:19:49 +01:00
Chocobozzz
4ab73ee86c Add Swiss German for video language metadata 2025-11-13 09:27:10 +01:00
Chocobozzz
c5c1521c4a Add comment to video source columns 2025-11-13 09:24:29 +01:00
Chocobozzz
41a86bfd3c Better "video blocked" message 2025-11-13 09:18:40 +01:00
Chocobozzz
6131a46c9a P2P explanations 2025-11-12 17:07:47 +01:00
Chocobozzz
bca5082fbf Explain the player theme is only used by the web 2025-11-12 17:01:45 +01:00
Chocobozzz
085311a90a Fix comments SQL query 2025-11-12 16:16:27 +01:00
Chocobozzz
375dc00707 Update translations 2025-11-12 15:43:02 +01:00
Aarón Guillén
9e1a7cccbb Translated using Weblate (Spanish)
Currently translated at 85.3% (2505 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-11-12 15:33:44 +01:00
Aarón Guillén
229d5d1959 Translated using Weblate (Spanish)
Currently translated at 85.2% (2504 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-11-12 15:25:16 +01:00
Aarón Guillén
71307a1033 Translated using Weblate (Spanish)
Currently translated at 84.8% (2490 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-11-12 15:25:16 +01:00
Phongpanot
98d1c1c35b Translated using Weblate (Thai)
Currently translated at 100.0% (261 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/th/
2025-11-12 15:25:16 +01:00
Aarón Guillén
a3eb92f004 Translated using Weblate (Spanish)
Currently translated at 84.8% (2490 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-11-12 15:25:16 +01:00
Phongpanot
377751bfa9 Translated using Weblate (Thai)
Currently translated at 100.0% (261 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/th/
2025-11-12 15:25:16 +01:00
Milo Ivir
9f9436accc Translated using Weblate (Croatian)
Currently translated at 75.6% (2221 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hr/
2025-11-12 15:25:16 +01:00
Milo Ivir
8d80ff6630 Translated using Weblate (Croatian)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/hr/
2025-11-12 15:25:16 +01:00
Goudarz Jafari
1316a84f5a Translated using Weblate (Persian)
Currently translated at 99.6% (273 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/fa/
2025-11-12 15:25:16 +01:00
chocobozzz
0384eb2b49 Translated using Weblate (German)
Currently translated at 100.0% (2936 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-11-12 15:25:16 +01:00
Besnik Bleta
90739eb286 Translated using Weblate (Albanian)
Currently translated at 97.7% (255 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sq/
2025-11-12 15:25:16 +01:00
Besnik Bleta
8fe58cf056 Translated using Weblate (Albanian)
Currently translated at 63.8% (1874 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sq/
2025-11-12 15:25:16 +01:00
Besnik Bleta
45e4f4694a Translated using Weblate (Albanian)
Currently translated at 95.7% (250 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sq/
2025-11-12 15:25:16 +01:00
T.S
7bf7aa96fd Translated using Weblate (Japanese)
Currently translated at 95.1% (2795 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-11-12 15:25:16 +01:00
Goudarz Jafari
fbf9902bc9 Translated using Weblate (Persian)
Currently translated at 60.5% (1777 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fa/
2025-11-12 15:25:16 +01:00
Fjuro
ab73b7798e Translated using Weblate (Czech)
Currently translated at 91.2% (2680 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-11-12 15:25:16 +01:00
peppe namir
1c1c9b1740 Translated using Weblate (Italian)
Currently translated at 85.3% (2506 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/it/
2025-11-12 15:25:16 +01:00
Goudarz Jafari
5b62583f9d Translated using Weblate (Persian)
Currently translated at 60.4% (1776 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fa/
2025-11-12 15:25:16 +01:00
Aarón Guillén
4b0c35cd13 Translated using Weblate (Spanish)
Currently translated at 81.4% (2391 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-11-12 15:25:16 +01:00
Goudarz Jafari
21a5f4c7bd Translated using Weblate (Persian)
Currently translated at 100.0% (261 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/fa/
2025-11-12 15:25:16 +01:00
Ghost of Sparta
c34eb462dd Translated using Weblate (Hungarian)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/hu/
2025-11-12 15:25:16 +01:00
Goudarz Jafari
3f70947e34 Translated using Weblate (Persian)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/fa/
2025-11-12 15:25:16 +01:00
Goudarz Jafari
f2051582d1 Translated using Weblate (Persian)
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/fa/
2025-11-12 15:25:16 +01:00
Goudarz Jafari
e3ad2a3465 Translated using Weblate (Persian)
Currently translated at 60.4% (1774 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fa/
2025-11-12 15:25:16 +01:00
Aarón Guillén
12e3c80d0a Translated using Weblate (Spanish)
Currently translated at 81.3% (2387 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-11-12 15:25:16 +01:00
Wuzzy
621c36ba22 Translated using Weblate (German)
Currently translated at 100.0% (2936 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-11-12 15:25:15 +01:00
Leonora
29f871ef65 Translated using Weblate (Danish)
Currently translated at 22.5% (662 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/da/
2025-11-12 15:25:15 +01:00
B
2623fb53d8 Translated using Weblate (Dutch)
Currently translated at 88.1% (230 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/nl/
2025-11-12 15:25:15 +01:00
Wuzzy
7022816a43 Translated using Weblate (German)
Currently translated at 99.2% (259 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/de/
2025-11-12 15:25:15 +01:00
Wuzzy
93db670074 Translated using Weblate (German)
Currently translated at 99.2% (2914 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-11-12 15:25:15 +01:00
Besnik Bleta
5c96101af4 Translated using Weblate (Albanian)
Currently translated at 91.1% (238 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sq/
2025-11-12 15:25:15 +01:00
偶尔来巡山
89dde0b6ef Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/zh_Hans/
2025-11-12 15:25:15 +01:00
Ricardo Simões
d40ab3c7e5 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/pt_PT/
2025-11-12 15:25:15 +01:00
Ricardo Simões
fa0dd3fff2 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/pt_PT/
2025-11-12 15:25:15 +01:00
Ricardo Simões
6199bf823b Translated using Weblate (Portuguese (Portugal))
Currently translated at 16.7% (493 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_PT/
2025-11-12 15:25:15 +01:00
fran secs
613e46903d Translated using Weblate (Catalan)
Currently translated at 100.0% (261 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/ca/
2025-11-12 15:25:15 +01:00
Besnik Bleta
ed21bf7c17 Translated using Weblate (Albanian)
Currently translated at 54.2% (1593 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sq/
2025-11-12 15:25:15 +01:00
fran secs
1aade976e1 Translated using Weblate (Catalan)
Currently translated at 100.0% (2936 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-11-12 15:25:15 +01:00
fran secs
469676602b Translated using Weblate (Catalan)
Currently translated at 97.4% (2861 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-11-12 15:25:15 +01:00
Jeff Huang
37b5010b2a Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (261 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/zh_Hant/
2025-11-12 15:25:15 +01:00
Leif-Jöran Olsson
eb9a2f6a07 Translated using Weblate (Swedish)
Currently translated at 100.0% (261 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sv/
2025-11-12 15:25:15 +01:00
Sveinn í Felli
5e95f21f15 Translated using Weblate (Icelandic)
Currently translated at 85.5% (2511 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/is/
2025-11-12 15:25:15 +01:00
Jeff Huang
b38c56dba4 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2936 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-11-12 15:25:15 +01:00
fran secs
3e5844695d Translated using Weblate (Spanish)
Currently translated at 80.8% (2375 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-11-12 15:25:15 +01:00
Aarón Guillén
edb6c04dbc Translated using Weblate (Spanish)
Currently translated at 80.8% (2375 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-11-12 15:25:15 +01:00
fran secs
ce08076915 Translated using Weblate (Catalan)
Currently translated at 97.3% (2857 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-11-12 15:25:15 +01:00
fran secs
c54cd4382c Translated using Weblate (Catalan)
Currently translated at 100.0% (261 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/ca/
2025-11-12 15:25:15 +01:00
fran secs
53f166b531 Translated using Weblate (Catalan)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/ca/
2025-11-12 15:25:15 +01:00
Aarón Guillén
330869c660 Translated using Weblate (Spanish)
Currently translated at 80.8% (2375 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-11-12 15:25:15 +01:00
fran secs
04ee9c8b8c Translated using Weblate (Catalan)
Currently translated at 95.9% (2818 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-11-12 15:25:15 +01:00
Jeff Huang
d280e35b23 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (261 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/zh_Hant/
2025-11-12 15:25:15 +01:00
Hồ Nhất Duy
22b5148125 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (261 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/vi/
2025-11-12 15:25:14 +01:00
Leif-Jöran Olsson
3c931c71f2 Translated using Weblate (Swedish)
Currently translated at 100.0% (261 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sv/
2025-11-12 15:25:14 +01:00
Besnik Bleta
e924229932 Translated using Weblate (Albanian)
Currently translated at 97.3% (254 of 261 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sq/
2025-11-12 15:25:14 +01:00
Besnik Bleta
52ee2cf48b Translated using Weblate (Albanian)
Currently translated at 98.7% (158 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/sq/
2025-11-12 15:25:14 +01:00
Jeff Huang
bf2ec614e3 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/zh_Hant/
2025-11-12 15:25:14 +01:00
Leif-Jöran Olsson
807a12bfcd Translated using Weblate (Swedish)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/sv/
2025-11-12 15:25:14 +01:00
Fjuro
d7306d2c6d Translated using Weblate (Czech)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/cs/
2025-11-12 15:25:14 +01:00
Hồ Nhất Duy
d7a7e77e98 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2936 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-11-12 15:25:14 +01:00
Leif-Jöran Olsson
1577d2275e Translated using Weblate (Swedish)
Currently translated at 100.0% (2936 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-11-12 15:25:14 +01:00
Victor QuQunta
b5e1921103 Translated using Weblate (Russian)
Currently translated at 78.6% (2309 of 2936 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ru/
2025-11-12 15:25:14 +01:00
Chocobozzz
e30e5c9f7b Add ability to retry video imports
Channel syncs also retry imports
2025-11-12 14:35:26 +01:00
Chocobozzz
f4e9192ca4 Fix alignment 2025-11-10 13:12:52 +01:00
Chocobozzz
f35c2477c9 Improve error messages 2025-11-10 13:12:37 +01:00
Chocobozzz
25f0ba7bd5 Replace description by name
Because we can't inject HTML in the title attribute
2025-10-31 14:08:05 +01:00
Chocobozzz
3405ebd2e0 Fix activity colors 2025-10-31 11:46:12 +01:00
Chocobozzz
e5351a0eb0 Group channel activities 2025-10-31 11:41:52 +01:00
Chocobozzz
639f73f414 More precise date toggle 2025-10-31 11:11:22 +01:00
Chocobozzz
4cd6dbf253 More precise interval 2025-10-31 11:11:12 +01:00
Chocobozzz
ff758863cf Prefer "shared"
We only have standalone components
2025-10-31 10:48:30 +01:00
Chocobozzz
bd11b153fb Correctly update playlists state
Handle creation/deletion etc
2025-10-31 10:35:39 +01:00
Chocobozzz
4f8edcc095 Add openapi doc for channel activities 2025-10-31 10:08:24 +01:00
Chocobozzz
0edf927e03 Optimize comment SQL query 2025-10-31 09:54:41 +01:00
Chocobozzz
09d90b8152 Add channel activities feature 2025-10-30 16:25:04 +01:00
Chocobozzz
dbc47e0397 Fix openid tests 2025-10-30 08:34:16 +01:00
Chocobozzz
08029076f9 Don't update publishedAt with null scheduleUpdate 2025-10-29 15:50:06 +01:00
Chocobozzz
755120e2c7 Fix DB inconsistency with node abi column 2025-10-29 15:29:54 +01:00
Chocobozzz
cb43337783 Add ability to customize transcription TTL 2025-10-29 15:19:31 +01:00
Chocobozzz
6bb9359065 Update nodejs version checker 2025-10-29 15:11:38 +01:00
Chocobozzz
084cfb0ead Fix sort by button spacing 2025-10-29 15:08:23 +01:00
Chocobozzz
2dcaefe83b Display all the available countries/regions
The previous was too low, and chart.js hid some country/region names
2025-10-29 14:47:59 +01:00
Chocobozzz
9257076b23 Add support/init.d in release tarball 2025-10-29 14:12:52 +01:00
Chocobozzz
5ef484a221 Add support/conf.d in release tarball 2025-10-29 14:11:08 +01:00
Chocobozzz
47f2b879db Faster HLS startTime seek 2025-10-29 13:59:09 +01:00
Chocobozzz
9d5fb9f772 Fix padding 2025-10-29 13:32:13 +01:00
Chocobozzz
fcdfeaf31d Delete/update buttons order consistency 2025-10-29 13:18:38 +01:00
Chocobozzz
4887c28ef8 Add STUN tests 2025-10-29 11:26:35 +01:00
Chocobozzz
9e687188c9 Fix nginx tests 2025-10-29 11:06:04 +01:00
Chocobozzz
9f97883172 Update STUN server lists 2025-10-29 11:06:04 +01:00
Chocobozzz
4376c728b1 Fix transcription CI 2025-10-29 10:32:06 +01:00
Chocobozzz
b548618c27 Fix migrations 2025-10-29 08:58:01 +01:00
Chocobozzz
eb23d76a85 Fix tests 2025-10-29 08:57:57 +01:00
Chocobozzz
f2f814f9d7 Fix tests 2025-10-28 16:49:23 +01:00
Chocobozzz
6c47548d51 Search on account name when searching channels 2025-10-28 16:40:56 +01:00
Chocobozzz
614521a39e Fix scrolling videos 2025-10-28 16:34:55 +01:00
Chocobozzz
7cdfc592be Update translations 2025-10-28 16:22:23 +01:00
Chocobozzz
2aa62a0383 Fix update script 2025-10-28 16:22:09 +01:00
Victor QuQunta
b822a2ac49 Translated using Weblate (Russian)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/ru/
2025-10-28 16:00:43 +01:00
Victor QuQunta
de58fe9499 Translated using Weblate (Russian)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/ru/
2025-10-28 16:00:43 +01:00
Hồ Nhất Duy
0fd61b1698 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/vi/
2025-10-28 16:00:43 +01:00
Victor QuQunta
b810c4a36b Translated using Weblate (Russian)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/ru/
2025-10-28 16:00:43 +01:00
Hồ Nhất Duy
f8f480950e Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-10-28 16:00:43 +01:00
Victor QuQunta
48f3128611 Translated using Weblate (Russian)
Currently translated at 82.3% (2338 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ru/
2025-10-28 16:00:43 +01:00
Hồ Nhất Duy
bcfed69ed9 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-10-28 16:00:42 +01:00
jinsoo
c823de2f98 Translated using Weblate (Korean)
Currently translated at 96.8% (152 of 157 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/ko/
2025-10-28 16:00:42 +01:00
jinsoo
8aca768257 Translated using Weblate (Korean)
Currently translated at 11.3% (322 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ko/
2025-10-28 16:00:42 +01:00
Sveinn í Felli
89418dd637 Translated using Weblate (Icelandic)
Currently translated at 90.1% (2559 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/is/
2025-10-28 16:00:42 +01:00
Daniel Viñar Ulriksen
dffe018a39 Translated using Weblate (Spanish)
Currently translated at 80.1% (2277 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-10-28 16:00:42 +01:00
Sveinn í Felli
516546bea6 Translated using Weblate (Icelandic)
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/is/
2025-10-28 16:00:42 +01:00
Sveinn í Felli
ca19fe0aba Translated using Weblate (Icelandic)
Currently translated at 87.0% (2471 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/is/
2025-10-28 16:00:42 +01:00
Jiří Podhorecký
a27d3a81d9 Translated using Weblate (Czech)
Currently translated at 92.3% (2622 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-10-28 16:00:42 +01:00
Daniel Renth
2858af6918 Translated using Weblate (German)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/de/
2025-10-28 16:00:42 +01:00
Wuzzy
a463adb0a2 Translated using Weblate (German)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/de/
2025-10-28 16:00:42 +01:00
Daniel Renth
2d06d07ee1 Translated using Weblate (German)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-10-28 16:00:42 +01:00
Wuzzy
33713e8b0f Translated using Weblate (German)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-10-28 16:00:42 +01:00
Leif-Jöran Olsson
426e73ce8b Translated using Weblate (Swedish)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-10-28 16:00:42 +01:00
jinsoo
c05117ef4d Translated using Weblate (Korean)
Currently translated at 8.0% (228 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ko/
2025-10-28 16:00:42 +01:00
Tibbe Debats
a571428735 Translated using Weblate (Dutch)
Currently translated at 94.2% (2676 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:42 +01:00
Hồ Nhất Duy
09fe2af39f Translated using Weblate (Vietnamese)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/vi/
2025-10-28 16:00:42 +01:00
John Livingston
39c30f9e17 Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-10-28 16:00:42 +01:00
Jiří Podhorecký
abc24fad2e Translated using Weblate (Czech)
Currently translated at 92.2% (2621 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-10-28 16:00:42 +01:00
fran secs
ed15e3ca4d Translated using Weblate (Catalan)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-10-28 16:00:42 +01:00
Tibbe Debats
7ed8ab75b5 Translated using Weblate (Dutch)
Currently translated at 94.1% (2675 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:42 +01:00
fran secs
0052a4d095 Translated using Weblate (Catalan)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-10-28 16:00:42 +01:00
Jiří Podhorecký
c0c6b9236c Translated using Weblate (Czech)
Currently translated at 91.3% (2593 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-10-28 16:00:42 +01:00
B
4ead7306ec Translated using Weblate (Dutch)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/nl/
2025-10-28 16:00:42 +01:00
Tibbe Debats
ec28327632 Translated using Weblate (Dutch)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/nl/
2025-10-28 16:00:41 +01:00
Tibbe Debats
03a2f5668c Translated using Weblate (Dutch)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/nl/
2025-10-28 16:00:41 +01:00
Tibbe Debats
cb9047c170 Translated using Weblate (Dutch)
Currently translated at 94.1% (2674 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:41 +01:00
Tibbe Debats
de8cee18d2 Translated using Weblate (Dutch)
Currently translated at 94.0% (2670 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:41 +01:00
Tibbe Debats
0c682a915b Translated using Weblate (Dutch)
Currently translated at 90.7% (2577 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:41 +01:00
Tibbe Debats
31e6b39fe0 Translated using Weblate (Dutch)
Currently translated at 89.4% (2541 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:41 +01:00
Tibbe Debats
f57110a956 Translated using Weblate (Dutch)
Currently translated at 86.1% (2448 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:41 +01:00
B
9dece339a3 Translated using Weblate (Dutch)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/nl/
2025-10-28 16:00:41 +01:00
Tibbe Debats
2bba9bba87 Translated using Weblate (Dutch)
Currently translated at 85.9% (2442 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:41 +01:00
B
095e49592b Translated using Weblate (Dutch)
Currently translated at 85.9% (2442 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:41 +01:00
Tibbe Debats
8a9ed579ab Translated using Weblate (Dutch)
Currently translated at 85.9% (2442 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:41 +01:00
Jeff Huang
0227fc19c2 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-10-28 16:00:41 +01:00
Oliwier Jaszczyszyn
9a5d2ebf48 Translated using Weblate (Polish)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-10-28 16:00:41 +01:00
Jeff Huang
e7a33866c5 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/zh_Hant/
2025-10-28 16:00:41 +01:00
Milo Ivir
766e50bf10 Translated using Weblate (Croatian)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/hr/
2025-10-28 16:00:41 +01:00
Milo Ivir
5d3717766b Translated using Weblate (Croatian)
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/hr/
2025-10-28 16:00:41 +01:00
Milo Ivir
6fa40c0bf0 Translated using Weblate (Croatian)
Currently translated at 79.4% (2255 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hr/
2025-10-28 16:00:41 +01:00
Wu Wei
1688b42476 Translated using Weblate (Croatian)
Currently translated at 79.4% (2255 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hr/
2025-10-28 16:00:41 +01:00
Jeff Huang
b342b0ae11 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/zh_Hant/
2025-10-28 16:00:41 +01:00
Jeff Huang
9ca3d8e58b Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/zh_Hant/
2025-10-28 16:00:41 +01:00
Oliwier Jaszczyszyn
ae81387001 Translated using Weblate (Polish)
Currently translated at 88.3% (2510 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-10-28 16:00:41 +01:00
Adrià Martín
25f6245680 Translated using Weblate (Catalan)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-10-28 16:00:41 +01:00
Leif-Jöran Olsson
9020e276f6 Translated using Weblate (Swedish)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-10-28 16:00:41 +01:00
Kenner Figueiredo
5541054f32 Translated using Weblate (Portuguese (Brazil))
Currently translated at 89.4% (2539 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-10-28 16:00:41 +01:00
Quentin THEURET
7013f04efc Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-10-28 16:00:40 +01:00
Ignacio Carrera González
7eda7b5f65 Translated using Weblate (Spanish)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/es/
2025-10-28 16:00:40 +01:00
Ignacio Carrera González
fca1ae4e0d Translated using Weblate (Spanish)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/es/
2025-10-28 16:00:40 +01:00
Ignacio Carrera González
eb2e14fccd Translated using Weblate (Spanish)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/es/
2025-10-28 16:00:40 +01:00
ukuk
f2adff7e12 Translated using Weblate (Polish)
Currently translated at 76.9% (2185 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-10-28 16:00:40 +01:00
Ignacio Carrera González
1d5a8bf589 Translated using Weblate (Spanish)
Currently translated at 77.5% (2201 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-10-28 16:00:40 +01:00
alex gabilondo
7915680ab7 Translated using Weblate (Basque)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/eu/
2025-10-28 16:00:40 +01:00
fran secs
309fce5a18 Translated using Weblate (Catalan)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/ca/
2025-10-28 16:00:40 +01:00
Oliwier Jaszczyszyn
bd3b81d109 Translated using Weblate (Polish)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/pl/
2025-10-28 16:00:40 +01:00
Tibbe Debats
fc27f6e5c3 Translated using Weblate (Dutch)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/nl/
2025-10-28 16:00:40 +01:00
Wu Wei
3bd0991011 Translated using Weblate (Croatian)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/hr/
2025-10-28 16:00:40 +01:00
Ignacio Carrera González
af40fd1707 Translated using Weblate (Latin)
Currently translated at 21.0% (33 of 157 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/la/
2025-10-28 16:00:40 +01:00
Ignacio Carrera González
875d5cd964 Translated using Weblate (Latin)
Currently translated at 6.6% (18 of 272 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/la/
2025-10-28 16:00:40 +01:00
Ignacio Carrera González
976ce40842 Translated using Weblate (Latin)
Currently translated at 0.1% (1 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/la/
2025-10-28 16:00:40 +01:00
Wu Wei
7965e0e16d Translated using Weblate (Croatian)
Currently translated at 78.1% (2220 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hr/
2025-10-28 16:00:40 +01:00
Oliwier Jaszczyszyn
656ca62796 Translated using Weblate (Polish)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/pl/
2025-10-28 16:00:40 +01:00
Ignacio Carrera González
80c7dc348e Translated using Weblate (Spanish)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/es/
2025-10-28 16:00:40 +01:00
Blood Axe
5e78d3bf6c Translated using Weblate (Norwegian Bokmål)
Currently translated at 30.6% (84 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/nb_NO/
2025-10-28 16:00:40 +01:00
Oliwier Jaszczyszyn
8f135fec5c Translated using Weblate (Polish)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/pl/
2025-10-28 16:00:40 +01:00
Ignacio Carrera González
938f3f9e51 Translated using Weblate (Spanish)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/es/
2025-10-28 16:00:40 +01:00
偶尔来巡山
810d6c6612 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-10-28 16:00:40 +01:00
Oliwier Jaszczyszyn
e82ba16b29 Translated using Weblate (Polish)
Currently translated at 76.6% (2178 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-10-28 16:00:40 +01:00
Tibbe Debats
3544b08f59 Translated using Weblate (Dutch)
Currently translated at 84.0% (2388 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-10-28 16:00:40 +01:00
Blood Axe
f610c910c0 Translated using Weblate (Norwegian Bokmål)
Currently translated at 76.5% (2175 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-10-28 16:00:40 +01:00
Ignacio Carrera González
8801004ba9 Translated using Weblate (Spanish)
Currently translated at 77.3% (2198 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-10-28 16:00:39 +01:00
Wuzzy
0e97d07629 Translated using Weblate (German)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-10-28 16:00:39 +01:00
Chocobozzz
afd913530c Fix mention redirection 2025-10-28 16:00:26 +01:00
Chocobozzz
190987cc72 Fix lint 2025-10-28 15:08:23 +01:00
Chocobozzz
0babdbc243 Require at least 3GB to upgrade peertube 2025-10-28 15:07:25 +01:00
Chocobozzz
1c94e97923 Improve notifications design 2025-10-28 14:59:56 +01:00
Chocobozzz
381f8e3b3a Add channel collaborators feature
For now only an "editor" role is available for collaborators. An editor
has the same right as the channel owner but cannot:
 * Delete the channel
 * Invite collaborators
 * Transfer ownership of a video
 * Transfer ownership of a channel (feature not developed yet)
 * Invite a new collaborator
 * Remove another collaborator

 The owner of a channel can invite another local account to be an editor
 of the channel. The editor can accept or reject the invitation.

 Moved transfer ownership of a video in the "Manage video" page.

 Updated the video channel update page to a "Manage" page, like we have
 for the video to add an "Editors" sub section, allowing the owner of
   the channel to manage channel editors.

Refactored the SQL query classes and added more raw SQL queries for
models that list entities depending on channel collaboration status.

Updated server tests to check editors can manage or cannot manage
channel entities.
2025-10-28 14:44:44 +01:00
Chocobozzz
4fd4c91ec1 Add ability to cleanup views on local videos too 2025-10-10 11:52:33 +02:00
Chocobozzz
ed8279eae6 Copy codecs for HLS if possible 2025-10-10 09:05:57 +02:00
Chocobozzz
f04a11f74d Copy codecs for HLS transcoding
It was disabled because of Safari playback issues
(https://github.com/Chocobozzz/PeerTube/issues/3502), but I couldn't
reproduce so re-enable it

Allows to have a better audio/video quality (because we don't re-encode
these streams) and it saves CPU
2025-10-09 16:32:28 +02:00
Chocobozzz
1ba09ea2fa Fix sitemap tests 2025-10-09 13:40:56 +02:00
Chocobozzz
15e9236373 Add insert at first channel position 2025-10-09 13:35:38 +02:00
Chocobozzz
6a51b685ef Update config after plugin settings changes
Plugin can change the configuration, like transcoding profiles for
example
2025-10-09 10:52:42 +02:00
Gianantonio Pini
319da3b6a5 fix(config): init config check does not report Browse Videos errors (#7222)
* fix(config): modify browse-videos validators to not use i18n when called by checker-after-init

* refactor(config): make browse-videos validators language parameter optional

* refactor(config): use template literals in browse-videos validators

* Fix i18n string extraction

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-10-09 10:35:58 +02:00
Chocobozzz
ba3bb0f142 Use schedule at date for publishedAt
Improve information to user and respect publication sort
2025-10-08 16:48:52 +02:00
Chocobozzz
5286f0ed46 Update sitemap static URLs 2025-10-08 16:27:21 +02:00
Chocobozzz
2f816446a6 Merge branch 'release/7.3.x' into develop 2025-10-08 15:58:37 +02:00
Chocobozzz
d867eb367b Show their own videos to muted accounts 2025-10-08 15:50:46 +02:00
Chocobozzz
a25c6d65b8 Fix admin abuse URL 2025-10-08 15:40:30 +02:00
Chocobozzz
77f28ece70 Accept non https URLs
We can use a search index on localhost for example
2025-10-08 15:39:26 +02:00
Chocobozzz
f6eefbde0c Correctly load user languages 2025-10-08 15:37:30 +02:00
Chocobozzz
f61581280d Fix select languages component label 2025-10-08 15:25:30 +02:00
Chocobozzz
3a9a76b3b4 Remove unused config 2025-10-08 11:25:16 +02:00
Chocobozzz
54bfae82ad Fix viewers stats date filter label after a reset 2025-09-24 16:53:16 +02:00
Chocobozzz
28a0c774f1 Improve video manage and admin config form a11y 2025-09-24 16:42:29 +02:00
Chocobozzz
d50c8a0b0a Fix scroll issue when navigating from homepage 2025-09-24 16:27:43 +02:00
Chocobozzz
b2704b2f36 theme breaking: --input-placeholder-color
Instead of --input-placeholder and introduce
--input-placeholder-font-size
2025-09-24 16:09:31 +02:00
Chocobozzz
e7694b2911 Remove unused file 2025-09-24 16:05:34 +02:00
Chocobozzz
16a7a5e8cc Don't use cursor on non interactive el 2025-09-24 16:02:26 +02:00
Chocobozzz
df86535f46 Add missing elements of user object 2025-09-24 16:00:34 +02:00
Chocobozzz
3f079b9398 Fix broken customization config page 2025-09-24 15:42:35 +02:00
Chocobozzz
4263d755e3 Fix max size information
We don't have such limit on backend side
2025-09-24 15:39:28 +02:00
Chocobozzz
30ca195efa Update node supported versions 2025-09-24 15:38:25 +02:00
Chocobozzz
68547190c7 Fix node min versions 2025-09-17 15:37:49 +02:00
Chocobozzz
94e55dfc6c Merge branch 'release/7.3.x' into develop 2025-09-16 11:06:00 +02:00
Chocobozzz
bb0c71549a Refactor player variables 2025-09-16 11:05:53 +02:00
Chocobozzz
2a648e6ea5 Fix docker production build 2025-09-16 06:36:25 +02:00
Chocobozzz
3a58afef10 Fix lint 2025-09-15 15:58:08 +02:00
Chocobozzz
84dbcb5f11 Decrease settings menu opacity 2025-09-15 15:40:01 +02:00
Chocobozzz
cd8ad77515 Fix settings menu overflow 2025-09-15 15:28:21 +02:00
Chocobozzz
050461528c Merge branch 'release/7.3.x' into develop 2025-09-15 15:06:33 +02:00
Chocobozzz
073cd4f0ba Fix nodejs_active_resources_total metric
Remove duplicate metric and transform it into a gauge because the value
can decrease
2025-09-15 14:16:37 +02:00
Chocobozzz
42e0c015e8 Fix reloading table data 2025-09-15 14:07:23 +02:00
Chocobozzz
4888717c09 Fix disabled button 2025-09-15 14:00:01 +02:00
Chocobozzz
449ebe4b54 Fix badges alignment 2025-09-15 13:50:44 +02:00
Chocobozzz
3cca1fdbf3 Use diff instead of vimdiff 2025-09-15 13:40:59 +02:00
Chocobozzz
50c184a9a2 Fix external token doc 2025-09-15 13:39:41 +02:00
Chocobozzz
e2e15e3f0c Typo 2025-09-15 13:21:00 +02:00
Chocobozzz
0048bf7326 Add guide to upgrade PostgreSQL in docker 2025-09-15 12:02:07 +02:00
Chocobozzz
4fd894308d Fix CI 2025-09-15 10:02:38 +02:00
Chocobozzz
496b50f6b1 Upgrade docker postgresql and redis versions 2025-09-15 08:39:41 +02:00
Chocobozzz
729a58a860 Move docker to trixie 2025-09-15 07:11:57 +02:00
Chocobozzz
2d96b7191d Remove unused file 2025-09-12 11:00:33 +02:00
Chocobozzz
dca5e363d1 Improve dependencies guide 2025-09-12 10:50:49 +02:00
Chocobozzz
e670b6d924 Fix lint 2025-09-12 10:45:06 +02:00
Chocobozzz
5c1cbcfcb1 Fix model imports 2025-09-12 10:26:59 +02:00
Chocobozzz
a11d3102ce Fix openapi schema 2025-09-12 10:13:29 +02:00
Chocobozzz
f184154aaa Fix handlebars dependency 2025-09-12 09:38:31 +02:00
Chocobozzz
f93870ea31 Patch video.js types to unbreak the build
Remove the patch when https://github.com/videojs/video.js/pull/9089 is
published
2025-09-12 09:08:17 +02:00
Chocobozzz
941469df29 Add externalRedirectUri doc 2025-09-12 08:54:50 +02:00
Chocobozzz
ef95c3fe72 Remove openapi warnings 2025-09-12 08:54:50 +02:00
Chocobozzz
572100b1a3 Fix tests build 2025-09-12 08:54:50 +02:00
Chocobozzz
200193262c Add openapi doc for player settings 2025-09-12 08:54:50 +02:00
Chocobozzz
74e97347bb Add ability to customize player settings 2025-09-12 08:54:50 +02:00
Chocobozzz
b742dbc0fc Update dprint HTML module 2025-09-12 08:54:50 +02:00
Chocobozzz
fcca9b72d3 Add copilot instructions 2025-09-12 08:54:50 +02:00
Chocobozzz
5edab3f795 Introduce lucide player theme 2025-09-12 08:54:50 +02:00
Chocobozzz
a2b99c3c92 Add more info to stats card 2025-09-12 08:54:50 +02:00
Chocobozzz
fde2c8c0c7 Prefer using vertical volume control
Better UX/control
2025-09-12 08:54:50 +02:00
Chocobozzz
48ea20c9e4 Upgrade to videojs v8 2025-09-12 08:54:49 +02:00
Chocobozzz
906b5f7f2c Migrate to pnpm 2025-09-12 08:43:41 +02:00
Chocobozzz
bbc1afada5 Optimize updating oauth tokens activity 2025-09-10 16:53:39 +02:00
Shalabh Agarwal
efa32646ed feat: add user password constraints (#6945)
* feat: add user password length constraints

* add password length changes in locale files

* revert maximum password length changes

* add tests

* fix lint

* fix lint and test

* fix tests

* Revert "add password length changes in locale files"

This reverts commit eaaf63ba7c.

* Update PR

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-09-10 16:51:04 +02:00
Chocobozzz
f1e05043bc Optimize updating oauth tokens activity 2025-09-10 15:16:40 +02:00
Chocobozzz
eedfb8b0a2 Update runner package 2025-09-10 11:55:24 +02:00
諏訪子
ef28ba3038 add x link
Add missing code
2025-09-10 11:51:58 +02:00
ilfarpro
dd52e8b89e Feature for runners - handle storyboard-generation-job (#7191)
* Implement processing storyboards by runners

* Fixed storyboard generation by runners

* use common code patterns

* fix import

* improve debug logging for storyboard generation

* config option for storyboard processing with remote-runners

* refactor repetitive pattern

* refactor storyboard related code to share common utlities

* Fix test

* Fix storyboard generation config logic

* Improve logging

* Added tests for storyboard generation with runners

* Refactor PR

---------

Co-authored-by: ilfarpro <ilfarpro@ya.ru>
Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-09-10 11:50:06 +02:00
Gianantonio Pini
e74bf8ae2a feat(config): add admin options to customize default "Browse videos" behaviour (#7193)
* feat(customBrowseVideosDefaultSort): update server config

* feat(customBrowseVideosDefaultSort): update client admin-config-general component

* feat(customBrowseVideosDefaultSort): add new consistency check to server checker-after-init

* feat(customBrowseVideosDefaultSort): update config .yaml with more details about available options

* feat(customBrowseVideosDefaultSort): refactor consistency check in server checker-after-init

* feat(customBrowseVideosDefaultSort): client, add new select-videos-sort shared component

* feat(customBrowseVideosDefaultSort): client, refactor admin-config-general component to use new select-videos-sort shared component

* feat(customBrowseVideosDefaultSort): client, fix my-select-videos-sort width in admin-config-general

* feat(customBrowseVideosDefaultSort): client, update video-filters-header scss

* feat(customBrowseVideosDefaultSort): client, update videos-list-all component

* feat(config): refactor checkBrowseVideosConfig logic into separate custom validator

* feat(config): refactor isBrowseVideosDefaultSortValid to use template literals

* feat(config): refactor isBrowseVideosDefaultSortValid

* feat(config): add check for invalid browse videos config to customConfigUpdateValidator

* feat(config): group browse-videos tests in describe block

* feat(config): refactor to use client.browse_videos section, instead of browse.videos section

* feat(config): add browse_videos default_scope config key (config and server changes)

* feat(config): add browse_videos default_scope config key (client changes)

* Reorder browse videos before videos

* Fix i18n message

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-09-10 10:41:45 +02:00
Chocobozzz
9b7edd1c59 Cleanup packages 2025-09-10 07:10:31 +02:00
Chocobozzz
93926d2700 Use :root instead of body for CSS variables 2025-09-09 12:56:49 +02:00
Chocobozzz
41b3a404dc Update changelog 2025-09-09 12:53:45 +02:00
Chocobozzz
c922886f8a Bumped to version v7.3.0 2025-09-09 11:07:47 +02:00
Chocobozzz
2bd5f564a3 Update changelog 2025-09-09 10:30:22 +02:00
Chocobozzz
f4c969fd00 Fix translations 2025-09-09 08:21:43 +02:00
Chocobozzz
c3daefa6e9 Update translations 2025-09-09 07:45:32 +02:00
Ghost of Sparta
4c5813463f Translated using Weblate (Hungarian)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/hu/
2025-09-08 16:24:14 +02:00
偶尔来巡山
6f318071db Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/zh_Hans/
2025-09-08 16:24:14 +02:00
Leif-Jöran Olsson
b3da438a00 Translated using Weblate (Swedish)
Currently translated at 100.0% (169 of 169 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sv/
2025-09-08 16:24:14 +02:00
偶尔来巡山
945604ea79 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-09-08 16:24:14 +02:00
sasek
f914e1b7bf Translated using Weblate (Polish)
Currently translated at 76.3% (2168 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-09-08 16:24:14 +02:00
Oliwier Jaszczyszyn
4cb99c3fd5 Translated using Weblate (Polish)
Currently translated at 76.3% (2168 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-09-08 16:24:14 +02:00
Oliwier Jaszczyszyn
715719238a Translated using Weblate (Polish)
Currently translated at 73.7% (2095 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-09-08 16:24:14 +02:00
Joe Silber
7b38c21631 Translated using Weblate (Dutch)
Currently translated at 83.7% (2378 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-09-08 16:24:14 +02:00
Chocobozzz
958aab240d Fix lint 2025-09-08 16:24:03 +02:00
Chocobozzz
4719cf26f4 Fix overflow in discover page 2025-09-08 15:31:59 +02:00
Chocobozzz
a6266dc4bf Fix lint 2025-09-08 08:36:07 +02:00
Chocobozzz
12c9825658 Optimize updating token activity 2025-09-05 10:34:47 +02:00
Chocobozzz
448bc823ef Update client dependencies 2025-09-05 10:34:44 +02:00
Chocobozzz
78eb54464c Update translations 2025-09-05 09:43:14 +02:00
fran secs
75fbdbf70e Translated using Weblate (Catalan)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/ca/
2025-09-05 09:37:23 +02:00
fran secs
326bf8d85f Translated using Weblate (Catalan)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-09-05 09:37:22 +02:00
Chocobozzz
38e04969df Check API search invalid config 2025-09-05 09:36:27 +02:00
Chocobozzz
a1bf55c7ae Update translations 2025-09-04 11:08:47 +02:00
Leonora
707e1e9b98 Translated using Weblate (Danish)
Currently translated at 23.9% (681 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/da/
2025-09-04 11:01:25 +02:00
Leonora
7f9f1feed5 Translated using Weblate (Danish)
Currently translated at 77.0% (205 of 266 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/da/
2025-09-04 11:01:25 +02:00
Leonora
52a94815c0 Translated using Weblate (Danish)
Currently translated at 17.3% (493 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/da/
2025-09-04 11:01:25 +02:00
Hồ Nhất Duy
6594ac1262 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-09-04 11:01:25 +02:00
Leif-Jöran Olsson
6e34fadcc2 Translated using Weblate (Swedish)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-09-04 11:01:25 +02:00
Leonora
a16955136d Translated using Weblate (Danish)
Currently translated at 8.2% (234 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/da/
2025-09-04 11:01:25 +02:00
Leif-Jöran Olsson
d50c038e07 Translated using Weblate (Swedish)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-09-04 11:01:25 +02:00
T.S
b59bded648 Translated using Weblate (Japanese)
Currently translated at 100.0% (162 of 162 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/ja/
2025-09-04 11:01:24 +02:00
Jeff Huang
3d825c56bf Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-09-04 11:01:24 +02:00
T.S
756b5646f6 Translated using Weblate (Japanese)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/ja/
2025-09-04 11:01:24 +02:00
T.S
640be407cf Translated using Weblate (Japanese)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/ja/
2025-09-04 11:01:24 +02:00
偶尔来巡山
d7948ad0bc Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-09-04 11:01:24 +02:00
T.S
b02cbfce7f Translated using Weblate (Japanese)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-09-04 11:01:24 +02:00
Chocobozzz
59d5f28ed6 Restore scroll position after homepage redirect 2025-09-04 11:00:53 +02:00
Chocobozzz
24a0d7fd00 Faster position scrolling 2025-09-04 06:57:56 +02:00
Chocobozzz
91afa1004e Fill video support on channel sync 2025-09-03 08:46:38 +02:00
Chocobozzz
0882d96624 Do not override privacy for imports and live 2025-09-03 07:13:12 +02:00
Chocobozzz
3ea32ba891 Remove useless help for live transcoding 2025-09-01 09:30:05 +02:00
Chocobozzz
12b4893239 Update translations 2025-08-27 16:59:59 +02:00
Cirnos
aea6983cc4 Translated using Weblate (Portuguese (Brazil))
Currently translated at 87.4% (2483 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-08-27 16:47:38 +02:00
E
65f5bd1c37 Translated using Weblate (Italian)
Currently translated at 89.2% (2536 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/it/
2025-08-27 16:47:38 +02:00
Wuzzy
c5ec42f587 Translated using Weblate (German)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-08-27 16:47:38 +02:00
ButterflyOfFire
741c8f62e0 Translated using Weblate (French (France) (fr_FR))
Currently translated at 99.9% (2839 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-27 16:47:38 +02:00
Weblate
5b1ac25794 Translated using Weblate (French (France) (fr_FR))
Currently translated at 99.9% (2839 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-27 16:47:38 +02:00
Wuzzy
eedcca7879 Translated using Weblate (German)
Currently translated at 100.0% (162 of 162 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/de/
2025-08-27 16:47:38 +02:00
Wuzzy
7f70d7f3f2 Translated using Weblate (German)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/de/
2025-08-27 16:47:38 +02:00
Wuzzy
8447769447 Translated using Weblate (German)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/de/
2025-08-27 16:47:38 +02:00
Fjuro
4d45ca6f09 Translated using Weblate (Czech)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/cs/
2025-08-27 16:47:38 +02:00
Wuzzy
77c3a279f7 Translated using Weblate (German)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-08-27 16:47:38 +02:00
Wuzzy
fde057171d Translated using Weblate (German)
Currently translated at 94.5% (2686 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-08-27 16:47:38 +02:00
Korren-Kerren
6c3d7501e2 Translated using Weblate (Esperanto)
Currently translated at 43.8% (1245 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/eo/
2025-08-27 16:47:38 +02:00
Jeff Huang
1b283c8694 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-08-27 16:47:38 +02:00
Hồ Nhất Duy
401e5c0b07 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (162 of 162 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/vi/
2025-08-27 16:47:38 +02:00
Hồ Nhất Duy
7e1701d9d1 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/vi/
2025-08-27 16:47:37 +02:00
偶尔来巡山
06e5f534ba Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-08-27 16:47:37 +02:00
Hồ Nhất Duy
3ee605b433 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-08-27 16:47:37 +02:00
Leif-Jöran Olsson
bc0132239e Translated using Weblate (Swedish)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-08-27 16:47:37 +02:00
Jiří Podhorecký
796229ac34 Translated using Weblate (Czech)
Currently translated at 90.8% (2580 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-08-27 16:47:37 +02:00
Chocobozzz
3d75a7288f Force to choose a channel to reorder playlists 2025-08-27 16:47:13 +02:00
Chocobozzz
42bf34c29a Fix "Show" button styling 2025-08-27 16:41:54 +02:00
Chocobozzz
d0e810d29a Fix retrying the test 2025-08-26 07:46:57 +02:00
Chocobozzz
b7aa685009 Use a better title 2025-08-25 10:36:26 +02:00
Chocobozzz
cfe49b37ec Fix video title with RSS feed video import 2025-08-25 08:48:03 +02:00
Chocobozzz
f383fe101a Typo 2025-08-25 08:47:40 +02:00
Chocobozzz
7db2817877 Fix RTL margins on some components 2025-08-21 17:16:23 +02:00
Chocobozzz
24dbbbad64 Fix sending emails in production 2025-08-21 11:49:01 +02:00
Chocobozzz
5894c362d6 Bumped to version v7.3.0-rc.1 2025-08-21 10:24:38 +02:00
Chocobozzz
57667734c6 Fix E2E tests 2025-08-21 10:21:17 +02:00
Chocobozzz
8f852e3153 Manage video playlist on thumbnail click 2025-08-20 10:49:08 +02:00
Chocobozzz
aaae2910e7 Save 2025-08-20 09:00:45 +02:00
Chocobozzz
507cedca1c Update translations 2025-08-20 09:00:34 +02:00
chocobozzz
a94128a9ce Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (162 of 162 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/fr_FR/
2025-08-20 08:57:29 +02:00
Marsalis Weatherspoon
d477aa0df6 Translated using Weblate (Spanish)
Currently translated at 100.0% (162 of 162 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/es/
2025-08-20 08:57:29 +02:00
chocobozzz
198192aeb4 Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/fr_FR/
2025-08-20 08:57:29 +02:00
偶尔来巡山
d1b9a88297 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/zh_Hans/
2025-08-20 08:57:29 +02:00
chocobozzz
2ebd9a74f5 Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/fr_FR/
2025-08-20 08:57:29 +02:00
Marsalis Weatherspoon
c2fc1cbbd9 Translated using Weblate (Spanish)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/es/
2025-08-20 08:57:29 +02:00
偶尔来巡山
423633bc2b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-08-20 08:57:29 +02:00
Leif-Jöran Olsson
045409fa35 Translated using Weblate (Swedish)
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-08-20 08:57:29 +02:00
Cirnos
74bb0e58c0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 87.3% (2482 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-08-20 08:57:29 +02:00
Codimp
bf1c1379a2 Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-20 08:57:29 +02:00
chocobozzz
c9eb2e2289 Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (2840 of 2840 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-20 08:57:29 +02:00
Chocobozzz
d090795d0c Fix useless i18n tag 2025-08-20 08:52:39 +02:00
Chocobozzz
6822bcfcb3 Typo 2025-08-20 08:52:30 +02:00
Chocobozzz
9ae1a0177c Update translations 2025-08-19 16:28:15 +02:00
Chocobozzz
c26c2c6007 Merge remote-tracking branch 'weblate/develop' into develop 2025-08-19 16:25:09 +02:00
Alberto
2955824366 Translated using Weblate (Dutch)
Currently translated at 100.0% (162 of 162 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/nl/
2025-08-19 16:24:59 +02:00
Alberto
fac0f0bc1d Translated using Weblate (Dutch)
Currently translated at 84.6% (2379 of 2810 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-08-19 16:24:59 +02:00
chocobozzz
33aaa7f1d1 Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (2810 of 2810 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-19 16:24:58 +02:00
Chocobozzz
2453a82856 Add translation description 2025-08-19 16:13:29 +02:00
Chocobozzz
0967ee953c Add missing $localize 2025-08-19 16:11:47 +02:00
Chocobozzz
a1a6515524 Update translations 2025-08-19 15:55:54 +02:00
Chocobozzz
0dd0198693 Merge remote-tracking branch 'weblate/develop' into develop 2025-08-19 15:53:55 +02:00
Leif-Jöran Olsson
6dcdc680e0 Translated using Weblate (Swedish)
Currently translated at 100.0% (276 of 276 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/sv/
2025-08-19 15:53:51 +02:00
Chocobozzz
8f0389ab8c Typo 2025-08-19 15:53:50 +02:00
Leif-Jöran Olsson
035846578f Translated using Weblate (Swedish)
Currently translated at 100.0% (2811 of 2811 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-08-19 15:53:49 +02:00
chocobozzz
c858dd9982 Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (2811 of 2811 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-19 15:53:48 +02:00
Chocobozzz
789696d22f Update changelog 2025-08-19 11:53:08 +02:00
Chocobozzz
0bb20d7e19 Update translations 2025-08-19 10:45:47 +02:00
Chocobozzz
e3f0beb6cb Merge remote-tracking branch 'weblate/develop' into develop 2025-08-19 10:42:42 +02:00
Cirnos
a383baa812 Translated using Weblate (Portuguese (Brazil))
Currently translated at 87.8% (2464 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-08-19 10:40:36 +02:00
chocobozzz
65f89db861 Translated using Weblate (French (France) (fr_FR))
Currently translated at 91.9% (2579 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-19 10:40:35 +02:00
Chocobozzz
b591f42914 Add "copyrighted" licence 2025-08-19 10:30:42 +02:00
Leif-Jöran Olsson
3ca2fec672 Translated using Weblate (Swedish)
Currently translated at 100.0% (162 of 162 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sv/
2025-08-19 06:14:47 +02:00
Leif-Jöran Olsson
263cd2e3d1 Translated using Weblate (Swedish)
Currently translated at 100.0% (2804 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-08-19 06:14:47 +02:00
Kenner Figueiredo
d7ae2daed1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 87.8% (2462 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-08-19 06:14:46 +02:00
Marius Monnier
667dc856ce Translated using Weblate (French (France) (fr_FR))
Currently translated at 91.9% (2578 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-19 06:14:46 +02:00
rosbeef andino
00b70b84ab Translated using Weblate (French (France) (fr_FR))
Currently translated at 91.9% (2578 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-19 06:14:46 +02:00
Yelena Bonny
748b940dc4 Translated using Weblate (French (France) (fr_FR))
Currently translated at 91.9% (2578 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-19 06:14:45 +02:00
Chocobozzz
6126aed19e Update translations 2025-08-18 09:20:33 +02:00
Ettore Atalan
82b92b497f Translated using Weblate (German)
Currently translated at 93.2% (2615 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-08-16 17:20:00 +02:00
Fjuro
67f495bdac Translated using Weblate (Czech)
Currently translated at 91.9% (2578 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-08-16 17:19:59 +02:00
fran secs
51ecd4c2b0 Translated using Weblate (Catalan)
Currently translated at 100.0% (162 of 162 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/ca/
2025-08-15 11:20:07 +02:00
Wuzzy
3561f25806 Translated using Weblate (German)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/de/
2025-08-15 11:20:07 +02:00
Hồ Nhất Duy
05c4e1c43d Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2804 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-08-15 11:20:06 +02:00
Wuzzy
0c5f88a541 Translated using Weblate (German)
Currently translated at 90.4% (2536 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-08-15 11:20:06 +02:00
fran secs
e631b1d32e Translated using Weblate (Catalan)
Currently translated at 100.0% (2804 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-08-15 11:20:05 +02:00
Marius Monnier
f6c77d1383 Translated using Weblate (French (France) (fr_FR))
Currently translated at 91.0% (2554 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-15 11:20:01 +02:00
偶尔来巡山
3656df036f Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (162 of 162 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/zh_Hans/
2025-08-13 15:30:35 +02:00
Neko Nekowazarashi
bc2b2a6c19 Translated using Weblate (Indonesian)
Currently translated at 34.6% (972 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/id/
2025-08-13 15:30:34 +02:00
Jeff Huang
54f572fbd0 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2804 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-08-13 15:30:32 +02:00
偶尔来巡山
98ccaec295 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2804 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-08-13 15:30:32 +02:00
Oliwier Jaszczyszyn
ce64ee9c5c Translated using Weblate (Polish)
Currently translated at 62.7% (1759 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-08-13 15:30:31 +02:00
Marius Monnier
4222dd6686 Translated using Weblate (French (France) (fr_FR))
Currently translated at 90.2% (2531 of 2804 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-13 15:30:29 +02:00
Chocobozzz
d7ffde7299 Merge remote-tracking branch 'weblate/develop' into develop 2025-08-12 12:02:09 +02:00
chocobozzz
bcb012977c Translated using Weblate (Polish)
Currently translated at 59.8% (1662 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-08-12 12:02:04 +02:00
Chocobozzz
18d05d3a40 Update translations 2025-08-12 11:53:56 +02:00
Korren-Kerren
5a87e008e5 Translated using Weblate (Esperanto)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/eo/
2025-08-12 11:42:45 +02:00
Neko Nekowazarashi
c5f854164c Translated using Weblate (Indonesian)
Currently translated at 24.6% (684 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/id/
2025-08-12 11:42:45 +02:00
Korren-Kerren
d301a9f3ae Translated using Weblate (Esperanto)
Currently translated at 43.7% (1215 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/eo/
2025-08-12 11:42:44 +02:00
alex gabilondo
fd0fc9a5f9 Translated using Weblate (Basque)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/eu/
2025-08-11 17:38:57 +02:00
Fjuro
264558e2ca Translated using Weblate (Czech)
Currently translated at 90.5% (2515 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-08-11 17:38:57 +02:00
alex gabilondo
92a4123f25 Translated using Weblate (Basque)
Currently translated at 72.8% (2023 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/eu/
2025-08-11 17:38:57 +02:00
Hồ Nhất Duy
5926787861 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/vi/
2025-08-11 17:38:57 +02:00
Hồ Nhất Duy
8d262d01b2 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/vi/
2025-08-11 17:38:57 +02:00
Hồ Nhất Duy
ae9a802403 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2776 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-08-11 17:38:57 +02:00
fran secs
4fd2cdb390 Translated using Weblate (Catalan)
Currently translated at 100.0% (2776 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-08-11 17:38:57 +02:00
fran secs
3edb4b75ee Translated using Weblate (Catalan)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/ca/
2025-08-11 17:38:57 +02:00
Neko Nekowazarashi
59adaaad69 Translated using Weblate (Indonesian)
Currently translated at 23.3% (648 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/id/
2025-08-11 17:38:57 +02:00
Александр
82815624b4 Translated using Weblate (Russian)
Currently translated at 82.6% (2294 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ru/
2025-08-11 17:38:57 +02:00
fran secs
1496961c53 Translated using Weblate (Catalan)
Currently translated at 91.4% (2539 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-08-11 17:38:57 +02:00
偶尔来巡山
18b22257a8 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/zh_Hans/
2025-08-11 17:38:57 +02:00
chocobozzz
bc1a7d0873 Translated using Weblate (French (France) (fr_FR))
Currently translated at 87.6% (2434 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-11 17:38:57 +02:00
chocobozzz
bd6eb388f8 Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/fr_FR/
2025-08-11 17:38:57 +02:00
DeepL
71c832f6b2 Translated using Weblate (French (France) (fr_FR))
Currently translated at 87.1% (2418 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-11 17:38:57 +02:00
Fabián León
f3f77f596e Translated using Weblate (Spanish)
Currently translated at 77.9% (2164 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-08-11 17:38:57 +02:00
Denis Dupont
ef690bc792 Translated using Weblate (Esperanto)
Currently translated at 43.7% (1214 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/eo/
2025-08-11 17:38:57 +02:00
dxuser514
ad41b6c06e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/zh_Hans/
2025-08-11 17:38:57 +02:00
偶尔来巡山
e10ed4f5ed Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/zh_Hans/
2025-08-11 17:38:57 +02:00
dxuser514
15867684f5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/zh_Hans/
2025-08-11 17:38:57 +02:00
chocobozzz
57a8e18022 Translated using Weblate (French (France) (fr_FR))
Currently translated at 87.1% (2418 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-08-11 17:38:56 +02:00
Oliwier Jaszczyszyn
19ec133abb Translated using Weblate (Polish)
Currently translated at 59.8% (1662 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-08-11 17:38:56 +02:00
Ettore Atalan
f5d6097980 Translated using Weblate (German)
Currently translated at 88.1% (2446 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-08-11 17:38:56 +02:00
偶尔来巡山
93f5a7d789 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/zh_Hans/
2025-08-11 17:38:56 +02:00
Leif-Jöran Olsson
afc1f0e6b0 Translated using Weblate (Swedish)
Currently translated at 100.0% (160 of 160 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/sv/
2025-08-11 17:38:56 +02:00
Jeff Huang
adfa6b43ad Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2776 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-08-11 17:38:56 +02:00
偶尔来巡山
06fd09b93a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2776 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-08-11 17:38:56 +02:00
Leif-Jöran Olsson
9d9607feff Translated using Weblate (Swedish)
Currently translated at 100.0% (2776 of 2776 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-08-11 17:38:56 +02:00
Chocobozzz
d1a35e8421 Disable nginx buffering on upload endpoints
To prevent timeout requests in peertube HTTP server
2025-08-11 17:38:22 +02:00
Chocobozzz
da23ad1d09 Add ability for admin to configure request timeout
AFAIK we can't set a specific timeout on a specific route/request, so
the admin must set it globally
2025-08-11 16:55:37 +02:00
Chocobozzz
b4df49b87f Fix fetching latest elements of a playlist 2025-08-11 14:52:09 +02:00
Chocobozzz
6fce7c808c Fix disabling wait transcoding 2025-08-11 14:15:59 +02:00
Chocobozzz
89360a4ef0 Update node 20 minimum version
To support importing ESM modules in plugins
2025-08-11 11:06:22 +02:00
Chocobozzz
acaabaace1 Compat with openid plugin 1.0.2 2025-08-11 10:46:27 +02:00
Chocobozzz
e763ad3036 Fix external login error message 2025-08-08 14:17:20 +02:00
Chocobozzz
b44dfef3f9 Add more openid tests 2025-08-08 14:17:20 +02:00
Chocobozzz
9619c2ea7d Add packagemanager field if using corepack 2025-08-08 14:16:50 +02:00
Chocobozzz
83f74169da Add official openid plugin tests 2025-08-08 14:16:49 +02:00
Jakob Meier
fc986076c9 Allow auth plugins to redirect to external url (#7179)
* Allow auth plugins to redirect to external url

Add a new optional field to `RegisterServerExternalAuthenticatedResult`,
the object passed to the `userAuthenticated` callback used by auth plugins.

The server code uses this to redirect to an external website if it is set.

Left TODO:

- This code has been tested manually but a test case is still missing.
- Here or in the plugin, the redirect urls must be limited to values configurable by admins.

* rename to URI for consistency

* add test for the new parameter

* address review comments

- correct syntax for optional parameter
- handle the case where `externalAuthToken` has query parameters included
2025-08-07 14:59:19 +02:00
Bojidar Marinov
8c9b4abe45 Add Scheduled Lives functionality (#7144)
* Add Scheduled Lives functionality through originallyPublishedAt

Implements #6604 by reusing the originallyPublishedAt field of isLive videos to mark "waiting for live" videos as scheduled at a set time.

* Hide scheduled lives from Browse Videos page

* Add tests for Scheduled Live videos

* Make scheduled lives use a dedicated scheduledAt field in the VideoLive table

* Plan live schedules to evolve in the future

 * Use a dedicated table to store live schedules, so we can add multiple
   schedules in the future and also add a title, description etc. for a
   specific schedule
 * Adapt REST API to use an array to store/get live schedules
 * Add REST API param so it's the client choice to include or not
   scheduled lives
 * Export schedules info in user import/export

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-08-01 15:06:27 +02:00
Chocobozzz
a5c087d3d4 Reapply "Upgrade webfinger lib to 2.8.1"
This reverts commit 04245f9dc1.
2025-07-31 10:10:59 +02:00
Chocobozzz
04245f9dc1 Revert "Upgrade webfinger lib to 2.8.1"
This reverts commit 1967546cab.
Another bug that must be fixed first: https://github.com/silverbucket/webfinger.js/issues/116
2025-07-30 14:25:35 +02:00
Chocobozzz
9af56c26bc Fix openapi missing param 2025-07-30 11:52:54 +02:00
Chocobozzz
1967546cab Upgrade webfinger lib to 2.8.1 2025-07-30 11:49:00 +02:00
Chocobozzz
bd337df442 Prefer "More" instead of "Settings" 2025-07-30 11:42:53 +02:00
Chocobozzz
57caf25611 Add ability to list and revoke token sessions 2025-07-30 11:42:49 +02:00
Chocobozzz
a53ed039b8 Prevent metric warning for redundancy gauge 2025-07-29 14:31:26 +02:00
Chocobozzz
1289d645d8 Revert webfinger changes
We can re-apply them when we'll upgrade to 2.8.x, but we need https://github.com/silverbucket/webfinger.js/issues/106 to be fixed first
2025-07-29 14:18:56 +02:00
Chocobozzz
f19954414f Fix tests build 2025-07-29 12:11:17 +02:00
Chocobozzz
1c5101a22b Update dependencies and version 2025-07-29 11:48:44 +02:00
Chocobozzz
94802f3175 Update dependencies 2025-07-29 11:48:19 +02:00
Chocobozzz
3e1cdb9fa2 Add runner version info 2025-07-29 10:30:33 +02:00
Chocobozzz
309068ae1d Save 2025-07-29 09:46:33 +02:00
Chocobozzz
17247f205f Also add stall job check for studio 2025-07-29 09:36:51 +02:00
Ankit lal
cdb861a26a Add WatchDog for stalled Transcription jobs 2025-07-29 09:36:51 +02:00
Chocobozzz
37e13bbcd2 Add 2FA info in admin 2025-07-28 17:13:00 +02:00
Chocobozzz
c9905ecd3a Add ability to set square icon in welcome wizard 2025-07-28 17:03:17 +02:00
Chocobozzz
37da276f9c Prevent URL change on default route
With custom scope/sort
2025-07-28 10:50:30 +02:00
Chocobozzz
e0eebb1c7e Improve config descriptions 2025-07-28 10:50:10 +02:00
Chocobozzz
06d9c7a13d More robust checkLiveSegmentHash 2025-07-28 09:46:56 +02:00
Chocobozzz
121d9029b9 Add rcf and gcr video languages 2025-07-28 09:22:15 +02:00
Chocobozzz
13bceb5f40 Better thumbnail error handling
* Had to upgrade to es2022 to use `cause` error
 * Had to declare class attributes with declare for sequelize models, so
   it still works as before
2025-07-25 17:01:36 +02:00
Chocobozzz
29a88c0dde Improve audio transcoding
ffmpeg aac encoder is not very good so prefer to keep the same bitrate
as mp3
we also use the max available bitrate with a flac input that has an
unknown bitrate
2025-07-24 16:49:28 +02:00
Chocobozzz
445866967f Fix table sort 2025-07-24 16:47:34 +02:00
Chocobozzz
2612112c63 Update translations 2025-07-24 15:18:19 +02:00
Chocobozzz
d46ca9b53a Fix broken translation 2025-07-24 15:08:13 +02:00
chocobozzz
924b2cb614 Translated using Weblate (French (France) (fr_FR))
Currently translated at 100.0% (158 of 158 strings)

Translation: PeerTube/server-internal
Translate-URL: https://weblate.framasoft.org/projects/peertube/server-internal/fr_FR/
2025-07-24 14:49:47 +02:00
Oliwier Jaszczyszyn
3f3bb74f99 Translated using Weblate (Polish)
Currently translated at 57.1% (1581 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-07-24 14:49:46 +02:00
Abrarul Hasan
8cb0062bb7 Translated using Weblate (Bengali)
Currently translated at 4.2% (119 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/bn/
2025-07-24 09:58:45 +02:00
Abrarul Hasan
54ef9b308f Translated using Weblate (Bengali)
Currently translated at 100.0% (265 of 265 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/bn/
2025-07-24 09:58:45 +02:00
Oliwier Jaszczyszyn
29506af46b Translated using Weblate (Polish)
Currently translated at 52.0% (1442 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-07-24 09:58:45 +02:00
Paolo Mauri
dcf3eb95a5 Translated using Weblate (Italian)
Currently translated at 87.7% (2430 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/it/
2025-07-24 09:58:45 +02:00
Ghost of Sparta
7a7f7b5dab Translated using Weblate (Hungarian)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/hu/
2025-07-24 09:58:45 +02:00
Paolo Mauri
1638b6c22d Translated using Weblate (Italian)
Currently translated at 87.7% (2430 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/it/
2025-07-24 09:58:45 +02:00
Fjuro
aa94ea8dd9 Translated using Weblate (Czech)
Currently translated at 90.4% (2505 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-07-24 09:58:45 +02:00
chocobozzz
06b9252b64 Translated using Weblate (French (France) (fr_FR))
Currently translated at 87.4% (2420 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-07-24 09:58:45 +02:00
Snue
d82b737133 Translated using Weblate (Danish)
Currently translated at 4.0% (113 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/da/
2025-07-24 09:58:45 +02:00
fran secs
07e3ce416a Translated using Weblate (Catalan)
Currently translated at 90.8% (2515 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-07-24 09:58:45 +02:00
fran secs
7586210cb8 Translated using Weblate (Catalan)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/ca/
2025-07-24 09:58:45 +02:00
Paolo Mauri
cb736664b8 Translated using Weblate (Italian)
Currently translated at 87.7% (2430 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/it/
2025-07-24 09:58:45 +02:00
alex gabilondo
459e40762a Translated using Weblate (Basque)
Currently translated at 73.1% (2026 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/eu/
2025-07-24 09:58:45 +02:00
偶尔来巡山
78bc2482fd Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2768 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-07-24 09:58:44 +02:00
Milo Ivir
57ebcba34c Translated using Weblate (Croatian)
Currently translated at 80.2% (2220 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hr/
2025-07-24 09:58:44 +02:00
Milo Ivir
382ecf4d73 Translated using Weblate (Croatian)
Currently translated at 100.0% (158 of 158 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/hr/
2025-07-24 09:58:44 +02:00
Milo Ivir
84968a3c02 Translated using Weblate (Croatian)
Currently translated at 80.0% (2216 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hr/
2025-07-24 09:58:44 +02:00
Milo Ivir
165d956fb5 Translated using Weblate (Croatian)
Currently translated at 100.0% (158 of 158 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/hr/
2025-07-24 09:58:44 +02:00
Jeff Huang
09596e3b56 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2768 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-07-24 09:58:44 +02:00
Leif-Jöran Olsson
89eed6ca11 Translated using Weblate (Swedish)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/sv/
2025-07-24 09:58:44 +02:00
Leif-Jöran Olsson
222e0fc635 Translated using Weblate (Swedish)
Currently translated at 100.0% (2768 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-07-24 09:58:44 +02:00
Александр
4cf831573a Translated using Weblate (Russian)
Currently translated at 82.8% (2292 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ru/
2025-07-24 09:58:44 +02:00
偶尔来巡山
c2365a945e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/zh_Hans/
2025-07-24 09:58:44 +02:00
Fjuro
cebbf9173d Translated using Weblate (Czech)
Currently translated at 100.0% (159 of 159 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/cs/
2025-07-24 09:58:44 +02:00
偶尔来巡山
8fc5a1aba5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2768 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-07-24 09:58:44 +02:00
Hồ Nhất Duy
fe3dbf5ec9 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2768 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-07-24 09:58:44 +02:00
T.S
3744ca473f Translated using Weblate (Japanese)
Currently translated at 90.5% (2507 of 2768 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-07-24 09:58:43 +02:00
Chocobozzz
d6e4dac032 Add email translations
Convert emails from Pug template to Handlebars because i18next doesn't
support Pug
2025-07-24 09:18:04 +02:00
Chocobozzz
b45fbf4337 Fix import tests 2025-07-22 16:43:38 +02:00
Chocobozzz
eadbf4e001 Merge branch 'release/7.2.0' into develop 2025-07-22 11:01:12 +02:00
Chocobozzz
3fd439839d Bumped to version v7.2.3 2025-07-22 10:52:43 +02:00
Chocobozzz
4109f157c0 Update changelog 2025-07-22 10:52:01 +02:00
Chocobozzz
189d846ab8 Fix duplicates when syncing a channel 2025-07-22 09:35:25 +02:00
Chocobozzz
d8368b86e6 Upgrade multer 2025-07-22 08:39:21 +02:00
Chocobozzz
e9af88b332 Update upgrade config documentation 2025-07-21 09:22:39 +02:00
Chocobozzz
32fbe20b13 Update CLI version 2025-07-18 09:14:51 +02:00
Chocobozzz
2790ec5aaa Fix choosing the licence in admin 2025-07-17 11:12:08 +02:00
Chocobozzz
8f4ba03550 Fix remote actor follow count after subscription 2025-07-17 11:09:26 +02:00
Chocobozzz
a02704a7a4 Fix table overflow 2025-07-16 17:13:20 +02:00
Chocobozzz
cd8573d79e Fix release script 2025-07-16 15:10:39 +02:00
Chocobozzz
e399515941 Add missing fields in openapi 2025-07-16 14:58:38 +02:00
Chocobozzz
a60eeeff60 Merge branch 'release/7.2.0' into develop 2025-07-16 13:39:11 +02:00
Chocobozzz
3a93b3154c Bumped to version v7.2.2 2025-07-16 13:11:29 +02:00
Chocobozzz
aa5687ca77 Update changelog 2025-07-16 13:11:02 +02:00
Chocobozzz
c6ffcb7ce4 Fix caption raw edition when editing segment 2025-07-16 12:05:51 +02:00
Chocobozzz
b4d7bd49e0 Fix channel sync duplicate after video deletion 2025-07-16 10:48:21 +02:00
Chocobozzz
4233b20451 Update translations 2025-07-11 10:59:10 +02:00
Chocobozzz
c52f4b4d48 Merge remote-tracking branch 'weblate/develop' into develop 2025-07-11 10:56:36 +02:00
Chocobozzz
db7c5d8a0e Merge branch 'release/7.2.0' into develop 2025-07-11 10:56:19 +02:00
Chocobozzz
b4d3b175dc Fix input search with multiple prefix tokens 2025-07-11 10:55:53 +02:00
Chocobozzz
76aa084fd5 Update credits 2025-07-11 10:34:34 +02:00
Chocobozzz
51d5a523ea Better radius config UX 2025-07-11 10:30:10 +02:00
Chocobozzz
17eb4dc74f Add missing ":" 2025-07-11 10:03:54 +02:00
Jeff Huang
622babd39e Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2761 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-07-11 06:01:04 +02:00
Hồ Nhất Duy
b6cd911bc2 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2761 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-07-11 06:01:04 +02:00
Jeff Huang
e8a1d94ac2 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 98.9% (2732 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-07-10 15:36:32 +02:00
Leif-Jöran Olsson
4df35a65e2 Translated using Weblate (Swedish)
Currently translated at 100.0% (2761 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-07-10 15:36:32 +02:00
Jeff Huang
0689fc7d87 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 93.6% (2587 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-07-10 15:36:32 +02:00
偶尔来巡山
ce73fefa84 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2761 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-07-10 15:36:32 +02:00
Leif-Jöran Olsson
d462d354f9 Translated using Weblate (Swedish)
Currently translated at 95.8% (2647 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-07-10 15:36:32 +02:00
Александр
5c73deed31 Translated using Weblate (Russian)
Currently translated at 82.7% (2284 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ru/
2025-07-10 15:36:32 +02:00
偶尔来巡山
fe413000f4 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2761 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-07-10 15:36:32 +02:00
Hasan Yıldız
d1b15d4f3c Translated using Weblate (Turkish)
Currently translated at 84.4% (2331 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/tr/
2025-07-10 15:36:32 +02:00
Jeff Huang
eeaec6d9a2 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 93.2% (2575 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-07-10 15:36:32 +02:00
Hồ Nhất Duy
4a44c774d8 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2761 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-07-10 15:36:32 +02:00
Leif-Jöran Olsson
10f2497c82 Translated using Weblate (Swedish)
Currently translated at 93.3% (2577 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-07-10 15:36:32 +02:00
Paolo Mauri
3f032d24af Translated using Weblate (Italian)
Currently translated at 87.7% (2424 of 2761 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/it/
2025-07-10 15:36:31 +02:00
Chocobozzz
015a324fad Merge branch 'release/7.2.0' into develop 2025-07-10 15:36:20 +02:00
Chocobozzz
7501394036 Fix selecting a frame on Safari 2025-07-10 15:21:27 +02:00
Chocobozzz
02b1d137ba Update hls.js
Should fix a media error with chrome 138

See https://github.com/Chocobozzz/PeerTube/issues/7146
2025-07-10 14:54:20 +02:00
Bojidar Marinov
45dbdb13c8 Fix scroll position not being preserved when pages load slowly (#7143) 2025-07-09 16:57:40 +02:00
Chocobozzz
d8de2f3ff9 Fix account playlists fetch 2025-07-09 15:37:45 +02:00
Chocobozzz
ee96cf3a19 Improve NSFW warning in player 2025-07-09 15:32:57 +02:00
Chocobozzz
f2556d80e3 Prevent loading web video poster that can be NSFW 2025-07-09 15:05:41 +02:00
Chocobozzz
1a9ef4ceaa Better discover page navigation 2025-07-09 10:28:22 +02:00
Chocobozzz
d3863d3a9a Adapt login message if upload is not allowed 2025-07-09 10:11:15 +02:00
Chocobozzz
037197a7e9 Merge branch 'release/7.2.0' into develop 2025-07-08 16:46:46 +02:00
Chocobozzz
56b8bff325 Convert video short uuid to uuid 2025-07-08 16:40:27 +02:00
Chocobozzz
3f4c267ec9 Add player strings to translate 2025-07-08 15:47:26 +02:00
Chocobozzz
faeacaec68 Fix menu focus 2025-07-08 15:31:54 +02:00
Chocobozzz
27f1976929 Add missing aria-controls attribute 2025-07-08 15:02:21 +02:00
Chocobozzz
2011ea37e6 Fix settings menu arrow left/right navigation 2025-07-08 14:53:38 +02:00
Chocobozzz
91002ac042 Fix settings menu escape key 2025-07-08 11:07:18 +02:00
Chocobozzz
c958f6271f Fix P2P player info accessibility 2025-07-08 09:47:07 +02:00
Chocobozzz
d2064d873b Fix dock accessibility 2025-07-08 09:32:11 +02:00
Chocobozzz
b0d5a6776b Remove reference to openapi generator
OpenAPI generation crashes so we had to remove them
2025-07-08 08:26:00 +02:00
Chocobozzz
49da883f7e More reliable config wizard fragment detection 2025-07-07 10:37:55 +02:00
Chocobozzz
e1b543bfa0 Fix pagination label in tables 2025-07-07 10:07:25 +02:00
Chocobozzz
65ae21436a Update translations 2025-07-07 09:06:46 +02:00
alex gabilondo
81f04543e5 Translated using Weblate (Basque)
Currently translated at 81.0% (2110 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/eu/
2025-07-06 14:25:48 +02:00
Paolo Mauri
1dfc3a3b74 Translated using Weblate (Italian)
Currently translated at 95.7% (2492 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/it/
2025-07-06 14:25:48 +02:00
Paolo Mauri
242e9ad983 Translated using Weblate (Italian)
Currently translated at 94.0% (2446 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/it/
2025-07-06 14:25:48 +02:00
Hồ Nhất Duy
754b60cfe1 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (155 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/vi/
2025-07-06 14:25:48 +02:00
Hồ Nhất Duy
175f065811 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2602 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-07-06 14:25:47 +02:00
Paolo Mauri
62d58a86fa Translated using Weblate (Italian)
Currently translated at 93.4% (2431 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/it/
2025-07-06 14:25:47 +02:00
Casper Ruttten
50a66c6843 Translated using Weblate (Dutch)
Currently translated at 95.2% (2478 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nl/
2025-07-06 14:25:47 +02:00
Ghost of Sparta
81b8706524 Translated using Weblate (Hungarian)
Currently translated at 100.0% (155 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/hu/
2025-07-06 14:25:47 +02:00
Hồ Nhất Duy
4739e367a6 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2602 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-07-06 14:25:47 +02:00
Fjuro
fe1448fa19 Translated using Weblate (Czech)
Currently translated at 100.0% (2602 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-07-06 14:25:47 +02:00
Booteille
11eea4731e Translated using Weblate (French (France) (fr_FR))
Currently translated at 96.6% (2515 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-07-06 14:25:47 +02:00
Booteille
d2a5d4d25d Translated using Weblate (French (France) (fr_FR))
Currently translated at 89.4% (2328 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-07-06 14:25:47 +02:00
Ihor Hordiichuk
7fcdae56ac Translated using Weblate (Ukrainian)
Currently translated at 74.0% (1926 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/uk/
2025-07-06 14:25:47 +02:00
T.S
66bcbaf21c Translated using Weblate (Japanese)
Currently translated at 100.0% (2602 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-07-06 14:25:47 +02:00
Thomas Citharel
57472ed255 Translated using Weblate (French (France) (fr_FR))
Currently translated at 89.4% (2328 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-07-06 14:25:47 +02:00
Booteille
30656ae18f Translated using Weblate (French (France) (fr_FR))
Currently translated at 89.4% (2328 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-07-06 14:25:47 +02:00
Chocobozzz
0adafa0fc0 Add ability to order playlists 2025-07-06 13:05:01 +02:00
Chocobozzz
546bd42240 Fix tests 2025-07-02 09:50:41 +02:00
Chocobozzz
532020e2af Styling
Also prefer "0" instead of "none" because outerHTML converts the later
to "medium" (I don't know why)
2025-06-27 11:01:18 +02:00
Chocobozzz
70010fac73 NSFW policy consistency even for the owner of the video 2025-06-27 10:42:27 +02:00
Chocobozzz
ed8f96354f Play/pause using "k" 2025-06-27 10:37:34 +02:00
Shalabh Agarwal
4323ffbb4e update allowfullscreen property 2025-06-27 10:24:35 +02:00
Lety Does Stuff
ff400224c2 Fix lint 2025-06-27 10:20:54 +02:00
Lety Does Stuff
1bdd0a8299 Fix thumbnail corner coloring 2025-06-27 10:20:54 +02:00
Lety Does Stuff
94046baaf0 Use SVG filter for thumbnail blurs 2025-06-27 10:20:54 +02:00
Chocobozzz
6c85bbf852 Prefer og:image for opengraph
See https://github.com/Chocobozzz/PeerTube/issues/7109
2025-06-27 10:00:51 +02:00
Chocobozzz
53472daa07 Merge branch 'release/7.2.0' into develop 2025-06-27 09:53:31 +02:00
Chocobozzz
a02aec578c Fix follow card overflow 2025-06-27 09:29:45 +02:00
Chocobozzz
2266bcabb9 Fix lint 2025-06-27 09:28:37 +02:00
Chocobozzz
684fb57019 Fix upload tab title when the file is uplodaded 2025-06-27 09:22:41 +02:00
Chocobozzz
013d413841 Reset filters when loading query params 2025-06-27 09:17:12 +02:00
Chocobozzz
379387f56f Fix broken video state on move failure
Also add a --force option to move files even if the state is broken
2025-06-27 09:03:35 +02:00
Chocobozzz
de884c6721 Fix migration version 2025-06-26 15:23:18 +02:00
Chocobozzz
3fbaae8ac2 Merge branch 'release/7.2.0' into develop 2025-06-26 09:13:56 +02:00
Chocobozzz
86e857e969 Fix lint 2025-06-26 09:10:55 +02:00
Chocobozzz
9373f571be Relax transaction level
We don't need serializable level
2025-06-24 16:20:51 +02:00
Chocobozzz
bbe4910247 More robust ACL error handler 2025-06-24 16:02:39 +02:00
Chocobozzz
5b887a77ae Simplify s3 error log 2025-06-24 15:57:06 +02:00
Chocobozzz
6b0ae9f082 Fix pip button z-index on firefox 2025-06-24 15:33:58 +02:00
Chocobozzz
83c1c5943e Keep playlist name original casing 2025-06-24 09:25:56 +02:00
Chocobozzz
208b29799a Correctly display bulk actions button in my videos 2025-06-24 09:20:37 +02:00
Chocobozzz
c0f4de6077 Add ability to customize instance logo 2025-06-24 06:38:29 +02:00
Chocobozzz
f5fd593976 Add ability for admins to refuse remote comments 2025-06-18 10:05:46 +02:00
Chocobozzz
031b61c466 Add ability to disable channel followers 2025-06-18 06:40:19 +02:00
Chocobozzz
ce28c64750 Support variable in email subject/signature 2025-06-18 06:40:19 +02:00
Chocobozzz
614d906ca6 Use raw URL for attributed to 2025-06-18 06:40:19 +02:00
Chocobozzz
0c7a89a70a Put ap:public in cc for unlisted data 2025-06-18 06:40:19 +02:00
Chocobozzz
24b59a2560 Remember table pagination 2025-06-18 06:40:19 +02:00
Chocobozzz
e9bb222b6c Add defaults values config in web admin 2025-06-18 06:40:19 +02:00
Chocobozzz
eb11e5793f Add admin config wizard 2025-06-18 06:40:19 +02:00
Chocobozzz
a6b89bde2b Redesign admin config and add theme customization 2025-06-18 06:40:19 +02:00
Chocobozzz
03425e10d3 Refactor primeng table 2025-06-18 06:40:18 +02:00
Chocobozzz
069f5d019b Upgrade to primeng 19 2025-06-18 06:40:18 +02:00
Lety Does Stuff
cbce8580d2 Update moderation wording 2025-06-18 06:40:12 +02:00
Lety Does Stuff
d964b71e93 Remove unused button from the contact form 2025-06-18 06:37:17 +02:00
Chocobozzz
e0b7cf6592 Remove deprecated non standard DNT support 2025-06-17 08:14:15 +02:00
Chocobozzz
5bceb37150 Bumped to version v7.2.1 2025-06-16 10:06:37 +02:00
Chocobozzz
a840060b19 Update changelog 2025-06-16 09:47:01 +02:00
Chocobozzz
1d6bdd1bab Update translations 2025-06-16 09:33:38 +02:00
Chocobozzz
a2a93b2c0f Merge remote-tracking branch 'weblate/develop' into develop 2025-06-16 09:31:29 +02:00
Chocobozzz
1d2b3ed4a2 Correctly load count and rows per page 2025-06-16 09:30:16 +02:00
GunChleoc
73416ebb42 Translated using Weblate (Gaelic)
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/gd/
2025-06-16 08:35:35 +02:00
fran secs
a7759d627c Translated using Weblate (Catalan)
Currently translated at 100.0% (2602 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-06-16 08:35:35 +02:00
Booteille
9d3f7aadbb Translated using Weblate (French (France) (fr_FR))
Currently translated at 89.3% (2325 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-06-16 08:35:35 +02:00
Leif-Jöran Olsson
854c779ab1 Translated using Weblate (Swedish)
Currently translated at 100.0% (2602 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-06-16 08:35:34 +02:00
Jeff Huang
7090edbd4e Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2602 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-06-16 08:35:34 +02:00
偶尔来巡山
5a2d571ed1 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2602 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-06-16 08:35:34 +02:00
Leif-Jöran Olsson
fe5ae394c6 Translated using Weblate (Swedish)
Currently translated at 100.0% (2602 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-06-16 08:35:34 +02:00
T.S
a5dcfaa36c Translated using Weblate (Japanese)
Currently translated at 100.0% (2602 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-06-16 08:35:34 +02:00
John Livingston
872f7bb370 Translated using Weblate (French (France) (fr_FR))
Currently translated at 88.5% (2303 of 2602 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-06-16 08:35:34 +02:00
Chocobozzz
9ca0d0739b Add missing channelId param 2025-06-16 08:34:25 +02:00
Chocobozzz
faa69acafe Don't display description/terms if empty 2025-06-13 11:00:21 +02:00
Chocobozzz
ccbd59713d Fix parent menu link highlight 2025-06-13 11:00:21 +02:00
Chocobozzz
1651498e0b Fix browse videos page title 2025-06-13 11:00:20 +02:00
Chocobozzz
7b62d5e8a9 Fix add new playlist broken style 2025-06-13 09:14:56 +02:00
Chocobozzz
9c3e8cd681 Fix support field not filled on publish 2025-06-10 10:18:15 +02:00
Chocobozzz
83b84fdb50 Update translations 2025-06-10 10:05:56 +02:00
Chocobozzz
66eb97d6a4 Merge remote-tracking branch 'weblate/develop' into release/7.2.0 2025-06-10 10:03:36 +02:00
Chocobozzz
11f769eade Do not uppercase tags
See https://github.com/Chocobozzz/PeerTube/issues/7076
2025-06-10 10:02:58 +02:00
Chocobozzz
aba91228de Fix plural form 2025-06-10 09:44:34 +02:00
Chocobozzz
a8df4ccbbe Upgrade multer 2025-06-10 09:44:34 +02:00
Chocobozzz
9fbfb76985 Add scp command to release script 2025-06-10 09:44:33 +02:00
Jackson
4ab22c7187 fix mismatching sql backup path and database name 2025-06-10 09:44:20 +02:00
Alessandro Molina
f19d34aa63 Fix invalid error when summary is undefined 2025-06-10 08:24:43 +02:00
GunChleoc
abf625fc96 Translated using Weblate (Gaelic)
Currently translated at 100.0% (155 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/gd/
2025-06-09 08:55:47 +02:00
Ettore Atalan
1973e08342 Translated using Weblate (German)
Currently translated at 100.0% (155 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/de/
2025-06-09 08:55:47 +02:00
GunChleoc
14cdf72944 Translated using Weblate (Gaelic)
Currently translated at 76.4% (1988 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/gd/
2025-06-09 08:55:46 +02:00
Ettore Atalan
afe730f945 Translated using Weblate (German)
Currently translated at 94.0% (2445 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-06-09 08:55:46 +02:00
偶尔来巡山
7a4efa23a4 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-06-04 15:18:49 +02:00
Chocobozzz
03e46572a3 Fix typo 2025-06-04 15:18:35 +02:00
Chocobozzz
c43ff33483 Bumped to version v7.2.0 2025-06-04 15:01:34 +02:00
Chocobozzz
181582060b Update changelog 2025-06-04 14:51:53 +02:00
Chocobozzz
d83931c145 Display comments column 2025-06-04 09:55:33 +02:00
Chocobozzz
e90d194c6e Update translations 2025-06-03 14:32:30 +02:00
dxuser514
ef437b3874 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-06-03 13:54:59 +02:00
Hồ Nhất Duy
3791f73977 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-06-03 13:54:59 +02:00
Chocobozzz
c0c83f334c Fix displaying images in support modal 2025-06-03 13:54:32 +02:00
Chocobozzz
6e8a473c5f Update changelog 2025-06-03 10:39:06 +02:00
Chocobozzz
9f4ea1cf1d Update translations 2025-06-02 10:23:33 +02:00
Jeff Huang
bcf6c5ec19 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-06-02 10:16:19 +02:00
Hồ Nhất Duy
72ffbcc8ea Translated using Weblate (Vietnamese)
Currently translated at 99.9% (2600 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-05-31 17:31:20 +02:00
Besnik Bleta
692f3e0b2d Translated using Weblate (Albanian)
Currently translated at 100.0% (272 of 272 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/sq/
2025-05-31 11:13:19 +02:00
T.S
e403af6e99 Translated using Weblate (Japanese)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-05-31 05:08:30 +02:00
Fjuro
069af38f02 Translated using Weblate (Czech)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-31 05:08:29 +02:00
Denis Dupont
c03998f827 Translated using Weblate (Esperanto)
Currently translated at 99.3% (154 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/eo/
2025-05-30 19:23:03 +02:00
Chocobozzz
7e52aeaddc More robust move video on failure 2025-05-30 16:55:22 +02:00
Chocobozzz
1d2b783b93 Prevent decreasing too much jobs info 2025-05-30 16:32:35 +02:00
Chocobozzz
e69cb0507d Fix replace file on not available video source 2025-05-30 15:39:21 +02:00
Chocobozzz
39c48888ca Add object storage env variable example 2025-05-30 15:36:17 +02:00
Chocobozzz
944240e442 Update theme guide 2025-05-30 15:25:13 +02:00
Chocobozzz
d1bb28374b Fix theme crash in embed 2025-05-30 15:02:45 +02:00
Chocobozzz
f85e1a57d4 Format xliff files 2025-05-30 14:31:25 +02:00
Chocobozzz
af859056da Remove reference to zanata 2025-05-30 14:11:02 +02:00
Chocobozzz
f07071ea7b Typo 2025-05-30 13:47:24 +02:00
Chocobozzz
200c5eb463 Fix lint 2025-05-30 13:26:11 +02:00
Chocobozzz
c817c2839d XML consistency 2025-05-30 13:21:18 +02:00
Chocobozzz
288b0f43a1 Update all angular translation files 2025-05-30 11:00:06 +02:00
Chocobozzz
00b2940315 Merge remote-tracking branch 'weblate/develop' into develop 2025-05-30 10:50:57 +02:00
Chocobozzz
571334eb02 Update all player/server translation files 2025-05-30 10:50:43 +02:00
chocobozzz
8d9d0fccb4 Deleted translation using Weblate (English (Ireland)) 2025-05-30 10:40:05 +02:00
chocobozzz
85caaf2fb3 Added translation using Weblate (English (Ireland)) 2025-05-30 10:39:00 +02:00
Chocobozzz
d84c65e90e Update translations 2025-05-30 09:59:38 +02:00
chocobozzz
0afdeb80d3 Deleted translation using Weblate (English (United Kingdom)) 2025-05-30 09:56:47 +02:00
chocobozzz
3a16f2da63 Deleted translation using Weblate (English (United Kingdom)) 2025-05-30 09:56:34 +02:00
chocobozzz
b5ce236a20 Deleted translation using Weblate (English (United Kingdom)) 2025-05-30 09:56:08 +02:00
chocobozzz
a3ddc7ab4b Deleted translation using Weblate (French) 2025-05-30 09:55:23 +02:00
chocobozzz
51d10c47f9 Deleted translation using Weblate (French) 2025-05-30 09:53:41 +02:00
chocobozzz
dca19b755d Deleted translation using Weblate (French) 2025-05-30 09:53:19 +02:00
spf
3c2bb28823 Translated using Weblate (French (France) (fr_FR))
Currently translated at 88.5% (2303 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/fr_FR/
2025-05-28 13:02:30 +02:00
Hồ Nhất Duy
5a2e8fc0aa Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-05-28 06:55:22 +02:00
fran secs
c6387ffad1 Translated using Weblate (Catalan)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-05-28 06:55:22 +02:00
Chocobozzz
96a9b5cc90 Fix ERR_REQUIRE_ESM error 2025-05-28 06:55:01 +02:00
Chocobozzz
fbb6fbb56f Fix go live in Chinese 2025-05-27 16:11:23 +02:00
chocobozzz
5bb9cc67dd Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 99.6% (2591 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-05-27 16:09:25 +02:00
chocobozzz
9e6630cfef Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-27 16:09:24 +02:00
Chocobozzz
ef5c3f0c4f Update translations 2025-05-27 16:01:11 +02:00
Ricardo Simões
4e4dcbaf72 Translated using Weblate (Portuguese)
Currently translated at 100.0% (71 of 71 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/pt/
2025-05-26 17:29:09 +02:00
Ricardo Simões
ed0a30afc7 Added translation using Weblate (Portuguese) 2025-05-26 17:23:12 +02:00
Ricardo Simões
69182dc52c Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (155 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/pt_PT/
2025-05-26 17:23:12 +02:00
Ricardo Simões
b788266f3e Translated using Weblate (Portuguese (Portugal))
Currently translated at 20.4% (531 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_PT/
2025-05-26 17:17:04 +02:00
Ricardo Simões
c3fb738013 Translated using Weblate (Portuguese (Portugal))
Currently translated at 20.2% (528 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_PT/
2025-05-26 17:14:53 +02:00
Leif-Jöran Olsson
d4e55740b1 Translated using Weblate (Swedish)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-05-26 14:48:19 +02:00
T.S
d0898df596 Translated using Weblate (Japanese)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-05-26 14:48:18 +02:00
tray
689296bf78 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-26 11:53:57 +02:00
Chocobozzz
4739b117e8 Always specify s3 content type 2025-05-26 11:08:47 +02:00
Chocobozzz
fb9d678f7f Put the delete button in a dedicated section 2025-05-26 10:27:44 +02:00
Chocobozzz
2e824a29cf Improve playlist column UX 2025-05-26 10:13:08 +02:00
Chocobozzz
056a94a44d Fix ownership changes count 2025-05-26 10:00:30 +02:00
Chocobozzz
ca2c6139ef Improve error handling message 2025-05-26 09:35:16 +02:00
Chocobozzz
1570d57c79 Update translations 2025-05-26 08:50:24 +02:00
Chocobozzz
0c1db92a23 Merge remote-tracking branch 'weblate/develop' into develop 2025-05-26 08:47:34 +02:00
Chocobozzz
d2706f6711 Fix multer vulnerability 2025-05-26 08:37:53 +02:00
Fjuro
db2dcbdc06 Translated using Weblate (Czech)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-26 08:30:13 +02:00
Fjuro
63058d434b Translated using Weblate (Czech)
Currently translated at 100.0% (155 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/cs/
2025-05-26 08:30:13 +02:00
T.S
db2d194150 Translated using Weblate (Japanese)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-05-26 08:30:13 +02:00
Fjuro
e8f3247efd Translated using Weblate (Czech)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-26 08:30:13 +02:00
Chocobozzz
8f46c6d23c Fix weblate link 2025-05-26 08:29:55 +02:00
Chocobozzz
9c94625fad Fix grammar 2025-05-26 08:29:13 +02:00
Chocobozzz
b3a7514066 Update translations 2025-05-22 07:17:17 +02:00
Jiří Podhorecký
1a6ad8b633 Translated using Weblate (Czech)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-22 00:41:16 +02:00
Jiří Podhorecký
d014001f7b Translated using Weblate (Czech)
Currently translated at 99.5% (2588 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-22 00:17:50 +02:00
Jiří Podhorecký
f7f3a54e00 Translated using Weblate (Czech)
Currently translated at 99.0% (2577 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-22 00:02:07 +02:00
Jiří Podhorecký
a66750da25 Translated using Weblate (Czech)
Currently translated at 98.5% (2563 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-21 23:50:29 +02:00
fran secs
042edbc792 Translated using Weblate (Catalan)
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-05-21 23:50:29 +02:00
Sveinn í Felli
845c49ac04 Translated using Weblate (Icelandic)
Currently translated at 96.9% (2522 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/is/
2025-05-21 17:15:02 +02:00
Sveinn í Felli
b3c9bdb2e7 Translated using Weblate (Icelandic)
Currently translated at 96.1% (2502 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/is/
2025-05-21 16:02:16 +02:00
偶尔来巡山
e7d546d129 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2601 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-21 08:22:41 +02:00
fran secs
23ae3d9a3e Translated using Weblate (Catalan)
Currently translated at 99.6% (2591 of 2601 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-05-21 08:22:41 +02:00
Chocobozzz
e37ac1a2c1 Fix my videos dropdown filter 2025-05-21 08:22:32 +02:00
Chocobozzz
0d9944bcf0 Reorder privacy related fields 2025-05-21 08:22:32 +02:00
Pedro hates github.com
e26f4b7c5c Update entrypoint.nginx.sh
add exec to nginx process to ensure is PID 1 and  thenensure a graceful shutdown
2025-05-20 15:37:03 +02:00
Chocobozzz
429a160943 Fix deep link with query params 2025-05-20 14:25:47 +02:00
Chocobozzz
6a718036b9 Update translations 2025-05-20 10:59:31 +02:00
Andreas Grupp
e0917b5ce5 Translated using Weblate (German)
Currently translated at 93.6% (2438 of 2604 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-05-20 10:56:05 +02:00
Ettore Atalan
d77d20e297 Translated using Weblate (German)
Currently translated at 92.4% (2407 of 2604 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-05-20 10:56:05 +02:00
T.S
cec2a2f10b Translated using Weblate (Japanese)
Currently translated at 100.0% (2604 of 2604 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-05-20 10:56:05 +02:00
Hồ Nhất Duy
6fa2cacc0c Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2604 of 2604 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-05-20 10:56:05 +02:00
Leif-Jöran Olsson
a1095f74d9 Translated using Weblate (Swedish)
Currently translated at 100.0% (155 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/sv/
2025-05-20 10:56:05 +02:00
姚霁恒
2dabd41230 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/zh_Hans/
2025-05-20 10:56:04 +02:00
Leif-Jöran Olsson
2f1f5e0080 Translated using Weblate (Swedish)
Currently translated at 100.0% (2604 of 2604 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-05-20 10:56:04 +02:00
Tsuki
8a2d458cbf Translated using Weblate (Polish)
Currently translated at 56.5% (1472 of 2604 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pl/
2025-05-20 10:56:04 +02:00
T.S
8170f530f6 Translated using Weblate (Japanese)
Currently translated at 96.1% (2504 of 2604 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-05-20 10:56:04 +02:00
Jeff Huang
d8d3a96dff Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2604 of 2604 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-05-20 10:56:04 +02:00
tray
03a9466a90 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2604 of 2604 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-20 10:56:04 +02:00
Chocobozzz
3292bbe55f Improve object storage config comment doc 2025-05-20 10:55:32 +02:00
Chocobozzz
8114c38c2b Fix typo 2025-05-20 10:49:01 +02:00
Chocobozzz
d56aaf5c99 Improve sensitive labels sentences
See https://framacolibri.org/t/concerns-about-the-new-nsfw-system/25843/4?u=chocobozzz
2025-05-20 10:38:24 +02:00
Chocobozzz
b19754f259 Use a migration script for comments count 2025-05-20 10:36:54 +02:00
Chocobozzz
feb178e171 Fix missing ownership change action 2025-05-15 15:40:08 +02:00
Chocobozzz
b78a1bec9c Fix listing account/channel videos 2025-05-15 10:17:45 +02:00
Chocobozzz
c7dc293960 Bumped to version v7.2.0-rc.1 2025-05-15 08:36:44 +02:00
Chocobozzz
281ad3351b Update changelog 2025-05-15 08:36:27 +02:00
Chocobozzz
766b3f237d Fix user export 2025-05-15 07:34:13 +02:00
Chocobozzz
6f3b827d6c Fix broken replay on live privacy change 2025-05-14 16:20:35 +02:00
Chocobozzz
7b06f37b22 Fix crash on non existing live replay directory 2025-05-14 15:39:56 +02:00
Chocobozzz
bd33fbb4ec Better avatar order in AP representation
Remote federated software usually use the first item, and so 48x48 is
too small. Prefer 120x120 instead
2025-05-14 15:37:41 +02:00
Chocobozzz
25c5507a03 Add global rate limit to video download 2025-05-14 15:16:38 +02:00
Chocobozzz
49a6211f25 Fix E2E tests 2025-05-14 15:16:38 +02:00
Chocobozzz
b84f203459 Remove shocking/disturbing nsfw flag
It's too vague
2025-05-14 15:16:38 +02:00
Wicklow
51aa83406e Update translation.md 2025-05-14 15:16:27 +02:00
Wicklow
389c432c5c update openapi 2025-05-14 15:16:27 +02:00
Chocobozzz
5ef31b0f47 Update translations 2025-05-14 08:32:17 +02:00
GunChleoc
f50f25b236 Translated using Weblate (Gaelic)
Currently translated at 100.0% (155 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/gd/
2025-05-14 08:23:53 +02:00
GunChleoc
1c41936ab2 Translated using Weblate (Gaelic)
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/gd/
2025-05-14 08:23:53 +02:00
GunChleoc
9cbbffe100 Translated using Weblate (Gaelic)
Currently translated at 75.3% (1959 of 2599 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/gd/
2025-05-14 08:23:53 +02:00
fran secs
4b41715bc0 Translated using Weblate (Catalan)
Currently translated at 100.0% (2599 of 2599 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-05-14 08:23:53 +02:00
Jeff Huang
d924dd3019 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2599 of 2599 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-05-14 08:23:53 +02:00
Sveinn í Felli
f60ca3db99 Translated using Weblate (Icelandic)
Currently translated at 95.5% (2484 of 2599 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/is/
2025-05-14 08:23:53 +02:00
T.S
caff9a2d95 Translated using Weblate (Japanese)
Currently translated at 96.3% (2503 of 2599 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-05-14 08:23:52 +02:00
偶尔来巡山
01801d6bd0 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2599 of 2599 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-14 08:23:52 +02:00
Chocobozzz
fd2292c723 Don't use file logger in worker threads 2025-05-13 16:06:37 +02:00
Chocobozzz
1aa9ff8aa4 Merge branch 'release/7.1.0' into develop 2025-05-13 15:24:51 +02:00
Chocobozzz
a9069d0d0b Fix crash on download stream error 2025-05-13 13:54:19 +02:00
Chocobozzz
6e40f1f5a0 Add piscina idle timeout 2025-05-13 11:24:39 +02:00
Chocobozzz
a29bf7619d Prevent plugins to log exceptions 2025-05-13 11:21:06 +02:00
Chocobozzz
106acd8509 Reorder NSFW policy settings
Blur is stricter than warn
2025-05-13 10:37:16 +02:00
Chocobozzz
f739c41722 Better explanation of NSFW flags 2025-05-13 09:37:20 +02:00
Chocobozzz
920e84dd4f Fix CI types 2025-05-13 09:05:13 +02:00
Chocobozzz
720f436654 Fix peertube account redirection 2025-05-13 08:27:04 +02:00
Chocobozzz
b4f5fdaf0c Update runner version 2025-05-13 08:08:31 +02:00
Chocobozzz
1d0fdb9864 Add download file timeout 2025-05-12 11:06:42 +02:00
Chocobozzz
dc05b37d17 Add ability to disable NSFW flags settings 2025-05-12 10:18:55 +02:00
Chocobozzz
9f180a36c4 Update client dependencies 2025-05-09 16:50:07 +02:00
Chocobozzz
3cf8adb6d1 Fix types CI 2025-05-09 16:04:23 +02:00
Chocobozzz
92e4492c48 Update server dependencies 2025-05-09 15:45:03 +02:00
Chocobozzz
401dcafe47 Add more info to NSFW confirm modal 2025-05-09 15:08:21 +02:00
Chocobozzz
1d35888ca8 More robust theme injection in embed 2025-05-09 14:13:28 +02:00
Chocobozzz
5158eb0d9e Update translations 2025-05-09 13:33:51 +02:00
Chocobozzz
3f75361db6 Merge remote-tracking branch 'weblate/develop' into develop 2025-05-09 13:31:59 +02:00
chocobozzz
81044ac1cb Translated using Weblate (Spanish)
Currently translated at 86.9% (2260 of 2598 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-05-09 13:31:52 +02:00
Chocobozzz
bba1ade360 Add NSFW filter for videos in admin 2025-05-09 12:27:31 +02:00
fran secs
ae3f4a367d Translated using Weblate (Catalan)
Currently translated at 100.0% (155 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/ca/
2025-05-09 11:58:51 +02:00
fran secs
a604032a11 Translated using Weblate (Catalan)
Currently translated at 100.0% (2598 of 2598 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-05-09 11:58:51 +02:00
Hồ Nhất Duy
50de7f74ed Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2598 of 2598 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-05-09 11:58:51 +02:00
Hồ Nhất Duy
861718d276 Translated using Weblate (Vietnamese)
Currently translated at 99.2% (2578 of 2598 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-05-09 11:58:51 +02:00
偶尔来巡山
d9f9e9b29a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2598 of 2598 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-09 11:58:51 +02:00
偶尔来巡山
1365086b5a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (155 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/zh_Hans/
2025-05-09 11:58:50 +02:00
偶尔来巡山
222918cb09 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2598 of 2598 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-09 11:58:50 +02:00
Hồ Nhất Duy
c0d86312a9 Translated using Weblate (Vietnamese)
Currently translated at 98.6% (2564 of 2598 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-05-09 11:58:50 +02:00
Besnik Bleta
ac6c54eb71 Translated using Weblate (Albanian)
Currently translated at 99.3% (154 of 155 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/sq/
2025-05-09 11:58:50 +02:00
Ettore Atalan
6bba1244f9 Translated using Weblate (German)
Currently translated at 91.3% (2374 of 2598 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-05-09 11:58:50 +02:00
Jeff Huang
f83b02d788 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2598 of 2598 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-05-09 11:58:50 +02:00
kontrollanten
f07112109b client: dont use rel=ugc for plugins markdown
closes #6959
2025-05-09 11:58:39 +02:00
Chocobozzz
8d3bc24c4b Support raw strings for AP to/cc 2025-05-09 11:36:21 +02:00
Chocobozzz
5138e28ff8 Remove IRC link
We mainly use matrix now
2025-05-09 10:04:59 +02:00
Chocobozzz
54c8280a3b Add issue template for mobile application 2025-05-09 10:01:15 +02:00
Chocobozzz
64a4017a09 Retry actor request on owner public key
May fix federation with gotosocial
2025-05-07 17:13:43 +02:00
Chocobozzz
e1a7d0ef8a Update tsconfig to include all files 2025-05-07 17:00:13 +02:00
Chocobozzz
034e1bf328 Migrate eslint to v9 2025-05-07 15:49:23 +02:00
Chocobozzz
bad8ea2c2e Fix object storage live tests 2025-05-06 12:06:33 +02:00
Chocobozzz
52a4813fbb Fix tests 2025-05-06 11:26:33 +02:00
Chocobozzz
718107d861 Fix spaces in the sentence 2025-05-06 09:42:24 +02:00
Chocobozzz
9aa557649e Support hot sort for search endpoint 2025-05-06 09:27:48 +02:00
Chocobozzz
1ee4d6f875 Add search index tests for nsfw flags 2025-05-06 09:03:14 +02:00
Chocobozzz
42ef506081 Add html dprint formatter 2025-05-06 08:37:55 +02:00
Chocobozzz
828a67aed8 Add dprint scss formatter 2025-05-05 15:59:47 +02:00
Chocobozzz
1681a664db Use hot algorithm by default 2025-05-05 15:37:43 +02:00
Chocobozzz
b9f6d021a3 Prefer to not store lives in S3 by default
It causes too many issues with some object storage providers
Admin may choose to use a CDN instead
2025-05-05 15:36:45 +02:00
Chocobozzz
516e95597e Update translations 2025-05-05 11:34:03 +02:00
josé m
ccdf8ad4cf Translated using Weblate (Galician)
Currently translated at 95.0% (2452 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/gl/
2025-05-05 11:28:56 +02:00
StarAtt
0e8293becb Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-05-05 11:28:56 +02:00
T.S
ba8810c411 Translated using Weblate (Japanese)
Currently translated at 97.3% (2512 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-05-05 11:28:56 +02:00
StarAtt
9cd5efd1c3 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (148 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/zh_Hant/
2025-05-05 11:28:56 +02:00
StarAtt
b57f51145e Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/zh_Hant/
2025-05-05 11:28:56 +02:00
StarAtt
0f2364d08e Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-05-05 11:28:56 +02:00
StarAtt
cf72ddf445 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (148 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/zh_Hant/
2025-05-05 11:28:56 +02:00
Jiří Podhorecký
7df9a6c089 Translated using Weblate (Czech)
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-05 11:28:56 +02:00
Cavernosa
3b5f1f9f94 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (148 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/pt_BR/
2025-05-05 11:28:56 +02:00
Cavernosa
d81dafc6a8 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/pt_BR/
2025-05-05 11:28:56 +02:00
Cavernosa
04b8af8b39 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (148 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/pt_BR/
2025-05-05 11:28:56 +02:00
Cirnos
e8aca0072f Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-05-05 11:28:56 +02:00
Cavernosa
6f8344613c Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (148 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/pt_BR/
2025-05-05 11:28:56 +02:00
Cavernosa
d0680b5ba3 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-05-05 11:28:56 +02:00
Cavernosa
9510b61356 Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.9% (2579 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-05-05 11:28:56 +02:00
Cavernosa
e97ef2d3eb Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.8% (2575 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-05-05 11:28:55 +02:00
T.S
030398ca08 Translated using Weblate (Japanese)
Currently translated at 96.9% (2501 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-05-05 11:28:55 +02:00
Jiří Podhorecký
6b65003085 Translated using Weblate (Czech)
Currently translated at 99.6% (2572 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-05 11:28:55 +02:00
Jiří Podhorecký
cbabe1a49e Translated using Weblate (Czech)
Currently translated at 99.1% (2557 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-05 11:28:55 +02:00
Blood Axe
95794e6604 Translated using Weblate (Norwegian Bokmål)
Currently translated at 96.6% (143 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
41c409252f Translated using Weblate (Norwegian Bokmål)
Currently translated at 86.2% (2226 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Александр
b65b180937 Translated using Weblate (Russian)
Currently translated at 90.3% (2331 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ru/
2025-05-05 11:28:55 +02:00
Blood Axe
53db855814 Translated using Weblate (Norwegian Bokmål)
Currently translated at 96.6% (143 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
de2a2997fd Translated using Weblate (Norwegian Bokmål)
Currently translated at 86.2% (2226 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
56785c8e71 Translated using Weblate (Norwegian Bokmål)
Currently translated at 96.6% (143 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
df2459145f Translated using Weblate (Norwegian Bokmål)
Currently translated at 27.5% (75 of 272 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
85fc4cd7ca Translated using Weblate (Norwegian Bokmål)
Currently translated at 86.2% (2225 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
0545e54215 Translated using Weblate (Norwegian Bokmål)
Currently translated at 78.6% (2029 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
167475789c Translated using Weblate (Norwegian Bokmål)
Currently translated at 77.2% (1992 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
a23d540597 Translated using Weblate (Norwegian Bokmål)
Currently translated at 76.9% (1985 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
dxuser514
90b6988696 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:55 +02:00
Blood Axe
638dcd3356 Translated using Weblate (Norwegian Bokmål)
Currently translated at 76.1% (1965 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
dc7463d681 Translated using Weblate (Norwegian Bokmål)
Currently translated at 96.6% (143 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
abf0cf247f Translated using Weblate (Norwegian Bokmål)
Currently translated at 71.3% (1840 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
98e4e19e20 Translated using Weblate (Norwegian Bokmål)
Currently translated at 70.0% (1808 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
082ba268da Translated using Weblate (Norwegian Bokmål)
Currently translated at 67.6% (1746 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
18d11094ce Translated using Weblate (Norwegian Bokmål)
Currently translated at 66.0% (1704 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
b7ac3b2848 Translated using Weblate (Norwegian Bokmål)
Currently translated at 64.7% (1671 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
548a635c9b Translated using Weblate (Norwegian Bokmål)
Currently translated at 62.2% (1607 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
bb8a398933 Translated using Weblate (Norwegian Bokmål)
Currently translated at 60.7% (1567 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
fd23e98d4c Translated using Weblate (Norwegian Bokmål)
Currently translated at 60.6% (1565 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Blood Axe
204705452e Translated using Weblate (Norwegian Bokmål)
Currently translated at 60.5% (1562 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/nb_NO/
2025-05-05 11:28:55 +02:00
Ettore Atalan
2c07a6c584 Translated using Weblate (German)
Currently translated at 92.5% (2388 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-05-05 11:28:54 +02:00
dxuser514
302a57228c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (148 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/zh_Hans/
2025-05-05 11:28:54 +02:00
darek
ed51b887ef Translated using Weblate (Polish)
Currently translated at 100.0% (148 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/pl/
2025-05-05 11:28:54 +02:00
darek
a4bf3518e4 Translated using Weblate (Polish)
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/pl/
2025-05-05 11:28:54 +02:00
Jiří Podhorecký
be4b02c25d Translated using Weblate (Czech)
Currently translated at 97.4% (2514 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-05 11:28:54 +02:00
tray
9b6e0e1c4f Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/zh_Hans/
2025-05-05 11:28:54 +02:00
tray
40fe866787 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
Jiří Podhorecký
b5e942256d Translated using Weblate (Czech)
Currently translated at 95.1% (2456 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-05-05 11:28:54 +02:00
tray
c95e7d3aa6 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 98.7% (2549 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
tray
61d493cd62 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 97.3% (2511 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
dxuser514
6f7dd4a767 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (2425 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
Liu Zhiyu
f40eea3413 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (2425 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
Liu Zhiyu
03de725ffa Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (2425 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
tray
db7f832b1d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (2425 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
Liu Zhiyu
43a0228c2c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (2425 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
tray
e8b70ccdff Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (2425 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
ou jian bo
140b153ff3 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (2425 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
legiorange
499d4f970a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (2425 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
tray
f3ac4d6a7a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (2425 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hans/
2025-05-05 11:28:54 +02:00
Ettore Atalan
6965754df1 Translated using Weblate (German)
Currently translated at 90.8% (2343 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-05-05 11:28:54 +02:00
Ettore Atalan
23ba5ad53e Translated using Weblate (German)
Currently translated at 84.3% (2177 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/de/
2025-05-05 11:28:54 +02:00
Leif-Jöran Olsson
5f1bedef44 Translated using Weblate (Swedish)
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-05-05 11:28:54 +02:00
Leif-Jöran Olsson
da8be31418 Translated using Weblate (Swedish)
Currently translated at 99.8% (2576 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-05-05 11:28:54 +02:00
Leif-Jöran Olsson
226d4618e2 Translated using Weblate (Swedish)
Currently translated at 99.7% (2574 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-05-05 11:28:53 +02:00
T.S
0c525bb4fe Translated using Weblate (Japanese)
Currently translated at 96.5% (2492 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-05-05 11:28:53 +02:00
fran secs
0354f8ab51 Translated using Weblate (Catalan)
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-05-05 11:28:53 +02:00
ButterflyOfFire
809eaac6ce Translated using Weblate (Kabyle)
Currently translated at 83.7% (124 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/kab/
2025-05-05 11:28:53 +02:00
ButterflyOfFire
3963a7d01b Translated using Weblate (Kabyle)
Currently translated at 92.7% (254 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/kab/
2025-05-05 11:28:53 +02:00
ButterflyOfFire
dc4cf14b9a Translated using Weblate (Kabyle)
Currently translated at 50.1% (1294 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/kab/
2025-05-05 11:28:53 +02:00
Hồ Nhất Duy
245b941563 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-05-05 11:28:53 +02:00
Jeff Huang
ee0b4cfd3d Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2580 of 2580 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-05-05 11:28:53 +02:00
Chocobozzz
2751dbef6f Fix overflow 2025-05-05 11:28:26 +02:00
Chocobozzz
d5c4fa74e4 Use theme colors for popover 2025-05-05 11:25:20 +02:00
Chocobozzz
1c31fe29cc Correctly handle generateTranscription 2025-05-05 11:16:20 +02:00
Chocobozzz
7d3e366f00 Remove unnecessary i18n tag 2025-05-05 10:16:23 +02:00
Chocobozzz
5d3b6f6be9 Prevent layout shift 2025-05-05 10:16:03 +02:00
Chocobozzz
dd4027a10f Improve NSFW system
* Add NSFW flags to videos so the publisher can add more NSFW context
 * Add NSFW summary to videos, similar to content warning system so the
   publisher has a free text to describe NSFW aspect of its video
 * Add additional "warn" NSFW policy: the video thumbnail is not blurred
   and we display a tag below the video miniature, the video player
   includes the NSFW warning (with context if available) and it also
   prevent autoplay
 * "blur" NSFW settings inherits "warn" policy and also blur the video
   thumbnail
 * Add NSFW flag settings to users so they can have more granular
   control about what content they want to hide, warn or display
2025-04-30 15:54:11 +02:00
Chocobozzz
fac6b15ada Fix action button overflow 2025-04-22 14:20:26 +02:00
Chocobozzz
a2a8ba7af5 Add padding to admin videos cells 2025-04-22 14:14:44 +02:00
Johan van Dongen
1bf655fcba Add embed paramaters (#6989)
* peertube-video-embed: add support for responsive data attribute

* peertube-video-embed: add support for the remaining data-* attributes

* add support for playlist position data tag

* Styling

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-04-22 10:02:21 +02:00
Chocobozzz
e24716c571 Better chapters from description parsing 2025-04-22 09:44:13 +02:00
Chocobozzz
8c3797ced5 Update translations 2025-04-17 15:59:32 +02:00
Chocobozzz
5877b3749c Merge remote-tracking branch 'weblate/develop' into develop 2025-04-17 15:57:41 +02:00
Chocobozzz
fbe794f9a4 Don't send auth header to object storage 2025-04-17 15:57:20 +02:00
Cirnos
15057edf95 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-04-17 15:34:57 +02:00
Leif-Jöran Olsson
0dbc7b9b8c Translated using Weblate (Swedish)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
181c2e1e46 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (148 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/vi/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
cfb01e20c4 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/vi/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
967cb2a010 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
f4a098749c Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
f226272a14 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
2f7bdd664e Translated using Weblate (Vietnamese)
Currently translated at 100.0% (148 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/vi/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
5925047fb7 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
fac343ac28 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
f915fab8d0 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
2fffd9379b Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:57 +02:00
Hồ Nhất Duy
079f499bc5 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:57 +02:00
Leif-Jöran Olsson
bb27398151 Translated using Weblate (Swedish)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-04-17 15:34:57 +02:00
T.S
86b216cf86 Translated using Weblate (Japanese)
Currently translated at 95.3% (2453 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-04-17 15:34:56 +02:00
T.S
7b06bcc279 Translated using Weblate (Japanese)
Currently translated at 95.2% (2452 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-04-17 15:34:56 +02:00
Hồ Nhất Duy
a558e8b2d2 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:56 +02:00
Hồ Nhất Duy
53a93e279d Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:56 +02:00
Leif-Jöran Olsson
361daf8433 Translated using Weblate (Swedish)
Currently translated at 98.4% (2532 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-04-17 15:34:56 +02:00
Hồ Nhất Duy
09b14e656e Translated using Weblate (Vietnamese)
Currently translated at 99.3% (2556 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:56 +02:00
Hồ Nhất Duy
ae496af13e Translated using Weblate (Vietnamese)
Currently translated at 98.8% (2544 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:56 +02:00
Leif-Jöran Olsson
73fa352cca Translated using Weblate (Swedish)
Currently translated at 96.3% (2480 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-04-17 15:34:56 +02:00
Hồ Nhất Duy
04a1c1aecc Translated using Weblate (Vietnamese)
Currently translated at 98.6% (2537 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-17 15:34:56 +02:00
Leif-Jöran Olsson
00d4387a85 Translated using Weblate (Swedish)
Currently translated at 96.2% (2476 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-04-17 15:34:56 +02:00
Jeff Huang
b06fbace89 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-04-17 15:34:56 +02:00
fran secs
6737fdf49a Translated using Weblate (Catalan)
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/ca/
2025-04-17 15:34:56 +02:00
fran secs
f18ac54e5b Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-04-17 15:34:56 +02:00
fran secs
d49ecdf440 Translated using Weblate (Catalan)
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-04-17 15:34:56 +02:00
Viorel-Cătălin Răpițeanu
d174362881 Translated using Weblate (Romanian)
Currently translated at 20.6% (282 of 1367 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ro/
2025-04-17 15:34:56 +02:00
Leif-Jöran Olsson
1d0470561e Translated using Weblate (Swedish)
Currently translated at 95.3% (2453 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-04-17 15:34:56 +02:00
Jeff Huang
17626d7b3f Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 98.9% (2545 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-04-17 15:34:56 +02:00
Ghost of Sparta
63d30864f4 Translated using Weblate (Hungarian)
Currently translated at 83.0% (2137 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/hu/
2025-04-17 15:34:55 +02:00
Jeff Huang
741a58b7c2 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 96.8% (2493 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-04-17 15:34:55 +02:00
Jeff Huang
ead5de75d4 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 96.5% (2485 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-04-17 15:34:55 +02:00
ButterflyOfFire
29dfb87133 Translated using Weblate (Kabyle)
Currently translated at 51.7% (1332 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/kab/
2025-04-17 15:34:55 +02:00
Jeff Huang
2e99b2dd75 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 95.7% (2464 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-04-17 15:34:55 +02:00
Túlio Simões Martins Padilha
2735be4b47 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2573 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-04-17 15:34:55 +02:00
fran secs
cbfa839804 Translated using Weblate (Catalan)
Currently translated at 96.4% (2482 of 2573 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-04-17 15:34:55 +02:00
allmiha2
75c6fd9417 Add Drag-and-Drop to Replace File (#6970)
* Add Drag-and-Drop to Replace File

Added the drag and drop functionality (that was already used for publishing videos) for replacing the video files

* fix lint errors

* Implemented the new design for Replace file DnD

* fix lint errors

* Styling

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-04-17 15:34:51 +02:00
Chocobozzz
89c0f36a53 Run transcription after file replacement 2025-04-17 15:15:21 +02:00
Chocobozzz
f8db7406cf Upgrade pretty 2025-04-17 14:35:20 +02:00
Chocobozzz
7ecfb807ad Update videos on query params change 2025-04-17 14:29:23 +02:00
Chocobozzz
d31993b714 Fix sort with a video search 2025-04-17 14:29:23 +02:00
Chocobozzz
8f72e470f4 Force colors on dev/test mode
Concurrently program is used and not detected as a tty
2025-04-17 14:29:16 +02:00
Luc Didry
8de04c14e9 🔊 — [server] Disable log coloring when TTY does not support it 2025-04-17 14:29:16 +02:00
Luc Didry
04333e817f 🔊 — [peertube-runner] Disable log coloring when TTY does not support it 2025-04-17 14:13:01 +02:00
Chocobozzz
c1ced4209e User is created in the production guide 2025-04-16 16:43:51 +02:00
Chocobozzz
acaa6810df Prevent login for prunner 2025-04-16 16:27:42 +02:00
Chocobozzz
97b846b806 Fix tests 2025-04-16 15:58:14 +02:00
Chocobozzz
745c051bc3 Update runner version 2025-04-16 15:03:21 +02:00
Chocobozzz
b7a974e448 Support query params in runner custom upload 2025-04-16 15:00:59 +02:00
Chocobozzz
e498a80638 Sticky video manage header 2025-04-16 13:52:18 +02:00
Florent Poinsaut
b991534827 Fix typo in production.yaml 2025-04-16 13:52:14 +02:00
q0ntinuum
efdbd77d5d Modernize the OpenRC service with openrc-run and improve production guide (#6983)
* Modernize the OpenRC service with openrc-run and add upgrade documentation

* Move some variables to conf.d
2025-04-16 07:00:50 +02:00
Chocobozzz
66b27aafac Add ability to "show more" to markdown textarea 2025-04-15 16:20:16 +02:00
Chocobozzz
75089d7dc2 Better leave page warning modal
Inverse primary/secondary button so we don't leave the page by accident
2025-04-15 15:39:31 +02:00
Chocobozzz
9480204f0a Add E2E to change user email 2025-04-15 13:32:54 +02:00
Chocobozzz
ad21027598 Add missing reset password doc 2025-04-15 10:49:15 +02:00
Chocobozzz
986e71a1f7 Better ask email verification flow
Allow user to resend the email verification link when changing the
current email
Fix success messages when validating a new email
2025-04-15 10:36:12 +02:00
Chocobozzz
e19ee1ebc9 Merge branch 'release/7.1.0' into develop 2025-04-15 09:44:04 +02:00
Chocobozzz
1efa315d55 Update changelog with security CVEs 2025-04-15 09:37:08 +02:00
Chocobozzz
d6f7b471de Fix nodeinfo local posts 2025-04-15 09:36:56 +02:00
Chocobozzz
9f70fecb42 Remove duplicate sentence
We already have a "public email" checkbox above
2025-04-14 11:24:58 +02:00
Chocobozzz
98e3648a71 Invert badge colors for dark themes 2025-04-14 11:20:28 +02:00
Chocobozzz
933be18036 Better client scroll management
Remove the need to have query params in the URL
Fix scroll restore on channel and account pages
2025-04-14 11:04:43 +02:00
Chocobozzz
5e71dec766 Improve danger button style 2025-04-14 09:20:33 +02:00
Chocobozzz
3cce7ec1a0 Add ability to delete video in main info page 2025-04-14 09:10:33 +02:00
Chocobozzz
6a9c378021 Add ldap group tests 2025-04-11 15:50:13 +02:00
Chocobozzz
45da32cdd7 Merge branch 'release/7.1.0' into develop 2025-04-11 10:31:02 +02:00
Chocobozzz
8f87a6cd9f Fix audio only download 2025-04-11 10:30:16 +02:00
Chocobozzz
d0babc0012 Fix podcast feed download extension 2025-04-11 08:45:51 +02:00
Chocobozzz
a2812e40d9 Fix nginx max body size
We increased max image upload size in a4f836c042
2025-04-11 08:22:58 +02:00
Chocobozzz
1797f7e548 Fix podcast feed URL 2025-04-11 08:15:24 +02:00
Chocobozzz
b78a3f2e89 Fix progress bar margin 2025-04-11 06:55:32 +02:00
Chocobozzz
297e789cf8 Improve score label 2025-04-11 06:52:37 +02:00
Chocobozzz
9a021cfdc0 Fix input theme colors 2025-04-10 15:42:59 +02:00
Chocobozzz
a3ab7af885 Fix change detection for plugin fields 2025-04-10 14:39:06 +02:00
Chocobozzz
10eacdecf2 Improve responsive 2025-04-10 13:53:37 +02:00
Chocobozzz
0bd2abc5e8 Prevent overflow 2025-04-10 13:34:06 +02:00
Chocobozzz
a6f2e92c35 Limit max live sessions 2025-04-10 13:02:05 +02:00
Chocobozzz
9b05a4b49e Fix tests 2025-04-10 12:53:04 +02:00
Chocobozzz
d0e2ecd82c Ensure save button can be clicked with a new video 2025-04-10 10:34:27 +02:00
Chocobozzz
7cec8fd98c Use "match" sort when searching videos 2025-04-10 10:10:41 +02:00
Chocobozzz
7d99a6b857 Correctly display multi select header 2025-04-10 10:07:41 +02:00
Chocobozzz
e7753c1b62 Prefer handle param name 2025-04-10 09:55:55 +02:00
Chocobozzz
6f68db1be9 Use handle for param name 2025-04-10 09:44:50 +02:00
Chocobozzz
ade57193ac Use mobile for device if mobile is detected 2025-04-10 09:22:46 +02:00
Chocobozzz
a496da3780 Wait CSS variables to be ready 2025-04-10 09:16:58 +02:00
Chocobozzz
334ad174a9 Refactor account/channel manage checks
Use a more robust approach by requiring the caller to choose if it needs
to check the actor is local and/or the user can manage it
2025-04-10 09:07:42 +02:00
Chocobozzz
a1279d7eb5 Update peertube runner version 2025-04-10 07:15:39 +02:00
Chocobozzz
bd452215ae Update runner changelog 2025-04-10 07:02:32 +02:00
Chocobozzz
85eb64fb0e Update p2p media loader 2025-04-10 07:00:22 +02:00
Chocobozzz
0341f17e69 Update translations 2025-04-09 16:52:26 +02:00
Chocobozzz
006fc59c88 Merge remote-tracking branch 'weblate/develop' into develop 2025-04-09 16:45:44 +02:00
Sveinn í Felli
4474f95aa4 Translated using Weblate (Icelandic)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/is/
2025-04-09 16:45:36 +02:00
ButterflyOfFire
d0240a1372 Translated using Weblate (Kabyle)
Currently translated at 54.4% (1372 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/kab/
2025-04-09 16:45:35 +02:00
Túlio Simões Martins Padilha
b4dbe854b5 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/pt_BR/
2025-04-09 16:45:34 +02:00
Fjuro
f72762e5ee Translated using Weblate (Czech)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-04-09 16:45:26 +02:00
Chocobozzz
ccb3fd4ab7 Merge branch 'release/7.1.0' into develop 2025-04-09 16:45:05 +02:00
Chocobozzz
6e44e7e29a Create and inject caption playlist in HLS master 2025-04-09 16:18:38 +02:00
Fjuro
9719251d02 Translated using Weblate (Czech)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-04-08 23:20:01 +02:00
Chocobozzz
b9c3a4837e Bumped to version v7.1.1 2025-04-08 08:51:31 +02:00
Chocobozzz
d60983bea5 Update changelog 2025-04-08 08:35:40 +02:00
Chocobozzz
94deeb0a8f Fix HLS private static path 2025-04-08 08:18:54 +02:00
Leif-Jöran Olsson
f54d9e58f3 Translated using Weblate (Swedish)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/sv/
2025-04-07 14:49:47 +02:00
Murat Hasdemir
b77555124d Translated using Weblate (Turkish)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/tr/
2025-04-07 10:30:06 +02:00
Murat Hasdemir
8b6c0048b1 Translated using Weblate (Turkish)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/tr/
2025-04-07 10:30:06 +02:00
Murat Hasdemir
3793a666a6 Translated using Weblate (Turkish)
Currently translated at 100.0% (147 of 147 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/tr/
2025-04-07 10:30:06 +02:00
Murat Hasdemir
d3176ad9ac Translated using Weblate (Turkish)
Currently translated at 88.6% (2235 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/tr/
2025-04-07 10:30:06 +02:00
Hồ Nhất Duy
e222f78334 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-07 10:30:06 +02:00
T.S
0921485b55 Translated using Weblate (Japanese)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ja/
2025-04-07 10:30:06 +02:00
Hồ Nhất Duy
d7af541133 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-07 10:30:05 +02:00
Hồ Nhất Duy
75f34a9571 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (148 of 148 strings)

Translation: PeerTube/player
Translate-URL: https://weblate.framasoft.org/projects/peertube/player/vi/
2025-04-07 10:30:05 +02:00
Hồ Nhất Duy
edb113aa32 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-07 10:30:05 +02:00
Hồ Nhất Duy
8270cdbddf Translated using Weblate (Vietnamese)
Currently translated at 100.0% (274 of 274 strings)

Translation: PeerTube/server
Translate-URL: https://weblate.framasoft.org/projects/peertube/server/vi/
2025-04-07 10:30:05 +02:00
Hồ Nhất Duy
672cbb6adc Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-07 10:30:05 +02:00
Fjuro
9c0d014906 Translated using Weblate (Czech)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/cs/
2025-04-07 10:30:05 +02:00
wazakovsky
517cd44534 Translated using Weblate (Spanish)
Currently translated at 93.4% (2356 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-04-07 10:30:05 +02:00
Jeff Huang
ff66a55759 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/zh_Hant/
2025-04-07 10:30:05 +02:00
Miguel P.L
7fca6321dd Translated using Weblate (Spanish)
Currently translated at 91.3% (2302 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/es/
2025-04-07 10:30:05 +02:00
Hồ Nhất Duy
67d37707f9 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/vi/
2025-04-07 10:30:05 +02:00
fran secs
fcb63bc116 Translated using Weblate (Catalan)
Currently translated at 100.0% (2520 of 2520 strings)

Translation: PeerTube/angular
Translate-URL: https://weblate.framasoft.org/projects/peertube/angular/ca/
2025-04-07 10:30:05 +02:00
kontrollanten
a7be820abc add user agent video stats (#6871)
* add user agent video stats

closes #6832

* Disable indexes, support start/end dates

* move ua parsing to client

* Openapi, inline body request, update tests

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-04-07 10:29:59 +02:00
Chocobozzz
473cd4f7ef Check max ZIP uncompressed size 2025-04-07 08:29:34 +02:00
Chocobozzz
69c851c8e6 Fix path traversal when getting a private playlist 2025-04-07 07:10:08 +02:00
Chocobozzz
96380859ef Add unavailable features on publish page 2025-04-04 15:29:38 +02:00
Chocobozzz
a256b54371 Add unavailable info in manage video menu 2025-04-04 14:29:32 +02:00
Chocobozzz
5722674e99 Move manage menu in its own component 2025-04-04 10:27:13 +02:00
Chocobozzz
082c9e5b50 Add state info in manage page 2025-04-04 10:13:16 +02:00
Chocobozzz
ea55c052fc Use pagination for my videos 2025-04-03 16:35:42 +02:00
Chocobozzz
3c5b3b07dc Improve plugin inputs display 2025-04-03 15:55:57 +02:00
Chocobozzz
9e53e4c861 Fix form change detection with plugins 2025-04-03 11:53:14 +02:00
Chocobozzz
71744313f0 Fix infinite server crash on invalid zip import 2025-04-03 10:37:21 +02:00
Chocobozzz
0fc3f91d83 Ensure playlist is owned by actor/instance 2025-04-03 10:19:37 +02:00
Chocobozzz
76226d8568 Fix infinite loop in AP crawl 2025-04-03 09:47:34 +02:00
Chocobozzz
fd6b6b5931 Ensure channel is owned by the account 2025-04-03 09:47:34 +02:00
Chocobozzz
ccafb6c6eb Add nginx-logs directory creation 2025-04-03 09:03:58 +02:00
Chocobozzz
60db4392e0 Use tag style 2025-04-03 09:03:33 +02:00
Chocobozzz
af8237dbff Remove unused video action dropdown actions 2025-04-03 09:03:33 +02:00
Chocobozzz
211ff8457e Reduce resolution checkbox margin bottom 2025-04-03 09:03:33 +02:00
Chocobozzz
aa89718329 Faster menu collapsed detection 2025-04-03 09:03:33 +02:00
Chocobozzz
b7f42a187e Add dropdown show button border 2025-04-03 09:03:33 +02:00
Chocobozzz
6e57570283 Put licence on right column 2025-04-03 09:03:33 +02:00
Chocobozzz
72fc4adfe8 Add preview to support field 2025-04-03 09:03:33 +02:00
Chocobozzz
fb49e82524 Fix overflow with long video name 2025-04-03 09:03:33 +02:00
Chocobozzz
287f9adbc9 Better my videos responsive 2025-04-03 09:03:33 +02:00
RiQuY
cfc5cfd06b feat (docker): Expose NGINX logs folder. (#6963)
* feat (docker): Expose NGINX logs folder.

This commit adds the folder /var/log/ngnix of the webserver container to the volume mount.

* refactor (docker): Rename mount folder name to avoid conflicts with NGINX site file.

This commit renames the mount folder nginx/logs to nginx-logs  to avoid conflicts with the NGINX site file.
2025-04-03 09:03:03 +02:00
Chocobozzz
07bc2bdac4 Merge branch 'release/7.1.0' into develop 2025-04-03 06:31:10 +02:00
Chocobozzz
301e19c4b4 Inject blacklisted reason 2025-04-03 06:29:50 +02:00
Chocobozzz
0ee00337f3 Specify charset in content type for subtitles 2025-04-03 06:09:24 +02:00
Chocobozzz
a913427eaf Add padding for action cell on sticky tables
Because they may have a scrollbar
2025-04-02 16:37:52 +02:00
RF9A5V
25a9f37ded Add Comment Count to Video Preview Components (#6635)
* WIP: Add backend functionality to store comment count per video and update on comment visibility actions

* WIP: Display image icon and comment count on video miniature component

* Probably don't need to index the comment count

* Added comment count back to mini video component

* Added basic tests

* Sort by comments, more robust comments count

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-04-02 16:29:22 +02:00
kontrollanten
75d7c2a9dc add filter:email.template-path.result / filter:email.subject.result (#6876)
* add filter:email.template-path.result / filter:email.subject.result

closes #3392

* Remove juice

* Kill mock server

---------

Co-authored-by: Chocobozzz <me@florianbigard.com>
2025-04-02 15:16:29 +02:00
Chocobozzz
e9f887323a Revert "fix: plugin/theme names with scope are not allowed"
This reverts commit 8426746bf1.
2025-04-02 14:36:11 +02:00
2153 changed files with 1106772 additions and 551726 deletions

View File

@@ -67,6 +67,16 @@
"json": {},
"markdown": {},
"toml": {},
"malva": {
"quotes": "preferDouble",
"printWidth": 140,
"hexCase": "ignore",
"blockSelectorLinebreak": "always"
},
"markup": {
"printWidth": 160,
"preferAttrsSingleLine": true
},
"excludes": [
"**/node_modules",
"**/*-lock.json",
@@ -76,6 +86,8 @@
"https://plugins.dprint.dev/typescript-0.91.1.wasm",
"https://plugins.dprint.dev/json-0.19.3.wasm",
"https://plugins.dprint.dev/markdown-0.17.1.wasm",
"https://plugins.dprint.dev/toml-0.6.2.wasm"
"https://plugins.dprint.dev/toml-0.6.2.wasm",
"https://plugins.dprint.dev/g-plane/malva-v0.12.0.wasm",
"https://plugins.dprint.dev/g-plane/markup_fmt-v0.24.1.wasm"
]
}

View File

@@ -1,151 +0,0 @@
{
"extends": "standard-with-typescript",
"root": true,
"rules": {
"eol-last": [
"error",
"always"
],
"indent": "off",
"no-lone-blocks": "off",
"no-mixed-operators": "off",
"max-len": [
"error",
{
"code": 140
}
],
"array-bracket-spacing": [
"error",
"always"
],
"quote-props": [
"error",
"consistent-as-needed"
],
"padded-blocks": "off",
"prefer-regex-literals": "off",
"no-async-promise-executor": "off",
"dot-notation": "off",
"promise/param-names": "off",
"import/first": "off",
"operator-linebreak": [
"error",
"after",
{
"overrides": {
"?": "before",
":": "before"
}
}
],
"quotes": "off",
"no-constant-binary-expression": "error",
"@typescript-eslint/indent": [
"error",
2,
{
"SwitchCase": 1,
"MemberExpression": "off",
// https://github.com/eslint/eslint/issues/15299
"ignoredNodes": ["PropertyDefinition", "TSTypeParameterInstantiation", "TSConditionalType *"]
}
],
"@typescript-eslint/consistent-type-assertions": [
"error",
{
"assertionStyle": "as"
}
],
"@typescript-eslint/array-type": [
"error",
{
"default": "array"
}
],
"@typescript-eslint/restrict-template-expressions": [
"off",
{
"allowNumber": "true"
}
],
"@typescript-eslint/no-this-alias": [
"error",
{
"allowDestructuring": true, // Allow `const { props, state } = this`; false by default
"allowedNames": ["self"] // Allow `const self = this`; `[]` by default
}
],
"@typescript-eslint/return-await": "off",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/method-signature-style": "off",
"@typescript-eslint/no-base-to-string": "off",
"@typescript-eslint/quotes": [
"error",
"single",
{
"avoidEscape": true,
"allowTemplateLiterals": true
}
],
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/promise-function-async": "off",
"@typescript-eslint/no-dynamic-delete": "off",
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "off",
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/consistent-type-definitions": "off",
"@typescript-eslint/no-misused-promises": "off",
"@typescript-eslint/no-namespace": "off",
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-extraneous-class": "off",
"@typescript-eslint/no-use-before-define": "off",
"require-await": "off",
"@typescript-eslint/require-await": "error",
// bugged but useful
"@typescript-eslint/restrict-plus-operands": "off",
// Requires strictNullChecks
"@typescript-eslint/prefer-nullish-coalescing": "off",
"@typescript-eslint/consistent-type-imports": "off",
"@typescript-eslint/consistent-indexed-object-style": "off",
"@typescript-eslint/no-confusing-void-expression": "off",
"@typescript-eslint/consistent-type-exports": "off",
"@typescript-eslint/key-spacing": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/ban-types": [
"error",
{
"types": {
"{}": false,
"Function": false
},
"extendDefaults": true
}
]
},
"ignorePatterns": [
"node_modules",
"packages/tests/fixtures",
"apps/**/dist",
"packages/**/dist",
"server/dist",
"packages/types-generator/tests",
"*.js",
"/client",
"/dist"
],
"parserOptions": {
"project": [
"./tsconfig.eslint.json"
],
"EXPERIMENTAL_useSourceOfProjectReferenceRedirect": true
}
}

View File

@@ -79,7 +79,7 @@ First, you should use a server or PC with at least 4GB of RAM. Less RAM may lead
git clone https://github.com/Chocobozzz/PeerTube
cd PeerTube
git remote add me git@github.com:YOUR_GITHUB_USERNAME/PeerTube.git
yarn install --pure-lockfile
npm run install-node-dependencies
```
Note that development is done on the `develop` branch. If you want to hack on
@@ -223,8 +223,19 @@ Instance configurations are in `config/test-{1,2,3}.yaml`.
To test emails with PeerTube:
* Run [mailslurper](http://mailslurper.com/)
* Run PeerTube using mailslurper SMTP port: `NODE_CONFIG='{ "smtp": { "hostname": "localhost", "port": 2500, "tls": false } }' NODE_ENV=dev node dist/server`
* Run [MailDev](https://github.com/maildev/maildev) using Docker
* Run PeerTube using MailDev SMTP port: `NODE_CONFIG='{ "smtp": { "hostname": "localhost", "port": 2500, "tls": false } }' NODE_ENV=dev node dist/server`
To test all emails without having to run actions manually on the web interface, you can run notification unit tests with environment variables to relay emails to your MailDev instance. For example:
```sh
MAILDEV_RELAY_HOST=localhost MAILDEV_RELAY_PORT=2500 mocha --exit --bail packages/tests/src/api/notifications/comments-notifications.ts
```
You can then go to the MailDev web interface and see how emails look like.
The admin web interface also have a button to send some email templates to a specific email address.
### Environment variables

View File

@@ -1,11 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: 🤷💻🤦 Question/Forum
- name: 📱 Mobile Application bug/feature request
url: https://framagit.org/framasoft/peertube/mobile-application/-/issues
about: Use the mobile application repository to report bugs or request new features
- name: 🤷 Question/Forum
url: https://framacolibri.org/c/peertube
about: You can ask and answer other questions here
- name: 💬 Matrix
url: https://matrix.to/#/#peertube:matrix.org
about: Chat with us via Matrix for quick Q/A here
- name: 💬 IRC
url: https://web.libera.chat/#peertube
about: Chat with us via IRC for quick Q/A here

View File

@@ -11,32 +11,20 @@ runs:
using: "composite"
steps:
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- name: Cache Node.js modules
uses: actions/cache@v4
with:
path: |
**/node_modules
key: ${{ runner.OS }}-node-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.OS }}-node-
${{ runner.OS }}-
cache: 'pnpm'
- name: Install dependencies
shell: bash
run: yarn install --frozen-lockfile
- name: Install peertube runner dependencies
shell: bash
run: cd apps/peertube-runner && yarn install --frozen-lockfile
- name: Install peertube CLI dependencies
shell: bash
run: cd apps/peertube-cli && yarn install --frozen-lockfile
run: npm run install-node-dependencies
- name: Display PeerTube dependencies
shell: bash

View File

@@ -8,6 +8,7 @@ runs:
- name: Setup system dependencies
shell: bash
run: |
sudo apt-get update
sudo apt-get install postgresql-client-common redis-tools parallel libimage-exiftool-perl
wget --quiet --no-check-certificate "https://download.cpy.re/ffmpeg/ffmpeg-release-4.3.1-64bit-static.tar.xz"
tar xf ffmpeg-release-4.3.1-64bit-static.tar.xz

222
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,222 @@
# PeerTube Copilot Instructions
## Repository Overview
PeerTube is an open-source, ActivityPub-federated video streaming platform using P2P technology directly in web browsers. It's developed by Framasoft and provides a decentralized alternative to centralized video platforms like YouTube.
**Repository Stats:**
- **Size**: Large monorepo (~350MB, ~15k files)
- **Type**: Full-stack web application
- **Languages**: TypeScript (backend), Angular (frontend), Shell scripts
- **Target Runtime**: Node.js >=20.x, PostgreSQL >=10.x, Redis >=6.x
- **Package Manager**: Yarn 1.x (NOT >=2.x)
- **Architecture**: Express.js API server + Angular SPA client + P2P video delivery
## Critical: Client Directory Exclusion
**🚫 ALWAYS IGNORE `client/` directory** - it contains a separate Angular frontend project with its own build system, dependencies, and development workflow. Focus only on the server-side backend code.
## Build & Development Commands
### Prerequisites (Required)
1. **Dependencies**: Node.js >=20.x, Yarn 1.x, PostgreSQL >=10.x, Redis >=6.x, FFmpeg >=4.3, Python >=3.8
2. **PostgreSQL Setup**:
```bash
sudo -u postgres createuser -P peertube
sudo -u postgres createdb -O peertube peertube_dev
sudo -u postgres psql -c "CREATE EXTENSION pg_trgm;" peertube_dev
sudo -u postgres psql -c "CREATE EXTENSION unaccent;" peertube_dev
```
3. **Services**: Start PostgreSQL and Redis before development
### Installation & Build (Execute in Order)
```bash
# 1. ALWAYS install dependencies first (takes ~2-3 minutes)
yarn install --frozen-lockfile
# 2. Build server (required for most operations, takes ~3-5 minutes)
npm run build:server
# 3. Optional: Build full application (takes ~10-15 minutes)
npm run build
```
**⚠️ Critical Notes:**
- Always run `yarn install --frozen-lockfile` before any build operation
- Server build is prerequisite for testing and development
- Never use `npm install` - always use `yarn`
- Build failures often indicate missing PostgreSQL extensions or wrong Node.js version
### Development Commands
```bash
# Server-only development (recommended for backend work)
npm run dev:server # Starts server on localhost:9000 with hot reload
# Full stack development (NOT recommended if only working on server)
npm run dev # Starts both server (9000) and client (3000)
# Development credentials:
# Username: root
# Password: test
```
### Testing Commands (Execute in Order)
```bash
# 1. Prepare test environment (required before first test run)
sudo -u postgres createuser $(whoami) --createdb --superuser
npm run clean:server:test
# 2. Build (required before testing)
npm run build
# 3. Run specific test suites (recommended over full test)
npm run ci -- api-1 # API tests part 1
npm run ci -- api-2 # API tests part 2
npm run ci -- lint # Linting only
npm run ci -- client # Client tests
# 4. Run single test file
npm run mocha -- --exit --bail packages/tests/src/api/videos/single-server.ts
# 5. Full test suite (takes ~45-60 minutes, avoid unless necessary)
npm run test
```
**⚠️ Test Environment Notes:**
- Tests require PostgreSQL user with createdb/superuser privileges
- Some tests need Docker containers for S3/LDAP simulation
- Test failures often indicate missing system dependencies or DB permissions
- Set `DISABLE_HTTP_IMPORT_TESTS=true` to skip flaky import tests
### Validation Commands
```bash
# Lint code (runs ESLint + OpenAPI validation)
npm run lint
# Validate OpenAPI spec
npm run swagger-cli -- validate support/doc/api/openapi.yaml
# Build server
npm run build:server
```
## Project Architecture & Layout
### Server-Side Structure (Primary Focus)
```
server/core/
├── controllers/api/ # Express route handlers (add new endpoints here)
│ ├── index.ts # Main API router registration
│ ├── videos/ # Video-related endpoints
│ └── users/ # User-related endpoints
├── models/ # Sequelize database models
│ ├── video/ # Video, channel, playlist models
│ └── user/ # User, account models
├── lib/ # Business logic services
│ ├── job-queue/ # Background job processing
│ └── emailer.ts # Email service
├── middlewares/ # Express middleware
│ ├── validators/ # Input validation (always required)
│ └── auth.ts # Authentication middleware
├── helpers/ # Utility functions
└── initializers/ # App startup and constants
```
### Key Configuration Files
- `package.json` - Main dependencies and scripts
- `server/package.json` - Server-specific config
- `eslint.config.mjs` - Linting rules
- `tsconfig.base.json` - TypeScript base config
- `config/default.yaml` - Default app configuration
- `.mocharc.cjs` - Test runner configuration
### Shared Packages (`packages/`)
```
packages/
├── models/ # Shared TypeScript interfaces (modify for API changes)
├── core-utils/ # Common utilities
├── ffmpeg/ # Video processing
├── server-commands/ # Test helpers
└── tests/ # Test files
```
### Scripts Directory (`scripts/`)
- `scripts/build/` - Build automation
- `scripts/dev/` - Development helpers
- `scripts/ci.sh` - Continuous integration runner
- `scripts/test.sh` - Test runner
## Continuous Integration Pipeline
**GitHub Actions** (`.github/workflows/test.yml`):
1. **Matrix Strategy**: Tests run in parallel across different suites
2. **Required Services**: PostgreSQL, Redis, LDAP, S3, Keycloak containers
3. **Test Suites**: `types-package`, `client`, `api-1` through `api-5`, `transcription`, `cli-plugin`, `lint`, `external-plugins`
4. **Environment**: Ubuntu 22.04, Node.js 20.x
5. **Typical Runtime**: 15-30 minutes per suite
**Pre-commit Checks**: ESLint, TypeScript compilation, OpenAPI validation
## Making Code Changes
### Adding New API Endpoint
1. Create controller in `server/core/controllers/api/`
2. Add validation middleware in `server/core/middlewares/validators/`
3. Register route in `server/core/controllers/api/index.ts`
4. Update shared types in `packages/models/`
5. Add OpenAPI documentation tags
6. Write tests in `packages/tests/src/api/`
### Common Patterns to Follow
```typescript
// Controller pattern
import express from 'express'
import { apiRateLimiter, asyncMiddleware } from '../../middlewares/index.js'
const router = express.Router()
router.use(apiRateLimiter) // ALWAYS include rate limiting
router.get('/:id',
validationMiddleware, // ALWAYS validate inputs
asyncMiddleware(handler) // ALWAYS wrap async handlers
)
```
### Database Changes
1. Create/modify Sequelize model in `server/core/models/`
2. Generate migration in `server/core/initializers/migrations/`
3. Update shared types in `packages/models/`
4. Run `npm run build:server` to compile
## Validation Steps Before PR
1. **Build**: `npm run build` (must succeed)
2. **Lint**: `npm run lint` (must pass without errors)
5. **OpenAPI**: Validate if API changes made
## Common Error Solutions
**Build Errors:**
- "Cannot find module": Run `yarn install --frozen-lockfile`
- "PostgreSQL connection": Check PostgreSQL is running and extensions installed
- TypeScript errors: Check Node.js version (must be >=20.x)
**Test Errors:**
- Permission denied: Ensure PostgreSQL user has createdb/superuser rights
- Port conflicts: Stop other PeerTube instances
- Import test failures: Set `DISABLE_HTTP_IMPORT_TESTS=true`
**Development Issues:**
- "Client dist not found": Run `npm run build:client` (only if working on client features)
- Redis connection: Ensure Redis server is running
- Hot reload not working: Kill all Node processes and restart
## Trust These Instructions
These instructions have been validated against the current codebase. Only search for additional information if:
- Commands fail with updated error messages
- New dependencies are added to package.json
- Build system changes are detected
- You need specific implementation details not covered here
Focus on server-side TypeScript development in `server/core/` and ignore the `client/` directory unless explicitly working on frontend integration.

View File

@@ -27,7 +27,7 @@ jobs:
# FIXME: https://github.com/actions/checkout/issues/290
git fetch --force --tags
one="{ \"build-peertube\": true, \"file\": \"./support/docker/production/Dockerfile.bookworm\", \"ref\": \"develop\", \"tags\": \"chocobozzz/peertube:develop-bookworm\" }"
one="{ \"build-peertube\": true, \"file\": \"./support/docker/production/Dockerfile\", \"ref\": \"develop\", \"tags\": \"chocobozzz/peertube:develop-trixie,chocobozzz/peertube:develop\" }"
two="{ \"build-peertube\": true, \"file\": \"./support/docker/production/Dockerfile.bookworm\", \"ref\": \"master\", \"tags\": \"chocobozzz/peertube:production-bookworm,chocobozzz/peertube:$(git describe --abbrev=0)-bookworm\" }"
three="{ \"build-peertube\": false, \"file\": \"./support/docker/production/Dockerfile.nginx\", \"ref\": \"master\", \"tags\": \"chocobozzz/peertube-webserver:latest\" }"

View File

@@ -34,7 +34,7 @@ jobs:
run: |
wget "https://github.com/boyter/scc/releases/download/v3.0.0/scc-3.0.0-x86_64-unknown-linux.zip"
unzip "scc-3.0.0-x86_64-unknown-linux.zip"
./scc --format=json --exclude-dir .git,node_modules,client/node_modules,client/dist,dist,yarn.lock,client/yarn.lock,client/src/locale,test1,test2,test3,client/src/assets/images,config,storage,packages/tests/fixtures,support/openapi,.idea,.vscode,docker-volume,ffmpeg-3,ffmpeg-4 > ./scc.json
./scc --format=json --exclude-dir .git,node_modules,client/node_modules,client/dist,dist,pnpm-lock.yaml,client/src/locale,test1,test2,test3,client/src/assets/images,config,storage,packages/tests/fixtures,support/openapi,.idea,.vscode,docker-volume,ffmpeg-3,ffmpeg-4 > ./scc.json
- name: PeerTube client stats
if: github.event_name != 'pull_request'

View File

@@ -38,6 +38,14 @@ jobs:
ports:
- 9444:9000
keycloak:
image: chocobozzz/peertube-tests-keycloak
ports:
- 8082:8080
env:
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: admin
strategy:
fail-fast: false
matrix:
@@ -90,6 +98,15 @@ jobs:
~/.cache/huggingface
key: ${{ runner.OS }}-${{ matrix.test_suite }}-hugging-face-v1
# Transcription tools take a lot of disk space, we need to cleanup before running transcription tests
- name: Cleanup disk space
if: matrix.test_suite == 'transcription' || matrix.test_suite == 'external-plugins'
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
sudo docker image prune --all --force
sudo docker builder prune -a
df -h
- name: Set env test variable (schedule)
if: github.event_name != 'schedule'
run: |

2
.gitignore vendored
View File

@@ -1,9 +1,7 @@
# NPM instalation
node_modules
*npm-debug.log
yarn-error.log
*-ci.log
.yarn
# Testing
/test1/

View File

@@ -1,5 +1,260 @@
# Changelog
## v7.3.0
### IMPORTANT NOTES
* Minimum supported NodeJS version is `20.19`
### NGINX
* Disable request buffering on upload endpoints to fix HTTP request timeouts: https://github.com/Chocobozzz/PeerTube/commit/d1a35e8421195088e2754b787c4af1e765b9eaa9
### Plugins/Themes/Embed API
* **Breaking change** Plugin and themes must use `:root` CSS selector instead of `body` to inject CSS variables
* Add server API (https://docs.joinpeertube.org/api/plugins):
* Support `externalRedirectUri` for `registerExternalAuth` so PeerTube redirects users on another URL set by the plugin
* If your plugin uses `filter:email.template-path.result` server hook: emails now use Handlebars template engine instead of Pug template engine
### Features
* :tada: Emails can now be translated :tada: Check the [translation documentation](https://docs.joinpeertube.org/support/doc/translation) to help us translate emails in your language!
* :tada: Introduce a web configuration wizard to help administrators to configure their instance automatically :tada:
* The wizard appears once the administrators have logged in following the installation of the PeerTube instance
* Admins can also run the wizard via a button in the web admin config
* The main instance information (e.g. name, short description, logo, primary colour) can be entered using the wizard.
* It also helps the admin to apply a configuration depending on the instance type (community-based, institutional, private)
* :tada: Redesign the admin config to use a lateral menu for navigating between subsections :tada:
* Add a new *Customization* page to easily change the main colors and shape of the client interface
* Add a new *Logo* page where admins can upload logos/favicon and social media images for their instances
* Add an option to set the default licence, privacy and comments policy when publishing videos
* The email prefix and body can now be changed in the web admin config. These configurations also support the `{{instanceName}}` template variable, which is replaced by the instance name
* Improve admin federation control:
* Add the ability for admins to completely disable remote subscriptions to local channels
* Admins can also set up automatic rejection of video comments from remote instances
* Add 2FA column information in admin users overview table
* Display remote runner version in admin
* Add ability for users to set the planned date of a live. These lives are displayed when browsing videos [#7144](https://github.com/Chocobozzz/PeerTube/pull/7144)
* Improve data tables UX/UI
* Improve account/channel playlists management:
* Use a data table to manage account and channel playlists
* Allow to manually set the order of the public playlists displayed in a channel
* Improve sensitive content warning in embed player
* Improve audio transcoding quality, especially with FLAC input
* Support Creole French languages in video language metadata
* Add ability for users to list and revoke token sessions
* Support *Free of known copyright restrictions* and *Copyrighted - All Rights Reserved* video licence metadata
* Play/pause the video player using `k` key
### Bug fixes
* Fix ActivityPub audience for unlisted videos
* Use an array of URL in `attributedTo` ActivityPub field
* Prefer `og:image` instead of `og:image:url`
* Better thumbnail blur for sensitive content [#7105](https://github.com/Chocobozzz/PeerTube/pull/7105)
* Prefer `allow="fullscreen"` for video embed `iframe` [#7043](https://github.com/Chocobozzz/PeerTube/pull/7043)
* Respect the sensitive content policy, even for videos owned by the user
* Fix the issue of the scroll position not being restored when pages load slowly [#7143](https://github.com/Chocobozzz/PeerTube/pull/7143)
* Fix remote actor follow counter after a local subscription
* Fix reloading videos in *Browser videos* when the link only changes query parameters
* Add stall job check for remote studio and transcription runner jobs
* Prevent metric warning for redundancy gauge
* Fix disabling *Wait transcoding* checkbox
* Correctly import new elements of a playlist in channel synchronization
* Fix overflow in discover page
* Fix restoring scroll position when going back in the web browser on the homepage set by the admin
* Fill video support on channel sync
* Respect instance default privacy setting when publishing imports and lives
* Remove useless help for live transcoding
* Fix RTL margins on some components
## v7.2.3
### SECURITY
* Upgrade `multer` dependency to prevent Denial of Service with a malformed request
### Bug fixes
* Fix channel synchronization that duplicates video imports
## v7.2.2
### SECURITY
* Prevent ReDOS from `useragent` package by removing deprecated Do Not Track feature. Thanks to Patrick Bohn Matthiesen and [Leonora](https://github.com/herover) from IT University of Copenhagen for reporting this vulnerability!
### Bug fixes
* Correctly display bulk actions button in "My videos"
* Keep playlist name original casing in "My videos"
* Fix PIP button z-index on Firefox
* More robust S3 upload and ACL error handler
* Fix broken video state on S3 move failure
* Reset filters when loading query params in "Browse videos"
* Fix upload tab title when the file is uploaded
* Fix follow card overflow in about page
* Convert to full UUID request param `id` in `filter:html.embed.video.allowed.result` and `filter:html.embed.video-playlist.allowed.result` plugin hooks
* Fix HLS playback issue on Chrome 138
* Fix selecting frame on Safari
* Fix input search with multiple prefix tokens
* Fix channel sync duplicate after video deletion
* Fix caption raw edition when editing segment
* Fix accessibility issues:
* Fix embed title/avatar accessibility
* Add player P2P up/down info aria label
* Support escape key in the player settings menu
* Support arrow left/right navigation in the settings menu
* Fix entry focus when navigating in the settings menu
* Add aria controls attribute to settings button
* Thanks to [Woebin](https://github.com/Woebin) from [Access Lab](https://axesslab.com/) and [HowlRound Theatre Commons](https://howlround.com/) for conducting the player accessibility audit!
## v7.2.1
### Bug fixes
* Fix federation of sensitive videos with previous PeerTube versions
* Do not uppercase video tags to prevent accessibility issues
* Fix support field not automatically filled from channel data when publishing a video
* Fix "Add new playlist" broken style
* Fix browse videos page title on web browser "History Back"
* Fix parent menu highlighting in *About Platform* pages
* Don't display description/terms titles if these blocks are empty
* Correctly load count and rows per page when listing *My videos*
## v7.2.0
### IMPORTANT NOTES
* **Important** You need to manually execute a migration script after your upgrade while PeerTube is running and the database migration is complete (`Migrations finished. New migration version schema: xxx` in PeerTube startup logs):
* Classic installation: `cd /var/www/peertube/peertube-latest && sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production node dist/scripts/migrations/peertube-7.2.js`
* Docker installation: `cd /var/www/peertube-docker && docker compose exec -u peertube peertube node dist/scripts/migrations/peertube-7.2.js`
### SECURITY
* If you installed PeerTube using the [official documentation](https://docs.joinpeertube.org/install/any-os#installation), we highly recommend setting the default user shell to `nologin`. For example on GNU/Linux: `chsh -s /usr/sbin/nologin peertube`
* If you installed PeerTube runners using the [official Systemd service documentation](https://docs.joinpeertube.org/maintain/tools#as-a-systemd-service), we highly recommend setting the default user shell to `nologin`. For example on GNU/Linux: `chsh -s /usr/sbin/nologin prunner`
### Configuration
* Prefer to not store lives in object storage by default: `object_storage.streaming_playlists.store_live_streams` is now `false` in the config template
* Use `hot` trending algorithm by default: `trending.videos.default` is now `hot` in the config template
* Add global rate limit to video download that can be changed by `download_generate_video.max_parallel_downloads`
### Docker
* Add missing docker env options to configure live settings [#6948](https://github.com/Chocobozzz/PeerTube/pull/6948)
* Expose NGINX logs folder in `docker-compose.yml` [#6963](https://github.com/Chocobozzz/PeerTube/pull/6963)
* Add exec to NGINX process to ensure is PID 1 and then ensure a graceful shutdown[#7041](https://github.com/Chocobozzz/PeerTube/pull/7041)
### NGINX
* Fix max body size inconsistency with PeerTube backend: https://github.com/Chocobozzz/PeerTube/commit/a2812e40d90619528a6b2a4c491640a9737f8f3c
### Plugins/Themes/Embed API
* **Breaking change** Theme CSS must include `--is-dark: 0` or `--is-dark: 1` CSS variable for the `body` so PeerTube understands if it's a dark or a light theme
* Add server plugin hooks (https://docs.joinpeertube.org/api/plugins):
* `filter:email.subject.result` & `filter:email.template-path.result` [#6876](https://github.com/Chocobozzz/PeerTube/pull/6876)
### Features
* :tada: Redesign *Manage my videos* page :tada:
* Redesign the page to list more videos for a clearer overview
* Add sort, pagination and column display settings
* Add channel buttons to quickly filter videos
* Improve video search & filters
* Add ability to display video comments count [#6635](https://github.com/Chocobozzz/PeerTube/pull/6635)
* :tada: Redesign video management/publication pages :tada:
* Migrate the video update page to a *Manage video* tool, that includes *Studio* and *Stats* features
* Video publication privacy choice is moved in the second step
* Use a lateral menu to navigate between *Manage video* pages
* Add information related to the video state (transcoding, etc.) and clearly display unavailable features
* Add user agent stats to video stats [#6871](https://github.com/Chocobozzz/PeerTube/pull/6871)
* Support drag-and-drop to replace the video file [#6970](https://github.com/Chocobozzz/PeerTube/pull/6970)
* :tada: Improve NSFW/sensitive content system :tada:
* Support content warning so video authors can describe why the video is considered sensitive
* Change the *Blur* sensitive content policy for viewers where the miniature name is not blurred anymore
* Add an additional *Warn* sensitive content policy for viewers where the thumbnail is not blurred
* *Blur* and *Warn* policies add a *Sensitive* icon below the thumbnail. A warning is also displayed in the player
* The player embed now displays the sensitive content warning
* Add ability to set predefined sensitive flags to videos so video authors help to identify specific sensitive content
* If enabled by administrators, users can override their default sensitive content policy for specific flags.
For example, they can hide all sensitive content but display with a warning content flagged as *Violent* by video authors
* Add sensitive content filter in admin videos overview
* Allow users to resend the email verification link when changing their current email
* Inject subtitle links in HLS playlists so it's easier for external video players that use the `master.m3u8` playlist to display subtitles
* Disable log coloration when TTY does not support it [#6988](https://github.com/Chocobozzz/PeerTube/pull/6988)
* Support more embed parameters in custom markup (`<peertube-video-embed>` and `<peertube-playlist-embed>`) [#6989](https://github.com/Chocobozzz/PeerTube/pull/6989)
### Bug fixes
* More robust theme CSS variables injection
* Fix podcast feed URL in subscribe button
* Fix podcast feed download extension when the file is a video
* Fix broken downloaded audio file
* Fix crash on download stream error
* Fix local posts counter in NodeInfo
* Run transcription after file replacement
* Better video chapters parsing from the description
* Correctly handle `generateTranscription` body param on upload/import
* Fix federation compatibility with GoToSocial
* Fix PeerTube account client redirection
* Prevent plugins to log exceptions
* Fix broken replay on live privacy change
* Fix iOS/Android deep link with URL that contains query params in watch page
* Fix ownership changes count
* Always specify object storage content type
* Fix broken live title in Chinese
* Fix theme crash in embed
* Fix broken video state on move on object storage failure
* Fix CORS issue with object storage providers
* Correctly display images in support modal
## v7.1.1
### SECURITY
This release fixes important vulnerabilities discovered by Ori Hollander of the JFrog Vulnerability Research team. Many thanks to them!
* Fix DoS and blind SSRF on ActivityPub playlist creation [CVE-2025-32948](https://research.jfrog.com/vulnerabilities/peertube-activitypub-playlist-creation-blind-ssrf-dos/)
* Prevent infinite loop DoS when crawling ActivityPub data [CVE-2025-32947](https://research.jfrog.com/vulnerabilities/peertube-activitypub-crawl-dos/)
* Prevent an attacker from adding playlists to a another user's channel using the ActivityPub [CVE-2025-32946](https://research.jfrog.com/vulnerabilities/peertube-arbitrary-playlist-creation-activitypub/)
* Prevent an attacker from adding playlists to a another user's channel using the REST API [CVE-2025-32945](https://research.jfrog.com/vulnerabilities/peertube-arbitrary-playlist-creation-rest/)
* Add protection against [ZIP bomb](https://en.wikipedia.org/wiki/Zip_bomb) on user import [CVE-2025-32949](https://research.jfrog.com/vulnerabilities/peertube-archive-resource-exhaustion/)
* Prevent crash on user import with a ZIP containg an illegal filename [CVE-2025-32944](https://research.jfrog.com/vulnerabilities/peertube-archive-persistent-dos/)
* Do not leak private HLS playlists (`.m3u8` files) [CVE-2025-32943](https://research.jfrog.com/vulnerabilities/peertube-hls-path-traversal/)
### Bug fixes
* Fix playlist page margins
* Fix danger button border
* Fix unsubscribe button label for channels
* Fix remote subscribe on iOS
* Add Podcast feed to subscribe button
* Always display technical information tab in *About* page
* Fix menu button auto font-size to prevent overflow in some locales
* Correctly inject multiple `rel="me"` links with supported markdown fields
* Fix adding studio watermark with audio/video split HLS file
* Reset video state on studio failure
* Fix updating a user in administration
* Fix error when getting a S3 object with some S3 providers
* Specify charset when uploading caption files in S3
* Fix theme color parsing with some web browsers
* Improve channel description in custom markup miniature
* Ensure ffmpeg process is killed if download is aborted
* Correctly reload playlist on playlist change in watch page
* Use `indexifembedded` in embeds instead of `noindex`
* Fix extra space on links of remote comments
* Don't convert webp images to jpeg
## v7.1.0
### IMPORTANT NOTES

View File

@@ -3,20 +3,23 @@
* Chocobozzz
* Rigel Kent
* DignifiedSilence
* Александр
* T.S
* josé m
* Александр
* Hồ Nhất Duy
* Jeff Huang
* josé m
* Milo Ivir
* Ihor Hordiichuk
* Filip Bengtsson
* fran secs
* kontrollanten
* Payman Moghadam
* Berto Te
* kontrollanten
* Milo Ivir
* Simon Brosdetzko
* Jiri Podhorecky
* Phongpanot
* Sveinn í Felli
* Hannes Ylä-Jääski
* GunChleoc
* hecko
* Laurent Ettouati
@@ -24,65 +27,76 @@
* Zet
* Ewout van Mansom
* Aitor Salaberria
* Sveinn í Felli
* Leif-Jöran Olsson
* Clemens Schielicke
* Luca Calcaterra
* Racida S
* Marcin Mikołajczak
* Eivind Ødegård
* Balázs Meskó
* Tirifto
* Marcin Mikołajczak
* Wicklow
* Blood Axe
* Eivind Ødegård
* John Livingston
* Hannes Ylä-Jääski
* Kim
* Tirifto
* Besnik Bleta
* Kim
* Vodoyo Kamal
* Jiří Podhorecký
* Armin
* Fontan 030
* ButterflyOfFire
* Mohamad Reza
* Quentin PAGÈS
* Kimsible
* Felix Ableitner
* Frank Sträter
* Free coss
* Ettore Atalan
* Andrea Gavioli
* Mürteza MERT
* Gérald Niel
* ButterflyOfFire
* Duy
* Eric Guichaoua
* Renne Rocha
* Slimane Selyan AMIRI
* Dingzhong Chen
* Eric Guichaoua
* Filip Hanes
* Julien Maulny
* Mark Van den Borre
* x
* Booteille
* Manuel Viens
* Jorropo
* Josh Morel
* Renne Rocha
* dxuser514
* BO41
* Ettore Atalan
* Marc Strange
* vachan
* AP
* Elegant Codes
* Florian CUNY
* Francesc
* alex gabilondo
* mando laress
* Ľubomír Šima
* Артём Котлубай
* Fjuro
* Ricardo Biloti
* 0que
* Blood Axe
* Cedric F
* Florent
* Marc Strange
* Ricardo Simões
* lutangar
* Ch
* J. Lavoie
* Luc Didry
* YILDIRIM YAPRAK
* alex gabilondo
* barzofarev2
* jan Seli
* 李奕寯
* Erik Guldberg
* Kempelen
* Kerim Demirkaynak
* Martin Hoefler
* Porrumentzio
* Poslovitch
@@ -91,67 +105,75 @@
* Alexander Ivanov
* Balázs Úr
* Echo Kilo
* Erik Guldberg
* Jan Keromnes
* Jiří Podhorecký
* Luc Didry
* Siourdakis Thanos
* Thomas Citharel
* knuxify
* tray
* Adrià Martín
* Agron Selimaj
* Attila F
* Caroline Chuong
* David Soh
* Diazepan Medina
* Jason Zhou
* Kerim Demirkaynak
* Loukas Stamellos
* Ms Kimsible
* NorbiPeti
* Sergey Zigachev
* Thomas Citharel
* Txopi
* Benjamin Bouvier
* Filip Hanes
* Cavernosa
* Ghost of Sparta
* Joe Bill
* Julien
* Jure Repinc
* Kemal Oktay Aktoğan
* Lucas Declercq
* Ryan He
* Sirxy
* Viorel-Cătălin Răpițeanu
* matograine
* Adrià Martín
* 偶尔来巡山
* Ahmed ABERWAG
* Daniel Santos
* David Libeau
* Ewald Arnold
* Florent F
* Florent Poinsaut
* Ignacio Carrera González
* Jayme Soares Almeida Cruz
* Lety Does Stuff
* Nassim Bounouas
* Rafael Fontenelle
* Thomas Kuntz
* Tzafrir Cohen
* Viorel-Cătălin Răpițeanu
* Vri
* miro
* nexi
* owiox8+1viroxeaziaxw@sharklasers.com
* spf
* wazakovsky
* yns bag
* Anne-Gaelle Moulun
* Arman
* Asier Iturralde Sarasola
* BRAINS YUM
* Belkacem Mohammed
* Bob Oob
* Côme 744
* Dimitri Gilbert
* Flavio F. M
* Florent Poinsaut
* Frank Chang
* Green-Star
* I_Automne
* Ilia
* Marek Ľach
* Micah Elizabeth Scott
* Pierre-Jean
* Ret Samys
* SVNET Libre
* StarAtt
* Tomasz
* Tony Simoes
* William Lahti
@@ -160,18 +182,18 @@
* boris joeson
* frankstrater
* mater
* spf
* test2a
* think4web
* 路过是好事
* Ajeje Brazorf
* Andreas Grupp
* Andrey
* Angristan
* Benjamin Seitz
* Bob Oob
* Booteille
* Cirnos
* Cokelat8
* DontUseGithub
* Eder Etxebarria
* Farooq Karimi Zadeh
* Frederic Bezies
* Iñigo
@@ -180,24 +202,30 @@
* José M
* Kristoffer Grundström
* LecygneNoir
* Liu Zhiyu
* Lukas
* MahdiTurki
* Martijn Dekker
* Mats Blomdahl
* Maxime Louet
* Mildred
* Murat Hasdemir
* Murat Özalp
* Nikolay
* Okhin
* Osama
* Pierre-Alain TORET
* Serge Victor
* Théo Le Calvar
* Ugaitz
* Vaclovas Intas
* Vincent Finance
* aschaap
* clementbrizard
* gohoso9454
* helabasa
* kaiyou
* max
* roberto marcolin
* Ahsan Haris Ahmed
* Alberto Teira
@@ -212,11 +240,12 @@
* Asr128
* Aurélien Bertron
* Axel Viala
* Casper Ruttten
* Charles-Edouard Gervais
* Danail Emandiev
* Daniele Garau
* Dep Pranata
* Dirk Kelly
* Eder Etxebarria
* Ehsan Gholami
* Elga Ahmad Prayoga
* Girish Ramakrishnan
@@ -237,13 +266,14 @@
* Lukas Winkler
* M Z
* Manuela Silva
* Marian
* Morpheus Tao
* Mélanie Chauvel
* Natsuki Tsukishiro
* Paolo Mauri
* Pedro
* Petr Balíček
* Piotr Sikora
* Ryan He
* Stardream
* Stefan Keks
* Tom Wellington
@@ -259,8 +289,10 @@
* h3n3
* iapellaniz
* jonathanraes
* legiorange
* numéro6
* saleh oukiki
* Àngel Pérez Beroy
* Ömer Faruk Çakmak
* AQR_Rastiq
* Al-Hassan Abdel-Raouf
@@ -277,13 +309,14 @@
* Average Dude
* BGR2
* BitTube
* Boo
* Boo Teille
* Branislav Pavelka
* Casper Ruttten
* Dashie
* David Luís Pereira Pires
* David Marzal
* Doug Luce
* Emv
* EndoGai
* Fatih Özsoy
* FediverseTV
@@ -304,6 +337,8 @@
* Jan Hartig
* Jan Marsalek
* Jerguš Fonfer
* Jeroen de Wijn
* José Daniel Angulo Plata
* Joël Galeran
* Julien Lemaire
* Julien Rabier
@@ -314,11 +349,12 @@
* Mondo Xíbaro
* Moritz Warning
* Mostafa Ahangarha
* Murat Özalp
* Neko Nekowazarashi
* Nicolai Larsen
* Nojus
* Olivier Bouillet
* Pedro hates github.com
* Pep
* Pierre Jaury
* Piotr Strębski
* Puryx
@@ -328,19 +364,24 @@
* SerCom_KC
* Skid
* Stakovicz
* Suthep
* Takeshi Umeda
* Thai Localization
* The Cashew Trader
* Thijs Kinkhorst
* Timur Seber
* Toso Malero
* Tsuki
* Túlio Simões Martins Padilha
* Valvin
* XblateX
* Yaron Shahrabani
* YiDai
* Yogesh K S
* ahmadsharifian
* bopol
* brucekomike
* darek
* dingycle
* framail
* imgradeone Yan
@@ -348,13 +389,13 @@
* les
* libertas
* merty
* ou jian bo
* plr20
* q_h
* qwerty
* taziden
* vancha march
* victor héry
* Àngel Pérez Beroy
* 3risian
* A.D.R.S
* Acid Chicken (硫酸鶏)
@@ -368,6 +409,7 @@
* Alberto Mardegan
* Alejandro Criado-Pérez
* Aleksandr Sokolov
* Alessandro Molina
* Alexander F. Rødseth
* Ali Alim
* Alperen Abak
@@ -388,7 +430,7 @@
* Ben Lubar
* Benjamin EWFT
* Benoît Piédallu
* Boo
* Bojidar Marinov
* Brad Johnson
* Cadence Ember
* Cale
@@ -397,15 +439,16 @@
* Charlie Lambda
* Christoph Geschwind
* Chronos
* Cirnos
* Claude
* Clifford Garwood II
* Clément Brizard
* Cédric Bahirwe
* DLP
* Daniel Dutra
* David Baumgold
* David Dobryakov
* DeeJayBro
* Denis Dupont
* Deval
* Dimitri DI GUSTO
* Dimitrios Glentadakis
@@ -418,6 +461,7 @@
* Erwan Croze
* Esmail_Hazem
* Ethan Corgatelli
* FB
* Fabio Agreles Bezerra
* FediThing
* Fernandez, ReK2
@@ -433,6 +477,7 @@
* Henri BAUDESSON
* HesioZ
* Hozan Şahin
* Hydrolien
* ICabaleiro
* Iker Garaialde
* Ismaël Bouya
@@ -440,6 +485,7 @@
* Iván Cabaleiro
* J Webb
* Jacen
* Jackson
* Jackson Chen
* Jacob
* Jacques Foucry
@@ -453,6 +499,7 @@
* Jeston Tan
* Jinn Koriech
* Jlll1
* Johan van Dongen
* Johnny Jazeix
* Jonas Sulzer
* Jonatan Nyberg
@@ -465,24 +512,27 @@
* Kent Anderson
* Kevin Cope
* Kevin Pliester
* Khyvodul
* Knackie
* Kody
* Konstantinos Agiannis
* Kyâne Pichou
* Leo Mouyna
* Lesterpig
* Lety Does Stuff
* Levi Bard
* LiPeK
* Lint
* LoveIsGrief
* Luca B
* Lucian I. Last
* Lucien A
* Lupinard
* Léane GRASSER
* Léo Andrès
* ManMade-cube42
* Marcel Fuhrmann
* Marco Zehe
* Marcus Schwarz
* Marian Steinbach
* Mario Pepe
* Markus Richter
@@ -491,11 +541,14 @@
* Mateusz Piotrowski
* Mathieu Agopian
* Mathieu Brunot
* Matthias Frey
* Matthieu De Beule
* Max Rosenfors
* Michael Koppmann
* Michael Williams
* Midgard
* Miguel Mayol Tur
* Miguel P.L
* Mike
* Mikel Gartzia Santamaria
* Milo van der Linden
@@ -510,10 +563,11 @@
* Novel Martin Harianto
* Nuño Sempere
* Olivier Jolly
* Oliwier Jaszczyszyn
* Pablo Joubert
* Paul FLORENCE
* Paul V
* Pedro hates github.com
* Pavel 7 Tomsk
* PhieF
* Philip Durbin
* Philipp Fischbeck
@@ -522,15 +576,18 @@
* Quantic Axe
* Quentin Dupont
* Quentí
* RF9A5V
* ROPEDE
* Ramazan Geven
* Ramiellll
* Rangel Prodanov
* Raphael
* Raphaël Droz
* Ray
* Rebecca
* Rech
* Rep Dolsay
* RiQuY
* Robert Riemann
* Roberto Resoli
* Robin
@@ -542,6 +599,7 @@
* Scott Starkey
* Sebastian Paweł Wolski
* Seth Falco
* Shalabh Agarwal
* Showfom
* Shun Sakai
* Simon Gilliot
@@ -549,8 +607,10 @@
* Stefan Schüller
* Steffen
* Steffen Möller
* Subh B
* Sumit Khanna
* SupC
* Sébastien NOBILI
* TA
* Tanguy BERNARD
* Thavarasa Prasanth
@@ -562,7 +622,6 @@
* Tomás Sebastián Romero
* TrashMacNugget
* Treacle
* Tsuki
* Unetelle Inconnue
* Vagelis F
* Varik Valefor
@@ -577,10 +636,12 @@
* Yehuda Deutsch
* Yorwba
* Yun
* Zack Birkenbuel
* Zekovski
* Zig-03
* [ Bie ] Watcharapong Suriyawan
* adam iter
* allmiha2
* anmol26s
* april
* ar9708
@@ -600,7 +661,6 @@
* jomo
* kukhariev
* lambdacastix
* legiorange
* libertysoft3
* lost_geographer
* lsde
@@ -624,16 +684,19 @@
* philippe lhardy
* pitchum
* potedeo
* q0ntinuum
* rdxuan
* retiolus
* ruvilonix
* sanchis
* skyone-wzw
* slendermon
* smilekison
* sn0wygecko
* soonsouth
* thecashewtrader
* tilllt
* tmpod
* tomamplius
* toobad
* treac1e
@@ -646,6 +709,7 @@
* Артур Кирпо
* Дмитрий Кузнецов
* noisawe
* 姚霁恒
* abdhessuk
* abidin24
* aditoo
@@ -782,6 +846,7 @@
* `peertube-x` by Solen DP (CC-BY)
* `flame` by Freepik (Flaticon License)
* `local` by Larea (CC-BY)
* X (Twitter) icon: [Wikimedia Commons](https://fr.m.wikipedia.org/wiki/Fichier:X_logo_2023.svg)
# Contributors to our 2020 crowdfunding :heart:

View File

@@ -172,7 +172,7 @@ See our [ActivityPub documentation](https://docs.joinpeertube.org/api/activitypu
### Code
Copyright (C) 2015-2024 PeerTube Contributors (see [CREDITS.md](/CREDITS.md))
Copyright (C) 2015-2025 PeerTube Contributors (see [CREDITS.md](/CREDITS.md))
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published

View File

@@ -0,0 +1,5 @@
# Changelog
## v1.0.3
* Fix `util.isArray` deprecation warning

View File

@@ -10,8 +10,7 @@ See https://docs.joinpeertube.org/maintain/tools#remote-tools
```bash
cd peertube-root
yarn install --pure-lockfile
cd apps/peertube-cli && yarn install --pure-lockfile
npm run install-node-dependencies
```
## Develop

View File

@@ -1,6 +1,6 @@
{
"name": "@peertube/peertube-cli",
"version": "1.0.2",
"version": "1.0.3",
"type": "module",
"main": "dist/peertube.js",
"bin": "dist/peertube.js",

View File

@@ -16,7 +16,6 @@ export function defineAuthProgram () {
.option('-p, --password <token>', 'Password')
.option('--default', 'add the entry as the new default')
.action(options => {
/* eslint-disable no-import-assign */
prompt.override = options
prompt.start()
prompt.get({
@@ -39,7 +38,6 @@ export function defineAuthProgram () {
}
}
}, async (_, result) => {
// Check credentials
try {
// Strip out everything after the domain:port.
@@ -111,11 +109,13 @@ export function defineAuthProgram () {
}
})
program.addHelpText('after', '\n\n Examples:\n\n' +
' $ peertube auth add -u https://peertube.cpy.re -U "PEERTUBE_USER" --password "PEERTUBE_PASSWORD"\n' +
' $ peertube auth add -u https://peertube.cpy.re -U root\n' +
' $ peertube auth list\n' +
' $ peertube auth del https://peertube.cpy.re\n'
program.addHelpText(
'after',
'\n\n Examples:\n\n' +
' $ peertube auth add -u https://peertube.cpy.re -U "PEERTUBE_USER" --password "PEERTUBE_PASSWORD"\n' +
' $ peertube auth add -u https://peertube.cpy.re -U root\n' +
' $ peertube auth list\n' +
' $ peertube auth del https://peertube.cpy.re\n'
)
return program

View File

@@ -99,7 +99,6 @@ async function listRedundanciesCLI (options: CommonProgramOptions & { target: Vi
if (target === 'remote-videos') {
const tmp = streamingPlaylists.reduce((a, b) => a + b.size, 0)
// FIXME: don't use external dependency to stringify bytes: we already have the functions in the client
totalSize = bytes(tmp)
}
@@ -137,11 +136,11 @@ async function addRedundancyCLI (options: { video: number } & CommonProgramOptio
console.log('Video will be duplicated by your instance!')
} catch (err) {
if (err.message.includes(HttpStatusCode.CONFLICT_409)) {
throw new Error('This video is already duplicated by your instance.')
throw new Error('This video is already duplicated by your instance.', { cause: err })
}
if (err.message.includes(HttpStatusCode.NOT_FOUND_404)) {
throw new Error('This video id does not exist.')
throw new Error('This video id does not exist.', { cause: err })
}
throw err

View File

@@ -72,7 +72,12 @@ export function defineUploadProgram () {
await run({ ...options, url, username, password })
} catch (err) {
console.error('Cannot upload video: ' + err.message)
if (err.code === 'ECONNREFUSED') {
console.error(`Server is not responding`)
} else {
console.error('Cannot upload video: ' + err.message)
}
process.exit(-1)
}
})
@@ -127,7 +132,7 @@ async function buildVideoAttributesFromCommander (server: PeerTubeServer, option
waitTranscoding: true
}
const booleanAttributes: { [id in keyof typeof defaultBooleanAttributes]: boolean } | {} = {}
const booleanAttributes: { [id in keyof typeof defaultBooleanAttributes]: boolean } = {} as any
for (const key of Object.keys(defaultBooleanAttributes)) {
if (options[key] !== undefined) {

View File

@@ -72,8 +72,7 @@ function getRemoteObjectOrDie (
settings: Settings,
netrc: Netrc
): { url: string, username: string, password: string } {
function exitIfNoOptions (optionNames: string[], errorPrefix: string = '') {
function exitIfNoOptions (optionNames: string[], errorPrefix = '') {
let exit = false
for (const key of optionNames) {
@@ -126,9 +125,9 @@ function listOptions (val: string) {
function getServerCredentials (options: CommonProgramOptions) {
return Promise.all([ getSettings(), getNetrc() ])
.then(([ settings, netrc ]) => {
return getRemoteObjectOrDie(options, settings, netrc)
})
.then(([ settings, netrc ]) => {
return getRemoteObjectOrDie(options, settings, netrc)
})
}
function buildServer (url: string) {
@@ -184,11 +183,8 @@ export {
getRemoteObjectOrDie,
writeSettings,
deleteSettings,
getServerCredentials,
listOptions,
getAdminTokenOrDie,
buildServer,
assignToken

View File

@@ -1,236 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@colors/colors@1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
application-config-path@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/application-config-path/-/application-config-path-1.0.0.tgz#9c25b8c00ac9a342db27275abd3f38c67bbe5a05"
integrity sha512-6ZDlLTlfqrTybVzZJDpX2K2ZufqyMyiTbOG06GpxmkmczFgTN+YYRGcTcMCXv/F5P5SrZijVjzzpPUE9BvheLg==
application-config@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/application-config/-/application-config-3.0.0.tgz#9adec84dd2d81e97dd78ea0dffcbf97381a1f55c"
integrity sha512-7ViR4soQJDx2O9iLf1vGxvekkPqvwqV/AZ2OL3DNcAQrg03UjJE1VeBk7oYNoN9AKB0eNyVrcM7kPD30NKeLLw==
dependencies:
application-config-path "^1.0.0"
load-json-file "^7.0.1"
write-json-file "^5.0.0"
cli-table3@^0.6.0:
version "0.6.5"
resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f"
integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==
dependencies:
string-width "^4.2.0"
optionalDependencies:
"@colors/colors" "1.5.0"
cross-spawn@^6.0.0:
version "6.0.6"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.6.tgz#30d0efa0712ddb7eb5a76e1e8721bffafa6b5d57"
integrity sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
semver "^5.5.0"
shebang-command "^1.2.0"
which "^1.2.9"
debug@^3.1.0:
version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
dependencies:
ms "^2.1.1"
detect-indent@^7.0.0:
version "7.0.1"
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.1.tgz#cbb060a12842b9c4d333f1cac4aa4da1bb66bc25"
integrity sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
execa@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==
dependencies:
cross-spawn "^6.0.0"
get-stream "^3.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
is-plain-obj@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0"
integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==
is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==
is-typedarray@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
load-json-file@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-7.0.1.tgz#a3c9fde6beffb6bedb5acf104fad6bb1604e1b00"
integrity sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==
ms@^2.1.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
netrc-parser@^3.1.6:
version "3.1.6"
resolved "https://registry.yarnpkg.com/netrc-parser/-/netrc-parser-3.1.6.tgz#7243c9ec850b8e805b9bdc7eae7b1450d4a96e72"
integrity sha512-lY+fmkqSwntAAjfP63jB4z5p5WbuZwyMCD3pInT7dpHU/Gc6Vv90SAC6A0aNiqaRGHiuZFBtiwu+pu8W/Eyotw==
dependencies:
debug "^3.1.0"
execa "^0.10.0"
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==
dependencies:
path-key "^2.0.0"
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==
semver@^5.5.0:
version "5.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==
dependencies:
shebang-regex "^1.0.0"
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==
signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.7"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
sort-keys@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-5.1.0.tgz#50a3f3d1ad3c5a76d043e0aeeba7299241e9aa5c"
integrity sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ==
dependencies:
is-plain-obj "^4.0.0"
string-width@^4.2.0:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==
typedarray-to-buffer@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
dependencies:
is-typedarray "^1.0.0"
which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
dependencies:
isexe "^2.0.0"
write-file-atomic@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
dependencies:
imurmurhash "^0.1.4"
is-typedarray "^1.0.0"
signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5"
write-json-file@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-5.0.0.tgz#11c329a8ea9e8e23fb92a87cc27412a15f87708b"
integrity sha512-ddSsCLa4aQ3kI21BthINo4q905/wfhvQ3JL3774AcRjBaiQmfn5v4rw77jQ7T6CmAit9VOQO+FsLyPkwxoB1fw==
dependencies:
detect-indent "^7.0.0"
is-plain-obj "^4.0.0"
sort-keys "^5.0.0"
write-file-atomic "^3.0.3"

View File

@@ -1,8 +1,30 @@
# Changelog
## v0.3.0
* Add generate storyboard support (PeerTube >= 8.0)
## v0.2.0
* Add runner version in request and register payloads
* Update dependencies to fix vulnerabilities
## v0.1.3
* Disable log coloring when TTY does not support it
* Add download file timeout (2 hours) to prevent stuck jobs
## v0.1.2
* Support query params in custom upload URL
## v0.1.1
* Fix adding studio watermark with audio/video split HLS file
## v0.1.0
* Requires Node 20
* Introduce `list-jobs` command to list processing jobs
* Update dependencies
* Send last chunks/playlist content to correctly end the live
* Requires Node 20
* Introduce `list-jobs` command to list processing jobs
* Update dependencies
* Send last chunks/playlist content to correctly end the live

View File

@@ -10,8 +10,7 @@ Commands below has to be run at the root of PeerTube git repository.
```bash
cd peertube-root
yarn install --pure-lockfile
cd apps/peertube-runner && yarn install --pure-lockfile
npm run install-node-dependencies
```
### Develop

View File

@@ -1,18 +1,18 @@
{
"name": "@peertube/peertube-runner",
"version": "0.1.0",
"version": "0.3.0",
"type": "module",
"main": "dist/peertube-runner.js",
"bin": "dist/peertube-runner.js",
"license": "AGPL-3.0",
"dependencies": {},
"devDependencies": {
"@iarna/toml": "^2.2.5",
"@peertube/net-ipc": "^2.2.0",
"@types/follow-redirects": "1.14.4",
"cli-table3": "^0.6.5",
"env-paths": "^3.0.0",
"follow-redirects": "^1.15.5",
"pino": "^9.2.0",
"pino-pretty": "^11.2.1"
"net-ipc": "^2.2.2",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0"
}
}

View File

@@ -7,7 +7,13 @@ import {
RunnerJobVODWebVideoTranscodingPayload
} from '@peertube/peertube-models'
import { logger } from '../../shared/index.js'
import { processAudioMergeTranscoding, processHLSTranscoding, ProcessOptions, processWebVideoTranscoding } from './shared/index.js'
import {
processAudioMergeTranscoding,
processGenerateStoryboard,
processHLSTranscoding,
ProcessOptions,
processWebVideoTranscoding
} from './shared/index.js'
import { ProcessLiveRTMPHLSTranscoding } from './shared/process-live.js'
import { processStudioTranscoding } from './shared/process-studio.js'
import { processVideoTranscription } from './shared/process-transcription.js'
@@ -15,7 +21,7 @@ import { processVideoTranscription } from './shared/process-transcription.js'
export async function processJob (options: ProcessOptions) {
const { server, job } = options
logger.info(`[${server.url}] Processing job of type ${job.type}: ${job.uuid}`, { payload: job.payload })
logger.info({ payload: job.payload }, `[${server.url}] Processing job of type ${job.type}: ${job.uuid}`)
switch (job.type) {
case 'vod-audio-merge-transcoding':
@@ -42,6 +48,10 @@ export async function processJob (options: ProcessOptions) {
await processVideoTranscription(options as ProcessOptions<RunnerJobTranscriptionPayload>)
break
case 'generate-video-storyboard':
await processGenerateStoryboard(options as any)
break
default:
logger.error(`Unknown job ${job.type} to process`)
return

View File

@@ -1,5 +1,12 @@
import { pick } from '@peertube/peertube-core-utils'
import { FFmpegEdition, FFmpegLive, FFmpegVOD, getDefaultAvailableEncoders, getDefaultEncodersToTry } from '@peertube/peertube-ffmpeg'
import {
FFmpegEdition,
FFmpegImage,
FFmpegLive,
FFmpegVOD,
getDefaultAvailableEncoders,
getDefaultEncodersToTry
} from '@peertube/peertube-ffmpeg'
import { RunnerJob, RunnerJobPayload } from '@peertube/peertube-models'
import { buildUUID } from '@peertube/peertube-node-utils'
import { PeerTubeServer } from '@peertube/peertube-server-commands'
@@ -8,9 +15,9 @@ import { join } from 'path'
import { ConfigManager, downloadFile, logger } from '../../../shared/index.js'
import { getWinstonLogger } from './winston-logger.js'
export type JobWithToken <T extends RunnerJobPayload = RunnerJobPayload> = RunnerJob<T> & { jobToken: string }
export type JobWithToken<T extends RunnerJobPayload = RunnerJobPayload> = RunnerJob<T> & { jobToken: string }
export type ProcessOptions <T extends RunnerJobPayload = RunnerJobPayload> = {
export type ProcessOptions<T extends RunnerJobPayload = RunnerJobPayload> = {
server: PeerTubeServer
job: JobWithToken<T>
runnerToken: string
@@ -108,6 +115,10 @@ export function buildFFmpegEdition () {
return new FFmpegEdition(getCommonFFmpegOptions())
}
export function buildFFmpegImage () {
return new FFmpegImage(getCommonFFmpegOptions())
}
function getCommonFFmpegOptions () {
const config = ConfigManager.Instance.getConfig()

View File

@@ -1,3 +1,4 @@
export * from './common.js'
export * from './process-vod.js'
export * from './winston-logger.js'
export * from './process-storyboard.js'

View File

@@ -23,11 +23,11 @@ import { ConfigManager } from '../../../shared/config-manager.js'
import { logger } from '../../../shared/index.js'
import { buildFFmpegLive, ProcessOptions } from './common.js'
type CustomLiveRTMPHLSTranscodingUpdatePayload =
Omit<LiveRTMPHLSTranscodingUpdatePayload, 'resolutionPlaylistFile'> & { resolutionPlaylistFile?: [ Buffer, string ] | Blob | string }
type CustomLiveRTMPHLSTranscodingUpdatePayload = Omit<LiveRTMPHLSTranscodingUpdatePayload, 'resolutionPlaylistFile'> & {
resolutionPlaylistFile?: [Buffer, string] | Blob | string
}
export class ProcessLiveRTMPHLSTranscoding {
private readonly outputPath: string
private readonly fsWatchers: FSWatcher[] = []
@@ -326,7 +326,7 @@ export class ProcessLiveRTMPHLSTranscoding {
const p = payloadBuilder().then(p => this.updateWithRetry(p))
if (!sequentialPromises) sequentialPromises = p
if (sequentialPromises === undefined) sequentialPromises = p
else sequentialPromises = sequentialPromises.then(() => p)
}
@@ -388,7 +388,7 @@ export class ProcessLiveRTMPHLSTranscoding {
return [
Buffer.from(this.latestFilteredPlaylistContent[playlistName], 'utf-8'),
join(this.outputPath, 'master.m3u8')
] as [ Buffer, string ]
] as [Buffer, string]
}
// ---------------------------------------------------------------------------

View File

@@ -0,0 +1,60 @@
import { RunnerJobGenerateStoryboardPayload, GenerateStoryboardSuccess } from '@peertube/peertube-models'
import { buildUUID } from '@peertube/peertube-node-utils'
import { remove } from 'fs-extra/esm'
import { join } from 'path'
import { ConfigManager } from '../../../shared/config-manager.js'
import { logger } from '../../../shared/index.js'
import { buildFFmpegImage, downloadInputFile, ProcessOptions, scheduleTranscodingProgress } from './common.js'
export async function processGenerateStoryboard (options: ProcessOptions<RunnerJobGenerateStoryboardPayload>) {
const { server, job, runnerToken } = options
const payload = job.payload
let ffmpegProgress: number
let videoInputPath: string
const outputPath = join(ConfigManager.Instance.getStoryboardDirectory(), `storyboard-${buildUUID()}.jpg`)
const updateProgressInterval = scheduleTranscodingProgress({
job,
server,
runnerToken,
progressGetter: () => ffmpegProgress
})
try {
logger.info(`Downloading input file ${payload.input.videoFileUrl} for storyboard job ${job.jobToken}`)
videoInputPath = await downloadInputFile({ url: payload.input.videoFileUrl, runnerToken, job })
logger.info(`Downloaded input file ${payload.input.videoFileUrl} for job ${job.jobToken}. Generating storyboard.`)
const ffmpegImage = buildFFmpegImage()
await ffmpegImage.generateStoryboardFromVideo({
path: videoInputPath,
destination: outputPath,
inputFileMutexReleaser: () => {},
sprites: payload.sprites
})
const successBody: GenerateStoryboardSuccess = {
storyboardFile: outputPath
}
await server.runnerJobs.success({
jobToken: job.jobToken,
jobUUID: job.uuid,
runnerToken,
payload: successBody,
reqPayload: payload
})
} finally {
if (videoInputPath) await remove(videoInputPath)
if (outputPath) await remove(outputPath)
if (updateProgressInterval) clearInterval(updateProgressInterval)
}
}

View File

@@ -18,6 +18,13 @@ import {
ProcessOptions,
scheduleTranscodingProgress
} from './common.js'
import {
canDoQuickAudioTranscode,
canDoQuickVideoTranscode,
ffprobePromise,
getVideoStreamDimensionsInfo,
getVideoStreamFPS
} from '@peertube/peertube-ffmpeg'
export async function processWebVideoTranscoding (options: ProcessOptions<RunnerJobVODWebVideoTranscodingPayload>) {
const { server, job, runnerToken } = options
@@ -46,7 +53,9 @@ export async function processWebVideoTranscoding (options: ProcessOptions<Runner
logger.info(`Downloaded input file ${payload.input.videoFileUrl} for job ${job.jobToken}. Running web video transcoding.`)
const ffmpegVod = buildFFmpegVOD({
onJobProgress: progress => { ffmpegProgress = progress }
onJobProgress: progress => {
ffmpegProgress = progress
}
})
await ffmpegVod.transcode({
@@ -108,15 +117,28 @@ export async function processHLSTranscoding (options: ProcessOptions<RunnerJobVO
videoInputPath = await downloadInputFile({ url: payload.input.videoFileUrl, runnerToken, job })
separatedAudioInputPath = await downloadSeparatedAudioFileIfNeeded({ urls: payload.input.separatedAudioFileUrl, runnerToken, job })
const inputProbe = await ffprobePromise(videoInputPath)
const { resolution } = await getVideoStreamDimensionsInfo(videoInputPath, inputProbe)
const fps = await getVideoStreamFPS(videoInputPath, inputProbe)
// Copy codecs if the input file can be quick transcoded (appropriate bitrate, codecs, etc.)
// And if the input resolution/fps are the same as the output resolution/fps
const copyCodecs = await canDoQuickAudioTranscode(videoInputPath, inputProbe) &&
await canDoQuickVideoTranscode(videoInputPath, fps) &&
resolution === payload.output.resolution &&
(!resolution || fps === payload.output.fps)
logger.info(`Downloaded input file ${payload.input.videoFileUrl} for job ${job.jobToken}. Running HLS transcoding.`)
const ffmpegVod = buildFFmpegVOD({
onJobProgress: progress => { ffmpegProgress = progress }
onJobProgress: progress => {
ffmpegProgress = progress
}
})
await ffmpegVod.transcode({
type: 'hls',
copyCodecs: false,
copyCodecs,
videoInputPath,
separatedAudioInputPath,
@@ -172,7 +194,7 @@ export async function processAudioMergeTranscoding (options: ProcessOptions<Runn
try {
logger.info(
`Downloading input files ${payload.input.audioFileUrl} and ${payload.input.previewFileUrl} ` +
`for audio merge transcoding job ${job.jobToken}`
`for audio merge transcoding job ${job.jobToken}`
)
audioPath = await downloadInputFile({ url: payload.input.audioFileUrl, runnerToken, job })
@@ -180,11 +202,13 @@ export async function processAudioMergeTranscoding (options: ProcessOptions<Runn
logger.info(
`Downloaded input files ${payload.input.audioFileUrl} and ${payload.input.previewFileUrl} ` +
`for job ${job.jobToken}. Running audio merge transcoding.`
`for job ${job.jobToken}. Running audio merge transcoding.`
)
const ffmpegVod = buildFFmpegVOD({
onJobProgress: progress => { ffmpegProgress = progress }
onJobProgress: progress => {
ffmpegProgress = progress
}
})
await ffmpegVod.transcode({

View File

@@ -1,15 +1,15 @@
import { pick, shuffle, wait } from '@peertube/peertube-core-utils'
import { PeerTubeProblemDocument, RunnerJobType, ServerErrorCode } from '@peertube/peertube-models'
import { PeerTubeServer as PeerTubeServerCommand } from '@peertube/peertube-server-commands'
import { ensureDir, remove } from 'fs-extra/esm'
import { readdir } from 'fs/promises'
import { join } from 'path'
import { io, Socket } from 'socket.io-client'
import { pick, shuffle, wait } from '@peertube/peertube-core-utils'
import { PeerTubeProblemDocument, RunnerJobType, ServerErrorCode } from '@peertube/peertube-models'
import { PeerTubeServer as PeerTubeServerCommand } from '@peertube/peertube-server-commands'
import { ConfigManager } from '../shared/index.js'
import { IPCServer } from '../shared/ipc/index.js'
import { logger } from '../shared/logger.js'
import { JobWithToken, processJob } from './process/index.js'
import { getSupportedJobsList, isJobSupported } from './shared/index.js'
import { getSupportedJobsList } from './shared/index.js'
type PeerTubeServer = PeerTubeServerCommand & {
runnerToken: string
@@ -31,7 +31,7 @@ export class RunnerServer {
private readonly sockets = new Map<PeerTubeServer, Socket>()
constructor (private readonly enabledJobs?: Set<RunnerJobType>) {
constructor (enabledJobs?: Set<RunnerJobType>) {
this.enabledJobsArray = enabledJobs
? Array.from(enabledJobs)
: getSupportedJobsList()
@@ -57,7 +57,7 @@ export class RunnerServer {
try {
await ipcServer.run(this)
} catch (err) {
logger.error('Cannot start local socket for IPC communication', err)
logger.error(err, 'Cannot start local socket for IPC communication')
process.exit(-1)
}
@@ -74,9 +74,11 @@ export class RunnerServer {
// Process jobs
await ensureDir(ConfigManager.Instance.getTranscodingDirectory())
await ensureDir(ConfigManager.Instance.getStoryboardDirectory())
await this.cleanupTMP()
logger.info(`Using ${ConfigManager.Instance.getTranscodingDirectory()} for transcoding directory`)
logger.info(`Using ${ConfigManager.Instance.getStoryboardDirectory()} for storyboard directory`)
this.initialized = true
await this.checkAvailableJobs()
@@ -95,7 +97,12 @@ export class RunnerServer {
logger.info(`Registering runner ${runnerName} on ${url}...`)
const serverCommand = new PeerTubeServerCommand({ url })
const { runnerToken } = await serverCommand.runners.register({ name: runnerName, description: runnerDescription, registrationToken })
const { runnerToken } = await serverCommand.runners.register({
name: runnerName,
description: runnerDescription,
registrationToken,
version: process.env.PACKAGE_VERSION
})
const server: PeerTubeServer = Object.assign(serverCommand, {
runnerToken,
@@ -268,18 +275,17 @@ export class RunnerServer {
jobTypes: this.enabledJobsArray.length !== getSupportedJobsList().length
? this.enabledJobsArray
: undefined
: undefined,
version: process.env.PACKAGE_VERSION
})
// FIXME: remove in PeerTube v8: jobTypes has been introduced in PeerTube v7, so do the filter here too
const filtered = availableJobs.filter(j => isJobSupported(j, this.enabledJobs))
if (filtered.length === 0) {
if (availableJobs.length === 0) {
logger.debug(`No job available on ${server.url} for runner ${server.runnerName}`)
return undefined
}
return filtered[0]
return availableJobs[0]
}
private async tryToExecuteJobAsync (server: PeerTubeServer, jobToAccept: { uuid: string }) {
@@ -358,6 +364,8 @@ export class RunnerServer {
try {
for (const { server, job } of this.processingJobs) {
logger.info(`Aborting job ${job.uuid} on ${server.url} as the runner is stopping`)
await server.runnerJobs.abort({
jobToken: job.jobToken,
jobUUID: job.uuid,

View File

@@ -1,4 +1,5 @@
import {
RunnerJobGenerateStoryboardPayload,
RunnerJobLiveRTMPHLSTranscodingPayload,
RunnerJobPayload,
RunnerJobStudioTranscodingPayload,
@@ -10,7 +11,7 @@ import {
VideoStudioTaskPayload
} from '@peertube/peertube-models'
const supportedMatrix: { [ id in RunnerJobType ]: (payload: RunnerJobPayload) => boolean } = {
const supportedMatrix: { [id in RunnerJobType]: (payload: RunnerJobPayload) => boolean } = {
'vod-web-video-transcoding': (_payload: RunnerJobVODWebVideoTranscodingPayload) => {
return true
},
@@ -33,16 +34,8 @@ const supportedMatrix: { [ id in RunnerJobType ]: (payload: RunnerJobPayload) =>
},
'video-transcription': (_payload: RunnerJobTranscriptionPayload) => {
return true
}
}
export function isJobSupported (job: { type: RunnerJobType, payload: RunnerJobPayload }, enabledJobs?: Set<RunnerJobType>) {
if (enabledJobs && !enabledJobs.has(job.type)) return false
const fn = supportedMatrix[job.type]
if (!fn) return false
return fn(job.payload as any)
},
'generate-video-storyboard': (_payload: RunnerJobGenerateStoryboardPayload) => true
}
export function getSupportedJobsList () {

View File

@@ -108,6 +108,10 @@ export class ConfigManager {
// ---------------------------------------------------------------------------
getStoryboardDirectory () {
return join(paths.cache, this.id, 'storyboard')
}
getTranscodingDirectory () {
return join(paths.cache, this.id, 'transcoding')
}
@@ -137,7 +141,7 @@ export class ConfigManager {
// ---------------------------------------------------------------------------
// Thanks: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
private deepFreeze <T extends object> (object: T) {
private deepFreeze<T extends object> (object: T) {
const propNames = Reflect.ownKeys(object)
// Freeze properties before freezing self

View File

@@ -41,6 +41,14 @@ export function downloadFile (options: {
}
const file = createWriteStream(destination)
file.on('error', err => {
remove(destination)
.catch(err => logger.error(err))
return rej(err)
})
file.on('finish', () => res())
response.pipe(file)
@@ -55,6 +63,10 @@ export function downloadFile (options: {
request.write(body)
request.end()
setTimeout(() => {
request.destroy(new Error('Global request timeout'))
}, 2 * 3600 * 1000) // 2 hours
})
}

View File

@@ -1,4 +1,4 @@
import { Client as NetIPC } from '@peertube/net-ipc'
import { Client as NetIPC } from 'net-ipc'
import CliTable3 from 'cli-table3'
import { ensureDir } from 'fs-extra/esm'
import { ConfigManager } from '../config-manager.js'
@@ -20,7 +20,8 @@ export class IPCClient {
if (err.code === 'ECONNREFUSED') {
throw new Error(
'This runner is not currently running in server mode on this system. ' +
'Please run it using the `server` command first (in another terminal for example) and then retry your command.'
'Please run it using the `server` command first (in another terminal for example) and then retry your command.',
{ cause: err }
)
}

View File

@@ -1,5 +1,5 @@
import { ensureDir } from 'fs-extra/esm'
import { Server as NetIPC } from '@peertube/net-ipc'
import { Server as NetIPC } from 'net-ipc'
import { pick } from '@peertube/peertube-core-utils'
import { RunnerServer } from '../../server/index.js'
import { ConfigManager } from '../config-manager.js'
@@ -58,11 +58,11 @@ export class IPCServer {
}
}
private sendResponse <T extends IPCResponseData> (
private sendResponse<T extends IPCResponseData> (
response: (data: any) => Promise<void>,
body: IPCResponse<T>
) {
response(body)
.catch(err => logger.error('Cannot send response after IPC request', err))
.catch(err => logger.error(err, 'Cannot send response after IPC request'))
}
}

View File

@@ -1,12 +1,4 @@
import { pino } from 'pino'
import pretty from 'pino-pretty'
const logger = pino(pretty({
colorize: true
}))
logger.level = 'info'
export {
logger
}
export const logger = pino({ level: 'info' }, pretty())

View File

@@ -1,351 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@iarna/toml@^2.2.5":
version "2.2.5"
resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c"
integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==
"@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz#9edec61b22c3082018a79f6d1c30289ddf3d9d11"
integrity sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==
"@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz#33677a275204898ad8acbf62734fc4dc0b6a4855"
integrity sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==
"@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz#19edf7cdc2e7063ee328403c1d895a86dd28f4bb"
integrity sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==
"@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz#94fb0543ba2e28766c3fc439cabbe0440ae70159"
integrity sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==
"@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz#4a0609ab5fe44d07c9c60a11e4484d3c38bbd6e3"
integrity sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==
"@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz#0aa5502d547b57abfc4ac492de68e2006e417242"
integrity sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==
"@peertube/net-ipc@^2.2.0":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@peertube/net-ipc/-/net-ipc-2.2.1.tgz#3d1c154a08b57cfea31ed760ec76fe2f69e35a19"
integrity sha512-RyKIGC3EeQ+xnSccf592qqsaXWrGp4wGfGl4W+wxDoZkwsThZJuiSbX8aCC1qZBHaDo3EuRH3ZrwsKpNjnyDAQ==
optionalDependencies:
fast-zlib "^2.0.1"
msgpackr "^1.3.2"
"@types/follow-redirects@1.14.4":
version "1.14.4"
resolved "https://registry.yarnpkg.com/@types/follow-redirects/-/follow-redirects-1.14.4.tgz#ca054d72ef574c77949fc5fff278b430fcd508ec"
integrity sha512-GWXfsD0Jc1RWiFmMuMFCpXMzi9L7oPDVwxUnZdg89kDNnqsRfUKXEtUYtA98A6lig1WXH/CYY/fvPW9HuN5fTA==
dependencies:
"@types/node" "*"
"@types/node@*":
version "22.9.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.3.tgz#08f3d64b3bc6d74b162d36f60213e8a6704ef2b4"
integrity sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==
dependencies:
undici-types "~6.19.8"
abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
dependencies:
event-target-shim "^5.0.0"
atomic-sleep@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b"
integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==
base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
buffer@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
dependencies:
base64-js "^1.3.1"
ieee754 "^1.2.1"
colorette@^2.0.7:
version "2.0.20"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
dateformat@^4.6.3:
version "4.6.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5"
integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==
detect-libc@^2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700"
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
dependencies:
once "^1.4.0"
env-paths@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-3.0.0.tgz#2f1e89c2f6dbd3408e1b1711dd82d62e317f58da"
integrity sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==
event-target-shim@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
events@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
fast-copy@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35"
integrity sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==
fast-redact@^3.1.1:
version "3.5.0"
resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4"
integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==
fast-safe-stringify@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884"
integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==
fast-zlib@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-zlib/-/fast-zlib-2.0.1.tgz#be624f592fc80ad8019ee2025d16a367a4e9b024"
integrity sha512-DCoYgNagM2Bt1VIpXpdGnRx4LzqJeYG0oh6Nf/7cWo6elTXkFGMw9CrRCYYUIapYNrozYMoyDRflx9mgT3Awyw==
follow-redirects@^1.15.5:
version "1.15.9"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
help-me@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6"
integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==
ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
joycon@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==
minimist@^1.2.6:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
msgpackr-extract@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz#e9d87023de39ce714872f9e9504e3c1996d61012"
integrity sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==
dependencies:
node-gyp-build-optional-packages "5.2.2"
optionalDependencies:
"@msgpackr-extract/msgpackr-extract-darwin-arm64" "3.0.3"
"@msgpackr-extract/msgpackr-extract-darwin-x64" "3.0.3"
"@msgpackr-extract/msgpackr-extract-linux-arm" "3.0.3"
"@msgpackr-extract/msgpackr-extract-linux-arm64" "3.0.3"
"@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.3"
"@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.3"
msgpackr@^1.3.2:
version "1.11.2"
resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.11.2.tgz#4463b7f7d68f2e24865c395664973562ad24473d"
integrity sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==
optionalDependencies:
msgpackr-extract "^3.0.2"
node-gyp-build-optional-packages@5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz#522f50c2d53134d7f3a76cd7255de4ab6c96a3a4"
integrity sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==
dependencies:
detect-libc "^2.0.1"
on-exit-leak-free@^2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8"
integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==
once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
dependencies:
wrappy "1"
pino-abstract-transport@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60"
integrity sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==
dependencies:
split2 "^4.0.0"
pino-pretty@^11.2.1:
version "11.3.0"
resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-11.3.0.tgz#390b3be044cf3d2e9192c7d19d44f6b690468f2e"
integrity sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==
dependencies:
colorette "^2.0.7"
dateformat "^4.6.3"
fast-copy "^3.0.2"
fast-safe-stringify "^2.1.1"
help-me "^5.0.0"
joycon "^3.1.1"
minimist "^1.2.6"
on-exit-leak-free "^2.1.0"
pino-abstract-transport "^2.0.0"
pump "^3.0.0"
readable-stream "^4.0.0"
secure-json-parse "^2.4.0"
sonic-boom "^4.0.1"
strip-json-comments "^3.1.1"
pino-std-serializers@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b"
integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==
pino@^9.2.0:
version "9.5.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-9.5.0.tgz#a7ef0fea868d22d52d8a4ce46e6e03c5dc46fdd6"
integrity sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==
dependencies:
atomic-sleep "^1.0.0"
fast-redact "^3.1.1"
on-exit-leak-free "^2.1.0"
pino-abstract-transport "^2.0.0"
pino-std-serializers "^7.0.0"
process-warning "^4.0.0"
quick-format-unescaped "^4.0.3"
real-require "^0.2.0"
safe-stable-stringify "^2.3.1"
sonic-boom "^4.0.1"
thread-stream "^3.0.0"
process-warning@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.0.tgz#581e3a7a1fb456c5f4fd239f76bce75897682d5a"
integrity sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==
process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
pump@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8"
integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
quick-format-unescaped@^4.0.3:
version "4.0.4"
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7"
integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==
readable-stream@^4.0.0:
version "4.5.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09"
integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==
dependencies:
abort-controller "^3.0.0"
buffer "^6.0.3"
events "^3.3.0"
process "^0.11.10"
string_decoder "^1.3.0"
real-require@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78"
integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==
safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safe-stable-stringify@^2.3.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd"
integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==
secure-json-parse@^2.4.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862"
integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==
sonic-boom@^4.0.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d"
integrity sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==
dependencies:
atomic-sleep "^1.0.0"
split2@^4.0.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
string_decoder@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
thread-stream@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1"
integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==
dependencies:
real-require "^0.2.0"
undici-types@~6.19.8:
version "6.19.8"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==

View File

@@ -1,181 +0,0 @@
{
"root": true,
"ignorePatterns": [
"projects/**/*",
"node_modules/",
"src/standalone/embed-player-api/dist"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"tsconfig.eslint.json"
],
"EXPERIMENTAL_useSourceOfProjectReferenceRedirect": true,
"createDefaultProgram": false
},
"extends": [
"../.eslintrc.json",
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
"jsdoc/newline-after-description": "off",
"jsdoc/check-alignment": "off",
"lines-between-class-members": "off",
"@typescript-eslint/lines-between-class-members": [ "off" ],
"arrow-body-style": "off",
"no-underscore-dangle": "off",
"n/no-callback-literal": "off",
"@angular-eslint/component-selector": [
"error",
{
"type": [ "element", "attribute" ],
"prefix": "my",
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": [ "element", "attribute" ],
"prefix": "my",
"style": "camelCase"
}
],
"@typescript-eslint/no-this-alias": [
"error",
{
"allowDestructuring": true,
"allowedNames": ["self", "player"]
}
],
"@typescript-eslint/prefer-readonly": "off",
"@angular-eslint/use-component-view-encapsulation": "error",
"prefer-arrow/prefer-arrow-functions": "off",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/consistent-type-definitions": "off",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/member-ordering": [
"off"
],
"@typescript-eslint/member-delimiter-style": [
"error",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "comma",
"requireLast": false
}
}
],
"@typescript-eslint/prefer-for-of": "off",
"@typescript-eslint/no-empty-function": "error",
"@typescript-eslint/no-floating-promises": "off",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-shadow": [
"off",
{
"hoist": "all"
}
],
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-unused-expressions": [
"error",
{
"allowTaggedTemplates": true,
"allowShortCircuit": true
}
],
"@typescript-eslint/quotes": [
"error",
"single",
{
"avoidEscape": true,
"allowTemplateLiterals": true
}
],
"@typescript-eslint/semi": [
"error",
"never"
],
"brace-style": [
"error",
"1tbs"
],
"comma-dangle": "error",
"curly": [
"error",
"multi-line"
],
"dot-notation": "off",
"no-useless-return": "off",
"indent": "off",
"no-bitwise": "off",
"no-console": "off",
"no-return-assign": "off",
"no-constant-condition": "error",
"no-control-regex": "error",
"no-duplicate-imports": "error",
"no-empty": "error",
"no-empty-function": [
"error",
{ "allow": [ "constructors" ] }
],
"no-invalid-regexp": "error",
"no-multiple-empty-lines": "error",
"no-redeclare": "error",
"no-regex-spaces": "error",
"no-return-await": "error",
"no-shadow": "off",
"no-unused-expressions": "error",
"semi": "error",
"space-before-function-paren": [
"error",
"always"
],
"space-in-parens": [
"error",
"never"
],
"object-shorthand": [
"error",
"properties"
],
"quote-props": [
"error",
"consistent-as-needed"
],
"no-constant-binary-expression": "error",
"@typescript-eslint/unbound-method": [
"error",
{ "ignoreStatic": true }
],
"import/no-named-default": "off"
}
},
{
"files": [
"*.html"
],
"extends": [
"plugin:@angular-eslint/template/recommended",
"plugin:@angular-eslint/template/accessibility"
],
"rules": {}
}
]
}

View File

@@ -0,0 +1,104 @@
---
description: 'Angular-specific coding standards and best practices'
applyTo: 'src/app/**/*.ts, src/app/**/*.html, src/app/**/*.scss, src/app/**/*.css'
---
# Angular Development Instructions
Instructions for generating high-quality Angular applications with TypeScript, using Angular Signals for state management, adhering to Angular best practices as outlined at https://angular.dev.
## Project Context
- Latest Angular version (use standalone components by default)
- TypeScript for type safety
- Angular CLI for project setup and scaffolding
- Follow Angular Style Guide (https://angular.dev/style-guide)
- Use Angular Material or other modern UI libraries for consistent styling (if specified)
## Development Standards
### Architecture
- Use standalone components unless modules are explicitly required
- Organize code by feature modules or domains for scalability
- Implement lazy loading for feature modules to optimize performance
- Use Angular's built-in dependency injection system effectively
- Structure components with a clear separation of concerns (smart vs. presentational components)
### TypeScript
- Enable strict mode in `tsconfig.json` for type safety
- Define clear interfaces and types for components, services, and models
- Use type guards and union types for robust type checking
- Implement proper error handling with RxJS operators (e.g., `catchError`)
- Use typed forms (e.g., `FormGroup`, `FormControl`) for reactive forms
### Component Design
- Follow Angular's component lifecycle hooks best practices
- When using Angular >= 19, Use `input()` `output()`, `viewChild()`, `viewChildren()`, `contentChild()` and `viewChildren()` functions instead of decorators; otherwise use decorators
- Leverage Angular's change detection strategy (default or `OnPush` for performance)
- Keep templates clean and logic in component classes or services
- Use Angular directives and pipes for reusable functionality
### Styling
- Use Angular's component-level CSS encapsulation (default: ViewEncapsulation.Emulated)
- Prefer SCSS for styling with consistent theming
- Implement responsive design using CSS Grid, Flexbox, or Angular CDK Layout utilities
- Follow Angular Material's theming guidelines if used
- Maintain accessibility (a11y) with ARIA attributes and semantic HTML
### State Management
- Use Angular Signals for reactive state management in components and services
- Leverage `signal()`, `computed()`, and `effect()` for reactive state updates
- Use writable signals for mutable state and computed signals for derived state
- Handle loading and error states with signals and proper UI feedback
- Use Angular's `AsyncPipe` to handle observables in templates when combining signals with RxJS
### Data Fetching
- Use Angular's `HttpClient` for API calls with proper typing
- Implement RxJS operators for data transformation and error handling
- Use Angular's `inject()` function for dependency injection in standalone components
- Implement caching strategies (e.g., `shareReplay` for observables)
- Store API response data in signals for reactive updates
- Handle API errors with global interceptors for consistent error handling
### Security
- Sanitize user inputs using Angular's built-in sanitization
- Implement route guards for authentication and authorization
- Use Angular's `HttpInterceptor` for CSRF protection and API authentication headers
- Validate form inputs with Angular's reactive forms and custom validators
- Follow Angular's security best practices (e.g., avoid direct DOM manipulation)
### Performance
- Enable production builds with `ng build --prod` for optimization
- Use lazy loading for routes to reduce initial bundle size
- Optimize change detection with `OnPush` strategy and signals for fine-grained reactivity
- Use trackBy in `ngFor` loops to improve rendering performance
- Implement server-side rendering (SSR) or static site generation (SSG) with Angular Universal (if specified)
### Testing
- Write unit tests for components, services, and pipes using Jasmine and Karma
- Use Angular's `TestBed` for component testing with mocked dependencies
- Test signal-based state updates using Angular's testing utilities
- Write end-to-end tests with Cypress or Playwright (if specified)
- Mock HTTP requests using `HttpClientTestingModule`
- Ensure high test coverage for critical functionality
## Implementation Process
1. Plan project structure and feature modules
2. Define TypeScript interfaces and models
3. Scaffold components, services, and pipes using Angular CLI
4. Implement data services and API integrations with signal-based state
5. Build reusable components with clear inputs and outputs
6. Add reactive forms and validation
7. Apply styling with SCSS and responsive design
8. Implement lazy-loaded routes and guards
9. Add error handling and loading states using signals
10. Write unit and end-to-end tests
11. Optimize performance and bundle size
## Additional Guidelines
- Follow Angular's naming conventions (e.g., `feature.component.ts`, `feature.service.ts`)
- Use Angular CLI commands for generating boilerplate code
- Document components and services with clear JSDoc comments
- Ensure accessibility compliance (WCAG 2.1) where applicable
- Use Angular's built-in i18n for internationalization (if specified)
- Keep code DRY by creating reusable utilities and shared modules
- Use signals consistently for state management to ensure reactive updates

View File

@@ -0,0 +1,112 @@
# PeerTube Client Development Instructions for Coding Agents
## Client Overview
This is the Angular frontend for PeerTube, a decentralized video hosting platform. The client is built with Angular 20+, TypeScript, and SCSS. It communicates with the PeerTube server API and provides the web interface for users, administrators, and content creators.
**Key Technologies:**
- Angular 20+ with standalone components
- TypeScript 5+
- SCSS for styling
- RxJS for reactive programming
- PrimeNg and Bootstrap for UI components
- WebdriverIO for E2E testing
- Angular CLI
## Client Build and Development Commands
### Prerequisites (for client development)
- Node.js 20+
- yarn 1
- Running PeerTube server (see ../server instructions)
### Essential Client Commands
```bash
# From the client directory:
cd /client
# 1. Install dependencies (ALWAYS first)
yarn install --pure-lockfile
# 2. Development server with hot reload
npm run dev
# 3. Build for production
npm run build
```
### Client Testing Commands
```bash
# From client directory:
npm run lint # ESLint for client code
```
### Common Client Issues and Solutions
**Angular Build Failures:**
- Always run `yarn install --pure-lockfile` after pulling changes
- Clear `node_modules` and reinstall if dependency errors occur
- Build may fail on memory issues: `NODE_OPTIONS="--max-old-space-size=4096" npm run build`
- Check TypeScript errors carefully - Angular is strict about types
**Development Server Issues:**
- Default port is 3000, ensure it's not in use
- Hot reload may fail on file permission issues
- Clear browser cache if changes don't appear
## Client Architecture and File Structure
### Client Directory Structure
```
/src/
/app/
+admin/ # Admin interface components
+my-account/ # User account management pages
+my-library/ # User's videos, playlists, subscriptions
+search/ # Search functionality and results
+shared/ # Shared Angular components, services, pipes
+standalone/ # Standalone Angular components
+videos/ # Video-related components (watch, upload, etc.)
/core/ # Core services (auth, server, notifications)
/helpers/ # Utility functions and helpers
/menu/ # Navigation menu components
/assets/ # Static assets (images, icons, etc.)
/environments/ # Environment configurations
/locale/ # Internationalization files
/sass/ # Global SCSS styles
```
### Key Client Configuration Files
- `angular.json` - Angular CLI workspace configuration
- `tsconfig.json` - TypeScript configuration for client
- `e2e/wdio*.conf.js` - WebdriverIO E2E test configurations
- `src/environments/` - Environment-specific configurations
### Shared Code with Server (`../shared/`)
The client imports TypeScript models and utilities from the shared directory:
- `../shared/models/` - Data models (Video, User, Channel, etc.). Import these in client code: `import { Video } from '@peertube/peertube-models'`
- `../shared/core-utils/` - Utility functions shared between client/server. Import these in client code: `import { ... } from '@peertube/peertube-core-utils'`
-
## Client Development Workflow
### Making Client Changes
1. **Angular Components:** Create/modify in `/src/app/` following existing patterns
2. **Shared Components:** Reusable components go in `/src/app/shared/`
3. **Services:** Core services in `/src/app/core/`, feature services with components
4. **Styles:** Component styles in `.scss` files, global styles in `/src/sass/`
5. **Assets:** Images, icons in `/src/assets/`
6. **Routing:** Routes defined in feature modules or `app-routing.module.ts`
## Trust These Instructions
These instructions are comprehensive and tested specifically for client development. Only search for additional information if:
1. Commands fail despite following instructions exactly
2. New error messages appear that aren't documented here
3. You need specific Angular implementation details not covered above
For server-side questions, refer to the server instructions in `../.github/copilot-instructions.md`.

View File

@@ -59,6 +59,9 @@
"selector-max-id": null,
"scss/at-function-pattern": null,
"scss/load-no-partial-leading-underscore": null,
"@stylistic/string-quotes": null,
"@stylistic/color-hex-case": null,
"@stylistic/function-parentheses-space-inside": null,
"property-no-vendor-prefix": [
true,
{

View File

@@ -185,12 +185,11 @@
"."
],
"sass": {
"silenceDeprecations": [ "import", "mixed-decls", "color-functions", "global-builtin" ]
"silenceDeprecations": [ "import", "color-functions", "global-builtin" ]
}
},
"assets": [
"src/assets/images",
"src/manifest.webmanifest"
"src/assets/images"
],
"styles": [
"src/sass/application.scss"
@@ -214,10 +213,10 @@
"escape-string-regexp",
"is-plain-object",
"parse-srcset",
"deepmerge",
"core-js/features/reflect",
"hammerjs",
"jschannel"
"jschannel",
"color-bits"
],
"scripts": [],
"extractLicenses": false,
@@ -246,7 +245,7 @@
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "120kb"
"maximumError": "140kb"
}
],
"fileReplacements": [
@@ -326,16 +325,36 @@
"prefix": "my",
"style": "scss",
"skipTests": true,
"flat": true
"flat": true,
"type": "component"
},
"@schematics/angular:directive": {
"prefix": "my"
"prefix": "my",
"type": "directive"
},
"@angular-eslint/schematics:application": {
"setParserOptionsProject": true
},
"@angular-eslint/schematics:library": {
"setParserOptionsProject": true
},
"@schematics/angular:service": {
"type": "service"
},
"@schematics/angular:guard": {
"typeSeparator": "."
},
"@schematics/angular:interceptor": {
"typeSeparator": "."
},
"@schematics/angular:module": {
"typeSeparator": "."
},
"@schematics/angular:pipe": {
"typeSeparator": "."
},
"@schematics/angular:resolver": {
"typeSeparator": "."
}
},
"cli": {

View File

@@ -1,55 +1,50 @@
import { NSFWPolicyType } from '@peertube/peertube-models'
import { browserSleep, go, setCheckboxEnabled } from '../utils'
export class AdminConfigPage {
async navigateTo (tab: 'instance-homepage' | 'basic-configuration' | 'instance-information' | 'live') {
const waitTitles = {
'instance-homepage': 'INSTANCE HOMEPAGE',
'basic-configuration': 'APPEARANCE',
'instance-information': 'INSTANCE',
'live': 'LIVE'
async navigateTo (page: 'information' | 'live' | 'general' | 'homepage') {
const url = '/admin/settings/config/' + page
const currentUrl = await browser.getUrl()
if (!currentUrl.endsWith(url)) {
await go(url)
}
const url = '/admin/settings/config/edit-custom#' + tab
if (await browser.getUrl() !== url) {
await go('/admin/settings/config/edit-custom#' + tab)
}
await $('h2=' + waitTitles[tab]).waitForDisplayed()
await $('a.active[href="' + url + '"]').waitForDisplayed()
}
async updateNSFWSetting (newValue: 'do_not_list' | 'blur' | 'display') {
await this.navigateTo('instance-information')
async updateNSFWSetting (newValue: NSFWPolicyType) {
await this.navigateTo('information')
const elem = $('#instanceDefaultNSFWPolicy')
const elem = $(`#instanceDefaultNSFWPolicy-${newValue} + label`)
await elem.waitForDisplayed()
await elem.scrollIntoView({ block: 'center' }) // Avoid issues with fixed header
await elem.waitForClickable()
return elem.selectByAttribute('value', newValue)
return elem.click()
}
async updateHomepage (newValue: string) {
await this.navigateTo('instance-homepage')
await this.navigateTo('homepage')
return $('#instanceCustomHomepageContent').setValue(newValue)
return $('#homepageContent').setValue(newValue)
}
async toggleSignup (enabled: boolean) {
await this.navigateTo('basic-configuration')
await this.navigateTo('general')
return setCheckboxEnabled('signupEnabled', enabled)
}
async toggleSignupApproval (required: boolean) {
await this.navigateTo('basic-configuration')
await this.navigateTo('general')
return setCheckboxEnabled('signupRequiresApproval', required)
}
async toggleSignupEmailVerification (required: boolean) {
await this.navigateTo('basic-configuration')
await this.navigateTo('general')
return setCheckboxEnabled('signupRequiresEmailVerification', required)
}
@@ -61,11 +56,18 @@ export class AdminConfigPage {
}
async save () {
const button = $('input[type=submit]')
const button = $('my-admin-save-bar .save-button')
try {
await button.waitForClickable()
} catch {
// The config may have not been changed
return
} finally {
await browserSleep(1000) // Wait for the button to be clickable
}
await button.waitForClickable()
await button.click()
await browserSleep(1000)
await button.waitForClickable({ reverse: true })
}
}

View File

@@ -1,26 +1,25 @@
import { browserSleep, findParentElement, go } from '../utils'
export class AdminRegistrationPage {
async navigateToRegistratonsList () {
async navigateToRegistrationsList () {
await go('/admin/moderation/registrations/list')
await $('my-registration-list').waitForDisplayed()
}
async accept (username: string, moderationResponse: string) {
const usernameEl = await $('*=' + username)
const usernameEl = $('*=' + username)
await usernameEl.waitForDisplayed()
const tr = await findParentElement(usernameEl, async el => await el.getTagName() === 'tr')
await tr.$('.action-cell .dropdown-root').click()
const accept = await $('span*=Accept this request')
const accept = $('span*=Accept this request')
await accept.waitForClickable()
await accept.click()
const moderationResponseTextarea = await $('#moderationResponse')
const moderationResponseTextarea = $('#moderationResponse')
await moderationResponseTextarea.waitForDisplayed()
await moderationResponseTextarea.setValue(moderationResponse)
@@ -31,5 +30,4 @@ export class AdminRegistrationPage {
await browserSleep(1000)
}
}

View File

@@ -0,0 +1,24 @@
export class AdminUserPage {
async createUser (options: {
username: string
password: string
}) {
const { username, password } = options
await $('.menu-link[title=Overview]').click()
await $('a*=Create user').click()
await $('#username').waitForDisplayed()
await $('#username').setValue(username)
await $('#password').setValue(password)
await $('#channelName').setValue(`${username}_channel`)
await $('#email').setValue(`${username}@example.com`)
const submit = $('my-user-create .primary-button')
await submit.scrollIntoView()
await submit.waitForClickable()
await submit.click()
await $('.cell-username*=' + username).waitForDisplayed()
}
}

View File

@@ -1,19 +1,45 @@
import { NSFWPolicyType } from '@peertube/peertube-models'
import { getCheckbox } from '../utils'
export class AnonymousSettingsPage {
async openSettings () {
const link = await $('my-header .settings-button')
const link = $('my-header .settings-button')
await link.waitForClickable()
await link.click()
await $('my-user-video-settings').waitForDisplayed()
}
async closeSettings () {
const closeModal = $('.modal.show .modal-header > button')
await closeModal.waitForClickable()
await closeModal.click()
await $('.modal.show').waitForDisplayed({ reverse: true })
}
async clickOnP2PCheckbox () {
const p2p = await getCheckbox('p2pEnabled')
await p2p.waitForClickable()
await p2p.click()
}
async updateNSFW (newValue: NSFWPolicyType) {
const nsfw = $(`#nsfwPolicy-${newValue} + label`)
await nsfw.waitForClickable()
await nsfw.click()
await $(`#nsfwPolicy-${newValue}:checked`).waitForExist()
}
async updateViolentFlag (newValue: NSFWPolicyType) {
const nsfw = $(`#nsfwFlagViolent-${newValue} + label`)
await nsfw.waitForClickable()
await nsfw.click()
await $(`#nsfwFlagViolent-${newValue}:checked`).waitForExist()
}
}

View File

@@ -1,9 +1,7 @@
import { browserSleep, go, isAndroid } from '../utils'
export class LoginPage {
constructor (private isMobileDevice: boolean) {
}
async login (options: {
@@ -51,8 +49,12 @@ export class LoginPage {
return $('.alert-danger').getText()
}
async loginAsRootUser () {
return this.login({ username: 'root', password: 'test' + this.getSuffix() })
loginAsRootUser () {
return this.login({ username: 'root', password: this.getRootPassword() })
}
getRootPassword () {
return 'test' + this.getSuffix()
}
loginOnPeerTube2 () {
@@ -64,7 +66,7 @@ export class LoginPage {
}
async logout () {
const loggedInDropdown = $('.logged-in-container .logged-in-info')
const loggedInDropdown = $('.logged-in-container .dropdown-toggle')
await loggedInDropdown.waitForClickable()
await loggedInDropdown.click()

View File

@@ -1,3 +1,4 @@
import { NSFWPolicyType } from '@peertube/peertube-models'
import { getCheckbox, go, selectCustomSelect } from '../utils'
export class MyAccountPage {
@@ -13,20 +14,34 @@ export class MyAccountPage {
return $('a[href="/my-library/history/videos"]').click()
}
// Settings
// ---------------------------------------------------------------------------
// My account settings
// ---------------------------------------------------------------------------
navigateToMySettings () {
return $('a[href="/my-account"]').click()
}
async updateNSFW (newValue: 'do_not_list' | 'blur' | 'display') {
const nsfw = $('#nsfwPolicy')
async updateNSFW (newValue: NSFWPolicyType) {
const nsfw = $(`#nsfwPolicy-${newValue} + label`)
await nsfw.waitForDisplayed()
await nsfw.scrollIntoView({ block: 'center' }) // Avoid issues with fixed header
await nsfw.waitForClickable()
await nsfw.selectByAttribute('value', newValue)
await nsfw.click()
await this.submitVideoSettings()
}
async updateViolentFlag (newValue: NSFWPolicyType) {
const nsfw = $(`#nsfwFlagViolent-${newValue} + label`)
await nsfw.waitForDisplayed()
await nsfw.scrollIntoView({ block: 'center' }) // Avoid issues with fixed header
await nsfw.waitForClickable()
await nsfw.click()
await this.submitVideoSettings()
}
@@ -50,7 +65,25 @@ export class MyAccountPage {
await submit.click()
}
// My account Videos
async updateEmail (email: string, password: string) {
const emailInput = $('my-account-change-email #new-email')
await emailInput.waitForDisplayed()
await emailInput.scrollIntoView({ block: 'center' }) // Avoid issues with fixed header
await emailInput.setValue(email)
const passwordInput = $('my-account-change-email #password')
await passwordInput.waitForDisplayed()
await passwordInput.setValue(password)
const submit = $('my-account-change-email input[type=submit]')
await submit.waitForClickable()
await submit.scrollIntoView({ block: 'center' }) // Avoid issues with fixed header
await submit.click()
}
// ---------------------------------------------------------------------------
// My account videos
// ---------------------------------------------------------------------------
async removeVideo (name: string) {
const container = await this.getVideoRow(name)
@@ -84,7 +117,21 @@ export class MyAccountPage {
return elements.length
}
async getVideoRow (name: string) {
let el = $('.name*=' + name)
await el.waitForDisplayed()
while (await el.getTagName() !== 'tr') {
el = el.parentElement()
}
return el
}
// ---------------------------------------------------------------------------
// My account playlists
// ---------------------------------------------------------------------------
async getPlaylistVideosText (name: string) {
const elem = await this.getPlaylist(name)
@@ -124,7 +171,7 @@ export class MyAccountPage {
await selectCustomSelect('videoChannelId', 'Main root channel')
await selectCustomSelect('privacy', privacy)
const submit = await $('form input[type=submit]')
const submit = $('form input[type=submit]')
await submit.waitForClickable()
await submit.scrollIntoView()
await submit.click()
@@ -134,27 +181,11 @@ export class MyAccountPage {
})
}
// My account Videos
private async getVideoRow (name: string) {
let el = $('.name*=' + name)
await el.waitForDisplayed()
while (await el.getTagName() !== 'tr') {
el = el.parentElement()
}
return el
}
// My account playlists
private async getPlaylist (name: string) {
const playlist = () => {
return $$('my-video-playlist-miniature')
.filter(async e => {
const t = await e.$('.miniature-name').getText()
const t = await e.$('img').getAttribute('aria-label')
return t.includes(name)
})

View File

@@ -1,7 +1,6 @@
import { browserSleep, isIOS, isMobileDevice, isSafari } from '../utils'
export class PlayerPage {
getWatchVideoPlayerCurrentTime () {
const elem = $('video')
@@ -10,7 +9,7 @@ export class PlayerPage {
: elem.getProperty('currentTime')
return p.then(t => parseInt(t + '', 10))
.then(t => Math.ceil(t))
.then(t => Math.ceil(t))
}
waitUntilPlaylistInfo (text: string, maxTime: number) {
@@ -23,9 +22,11 @@ export class PlayerPage {
}
waitUntilPlayerWrapper () {
return browser.waitUntil(async () => {
return !!(await $('#placeholder-preview'))
})
return $('#video-wrapper').waitForExist()
}
waitUntilPlaying () {
return $('.video-js.vjs-playing').waitForDisplayed()
}
async playAndPauseVideo (isAutoplay: boolean, waitUntilSec: number) {
@@ -66,16 +67,36 @@ export class PlayerPage {
return this.clickOnPlayButton()
}
private async clickOnPlayButton () {
const playButton = () => $('.vjs-big-play-button')
getPlayButton () {
return $('.vjs-big-play-button')
}
await playButton().waitForClickable()
await playButton().click()
getNSFWContentText () {
return $('.video-js .nsfw-info').getText()
}
getNSFWDetailsContent () {
return $('.video-js .nsfw-details-content')
}
getMoreNSFWInfoButton () {
return $('.video-js .nsfw-info button')
}
async hasPoster () {
const property = await $('.video-js .vjs-poster').getCSSProperty('background-image')
return property.value.startsWith('url(')
}
private async clickOnPlayButton () {
await this.getPlayButton().waitForClickable()
await this.getPlayButton().click()
}
async fillEmbedVideoPassword (videoPassword: string) {
const videoPasswordInput = $('input#video-password-input')
const confirmButton = await $('button#video-password-submit')
const confirmButton = $('button#video-password-submit')
await videoPasswordInput.clearValue()
await videoPasswordInput.setValue(videoPassword)

View File

@@ -1,7 +1,6 @@
import { getCheckbox } from '../utils'
export class SignupPage {
getRegisterMenuButton () {
return $('.create-account-button')
}
@@ -47,7 +46,7 @@ export class SignupPage {
await $('#displayName').setValue(options.displayName || `${options.username} display name`)
await $('#username').setValue(options.username)
await $('#password').setValue(options.password || 'password')
await $('#password').setValue(options.password || 'superpassword')
// Fix weird bug on firefox that "cannot scroll into view" when using just `setValue`
await $('#email').scrollIntoView({ block: 'center' })

View File

@@ -1,9 +1,7 @@
import { browserSleep, go } from '../utils'
import { browserSleep, findParentElement, go } from '../utils'
export class VideoListPage {
constructor (private isMobileDevice: boolean, private isSafari: boolean) {
}
async goOnVideosList () {
@@ -53,30 +51,54 @@ export class VideoListPage {
await this.waitForList()
}
async getNSFWFilter () {
async getNSFWFilterText () {
const el = $('.active-filter*=Sensitive')
await el.waitForDisplayed()
return el
return el.getText()
}
async getVideosListName () {
const elems = await $$('.videos .video-miniature .video-name')
const elems = $$('.videos .video-miniature .video-name')
const texts = await elems.map(e => e.getText())
return texts.map(t => t.trim())
}
videoExists (name: string) {
isVideoDisplayed (name: string) {
return $('.video-name=' + name).isDisplayed()
}
async videoIsBlurred (name: string) {
const filter = await $('.video-name=' + name).getCSSProperty('filter')
async isVideoBlurred (name: string) {
const miniature = await this.getVideoMiniature(name)
const filter = await miniature.$('my-video-thumbnail img').getCSSProperty('filter')
return filter.value !== 'none'
}
async hasVideoWarning (name: string) {
const miniature = await this.getVideoMiniature(name)
return miniature.$('.nsfw-warning').isDisplayed()
}
async expectVideoNSFWTooltip (name: string, summary?: string) {
const miniature = await this.getVideoMiniature(name)
const warning = miniature.$('.nsfw-warning')
await warning.waitForDisplayed()
expect(await warning.getAttribute('aria-label')).toEqual(summary)
}
private async getVideoMiniature (name: string) {
const videoName = $('.video-name=' + name)
await videoName.waitForDisplayed()
return findParentElement(videoName, async el => await el.getTagName() === 'my-video-miniature')
}
async clickOnVideo (videoName: string) {
const video = async () => {
const videos = await $$('.videos .video-miniature .video-name').filter(async e => {
@@ -92,9 +114,8 @@ export class VideoListPage {
const elem = await video()
return elem?.isClickable()
});
(await video()).click()
})
;(await video()).click()
await browser.waitUntil(async () => (await browser.getUrl()).includes('/w/'))
}
@@ -116,8 +137,4 @@ export class VideoListPage {
private waitForList () {
return $('.videos .video-miniature .video-name').waitForDisplayed()
}
private waitForTitle (title: string) {
return $('h1=' + title).waitForDisplayed()
}
}

View File

@@ -1,4 +1,4 @@
import { clickOnRadio, getCheckbox, go, isRadioSelected, selectCustomSelect } from '../utils'
import { clickOnRadio, getCheckbox, go, isRadioSelected, selectCustomSelect, setCheckboxEnabled } from '../utils'
export abstract class VideoManage {
async clickOnSave () {
@@ -19,13 +19,24 @@ export abstract class VideoManage {
// ---------------------------------------------------------------------------
async setAsNSFW () {
async setAsNSFW (options: {
violent?: boolean
summary?: string
} = {}) {
await this.goOnPage('Moderation')
const checkbox = await getCheckbox('nsfw')
await checkbox.waitForClickable()
return checkbox.click()
await checkbox.click()
if (options.violent) {
await setCheckboxEnabled('nsfwFlagViolent', true)
}
if (options.summary) {
await $('#nsfwSummary').setValue(options.summary)
}
}
// ---------------------------------------------------------------------------
@@ -65,10 +76,11 @@ export abstract class VideoManage {
await input.waitForClickable()
await input.click()
const nextDay = $('.p-datepicker-today + td > span')
await nextDay.waitForClickable()
await nextDay.click()
await nextDay.waitForDisplayed({ reverse: true })
const nextMonth = $('.p-datepicker-next-button')
await nextMonth.click()
await $('.p-datepicker-calendar td[aria-label="1"] > span').click()
await $('.p-datepicker-calendar').waitForDisplayed({ reverse: true, timeout: 15000 }) // Can be slow
}
getScheduleInput () {
@@ -92,7 +104,7 @@ export abstract class VideoManage {
async getLiveState () {
await this.goOnPage('Live settings')
if (await isRadioSelected('#permanentLiveTrue')) return 'permanent'
if (await isRadioSelected('permanentLiveTrue')) return 'permanent'
return 'normal'
}
@@ -123,7 +135,13 @@ export abstract class VideoManage {
}
protected async goOnPage (page: 'Main information' | 'Moderation' | 'Live settings') {
const el = $('my-video-manage-container .menu').$('*=' + page)
const urls = {
'Main information': '',
'Moderation': 'moderation',
'Live settings': 'live'
}
const el = $(`my-video-manage-container .menu a[href*="/${urls[page]}"]`)
await el.waitForClickable()
await el.click()
}

View File

@@ -1,9 +1,10 @@
import { join } from 'path'
import { join } from 'node:path'
import { VideoManage } from './video-manage'
import { FIXTURE_URLS } from '../utils'
export class VideoPublishPage extends VideoManage {
async navigateTo (tab?: 'Go live') {
const publishButton = await $('.publish-button > a')
const publishButton = $('.publish-button > a')
await publishButton.waitForClickable()
await publishButton.click()
@@ -30,13 +31,30 @@ export class VideoPublishPage extends VideoManage {
await browser.pause(1000)
const elem = await $(fileInputSelector)
const elem = $(fileInputSelector)
await elem.chooseFile(fileToUpload)
// Wait for the upload to finish
await this.getSaveButton().waitForClickable()
}
async importVideo () {
const tab = $('.nav-link*=Import with URL')
await tab.waitForClickable()
await tab.click()
const input = $('#targetUrl')
await input.waitForDisplayed()
await input.setValue(FIXTURE_URLS.IMPORT_URL)
const submit = $('.first-step-block .primary-button:not([disabled])')
await submit.waitForClickable()
await submit.click()
// Wait for the import to finish
await this.getSaveButton().waitForClickable({ timeout: 15000 }) // Can be slow
}
async publishLive () {
await $('#permanentLiveTrue').parentElement().click()
@@ -53,6 +71,7 @@ export class VideoPublishPage extends VideoManage {
await this.goOnPage('Main information')
const nameInput = $('input#name')
await nameInput.scrollIntoView()
await nameInput.clearValue()
await nameInput.setValue(videoName)

View File

@@ -40,7 +40,7 @@ export class VideoWatchPage {
}
isPrivacyWarningDisplayed () {
return $('my-privacy-concerns').isDisplayed()
return $('.privacy-concerns-text').isDisplayed()
}
async goOnAssociatedEmbed (passwordProtected = false) {
@@ -74,12 +74,84 @@ export class VideoWatchPage {
return go(FIXTURE_URLS.HLS_PLAYLIST_EMBED)
}
getModalTitleEl () {
return $('.modal-content .modal-title')
}
confirmModal () {
return $('.modal-content .modal-footer .primary-button').click()
}
private async getVideoNameElement () {
// We have 2 video info name block, pick the first that is not empty
const elem = async () => {
const elems = await $$('.video-info-first-row .video-info-name').filter(e => e.isDisplayed())
return elems[0]
}
await browser.waitUntil(async () => {
const e = await elem()
return e?.isDisplayed()
})
return elem()
}
// ---------------------------------------------------------------------------
// Video password
// ---------------------------------------------------------------------------
isPasswordProtected () {
return $('#confirmInput').isExisting()
}
async fillVideoPassword (videoPassword: string) {
const videoPasswordInput = $('input#confirmInput')
await videoPasswordInput.waitForClickable()
await videoPasswordInput.clearValue()
await videoPasswordInput.setValue(videoPassword)
const confirmButton = $('input[value="Confirm"]')
await confirmButton.waitForClickable()
return confirmButton.click()
}
// ---------------------------------------------------------------------------
// Video actions
// ---------------------------------------------------------------------------
async like () {
const likeButton = $('.action-button-like')
const isActivated = (await likeButton.getAttribute('class')).includes('activated')
let count: number
try {
count = parseInt(await $('.action-button-like > .count').getText())
} catch (error) {
count = 0
}
await likeButton.waitForClickable()
await likeButton.click()
if (isActivated) {
if (count === 1) {
return expect(!await $('.action-button-like > .count').isExisting())
} else {
return expect(parseInt(await $('.action-button-like > .count').getText())).toBe(count - 1)
}
} else {
return expect(parseInt(await $('.action-button-like > .count').getText())).toBe(count + 1)
}
}
async clickOnManage () {
await this.clickOnMoreDropdownIcon()
const items = await $$('.dropdown-menu.show .dropdown-item')
for (const item of items) {
// We need the await expression
return $$('.dropdown-menu.show .dropdown-item').mapSeries(async item => {
const content = await item.getText()
if (content.includes('Manage')) {
@@ -87,11 +159,27 @@ export class VideoWatchPage {
await $('#name').waitForClickable()
return
}
}
})
}
clickOnSave () {
return $('.action-button-save').click()
async clickOnMoreDropdownIcon () {
const dropdown = $('my-video-actions-dropdown .action-button')
await dropdown.scrollIntoView({ block: 'center' })
await dropdown.click()
await $('.dropdown-menu.show .dropdown-item').waitForDisplayed()
}
// ---------------------------------------------------------------------------
// Playlists
// ---------------------------------------------------------------------------
async clickOnSave () {
const button = $('.action-button-save')
await button.scrollIntoView({ block: 'center' })
return button.click()
}
async createPlaylist (name: string) {
@@ -116,101 +204,41 @@ export class VideoWatchPage {
return playlist().click()
}
async clickOnMoreDropdownIcon () {
const dropdown = $('my-video-actions-dropdown .action-button')
await dropdown.click()
await $('.dropdown-menu.show .dropdown-item').waitForDisplayed()
}
private async getVideoNameElement () {
// We have 2 video info name block, pick the first that is not empty
const elem = async () => {
const elems = await $$('.video-info-first-row .video-info-name').filter(e => e.isDisplayed())
return elems[0]
}
await browser.waitUntil(async () => {
const e = await elem()
return e?.isDisplayed()
})
return elem()
}
isPasswordProtected () {
return $('#confirmInput').isExisting()
}
async fillVideoPassword (videoPassword: string) {
const videoPasswordInput = await $('input#confirmInput')
await videoPasswordInput.waitForClickable()
await videoPasswordInput.clearValue()
await videoPasswordInput.setValue(videoPassword)
const confirmButton = await $('input[value="Confirm"]')
await confirmButton.waitForClickable()
return confirmButton.click()
}
async like () {
const likeButton = await $('.action-button-like')
const isActivated = (await likeButton.getAttribute('class')).includes('activated')
let count: number
try {
count = parseInt(await $('.action-button-like > .count').getText())
} catch (error) {
count = 0
}
await likeButton.waitForClickable()
await likeButton.click()
if (isActivated) {
if (count === 1) {
return expect(!await $('.action-button-like > .count').isExisting())
} else {
return expect(parseInt(await $('.action-button-like > .count').getText())).toBe(count - 1)
}
} else {
return expect(parseInt(await $('.action-button-like > .count').getText())).toBe(count + 1)
}
}
// ---------------------------------------------------------------------------
// Comments
// ---------------------------------------------------------------------------
async createThread (comment: string) {
const textarea = await $('my-video-comment-add textarea')
const textarea = $('my-video-comment-add textarea')
await textarea.waitForClickable()
await textarea.setValue(comment)
const confirmButton = await $('.comment-buttons .primary-button')
const confirmButton = $('.comment-buttons .primary-button')
await confirmButton.waitForClickable()
await confirmButton.click()
const createdComment = await (await $('.comment-html p')).getText()
const createdComment = await $('.comment-html p').getText()
return expect(createdComment).toBe(comment)
}
async createReply (comment: string) {
const replyButton = await $('button.comment-action-reply')
const replyButton = $('button.comment-action-reply')
await replyButton.waitForClickable()
await replyButton.scrollIntoView({ block: 'center' })
await replyButton.click()
const textarea = await $('my-video-comment my-video-comment-add textarea')
const textarea = $('my-video-comment my-video-comment-add textarea')
await textarea.waitForClickable()
await textarea.setValue(comment)
const confirmButton = await $('my-video-comment .comment-buttons .primary-button')
const confirmButton = $('my-video-comment .comment-buttons .primary-button')
await confirmButton.waitForClickable()
await replyButton.scrollIntoView({ block: 'center' })
await confirmButton.click()
const createdComment = await $('.is-child .comment-html p')
const createdComment = $('.is-child .comment-html p')
await createdComment.waitForDisplayed()
return expect(await createdComment.getText()).toBe(comment)

View File

@@ -1,6 +1,6 @@
import { PlayerPage } from '../po/player.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { FIXTURE_URLS, go, isMobileDevice, isSafari } from '../utils'
import { FIXTURE_URLS, go, isMobileDevice, isSafari, prepareWebBrowser } from '../utils'
describe('Live all workflow', () => {
let videoWatchPage: VideoWatchPage
@@ -10,9 +10,7 @@ describe('Live all workflow', () => {
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
playerPage = new PlayerPage()
if (!isMobileDevice()) {
await browser.maximizeWindow()
}
await prepareWebBrowser()
})
it('Should go to the live page', async () => {

View File

@@ -1,7 +1,7 @@
import { LoginPage } from '../po/login.po'
import { PlayerPage } from '../po/player.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { FIXTURE_URLS, go, isMobileDevice, isSafari } from '../utils'
import { FIXTURE_URLS, go, isMobileDevice, isSafari, prepareWebBrowser } from '../utils'
async function checkCorrectlyPlay (playerPage: PlayerPage) {
await playerPage.playAndPauseVideo(false, 2)
@@ -22,9 +22,7 @@ describe('Private videos all workflow', () => {
loginPage = new LoginPage(isMobileDevice())
playerPage = new PlayerPage()
if (!isMobileDevice()) {
await browser.maximizeWindow()
}
await prepareWebBrowser()
})
it('Should log in', async () => {

View File

@@ -2,10 +2,10 @@ import { LoginPage } from '../po/login.po'
import { MyAccountPage } from '../po/my-account.po'
import { PlayerPage } from '../po/player.po'
import { VideoListPage } from '../po/video-list.po'
import { VideoUpdatePage } from '../po/video-update.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { VideoUpdatePage } from '../po/video-update.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { FIXTURE_URLS, go, isIOS, isMobileDevice, isSafari, waitServerUp } from '../utils'
import { FIXTURE_URLS, go, isIOS, isMobileDevice, isSafari, prepareWebBrowser, waitServerUp } from '../utils'
function isUploadUnsupported () {
if (isMobileDevice() || isSafari()) {
@@ -53,9 +53,7 @@ describe('Videos all workflow', () => {
playerPage = new PlayerPage()
videoListPage = new VideoListPage(isMobileDevice(), isSafari())
if (!isMobileDevice()) {
await browser.maximizeWindow()
}
await prepareWebBrowser()
})
it('Should log in', async () => {

View File

@@ -1,7 +1,7 @@
import { LoginPage } from '../po/login.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { getScreenshotPath, go, isMobileDevice, isSafari, waitServerUp } from '../utils'
import { getScreenshotPath, go, isMobileDevice, isSafari, prepareWebBrowser, waitServerUp } from '../utils'
describe('Custom server defaults', () => {
let videoPublishPage: VideoPublishPage
@@ -15,7 +15,7 @@ describe('Custom server defaults', () => {
videoPublishPage = new VideoPublishPage()
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
await browser.maximizeWindow()
await prepareWebBrowser()
})
describe('Publish default values', function () {

View File

@@ -0,0 +1,393 @@
import { NSFWPolicyType } from '@peertube/peertube-models'
import { AdminConfigPage } from '../po/admin-config.po'
import { AdminUserPage } from '../po/admin-user.po'
import { AnonymousSettingsPage } from '../po/anonymous-settings.po'
import { LoginPage } from '../po/login.po'
import { MyAccountPage } from '../po/my-account.po'
import { PlayerPage } from '../po/player.po'
import { VideoListPage } from '../po/video-list.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { VideoSearchPage } from '../po/video-search.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { getScreenshotPath, go, isMobileDevice, isSafari, prepareWebBrowser, waitServerUp } from '../utils'
describe('NSFW', () => {
let videoListPage: VideoListPage
let videoPublishPage: VideoPublishPage
let adminConfigPage: AdminConfigPage
let loginPage: LoginPage
let adminUserPage: AdminUserPage
let myAccountPage: MyAccountPage
let videoSearchPage: VideoSearchPage
let videoWatchPage: VideoWatchPage
let playerPage: PlayerPage
let anonymousSettingsPage: AnonymousSettingsPage
const seed = Math.random()
const nsfwVideo = seed + ' - nsfw'
const violentVideo = seed + ' - violent'
const normalVideo = seed + ' - normal'
let videoUrl: string
async function checkVideo (options: {
policy: NSFWPolicyType
videoName: string
nsfwTooltip?: string
}) {
const { policy, videoName, nsfwTooltip } = options
if (policy === 'do_not_list') {
expect(await videoListPage.isVideoDisplayed(videoName)).toBeFalsy()
} else if (policy === 'warn') {
expect(await videoListPage.isVideoDisplayed(videoName)).toBeTruthy()
expect(await videoListPage.isVideoBlurred(videoName)).toBeFalsy()
expect(await videoListPage.hasVideoWarning(videoName)).toBeTruthy()
} else if (policy === 'blur') {
expect(await videoListPage.isVideoDisplayed(videoName)).toBeTruthy()
expect(await videoListPage.isVideoBlurred(videoName)).toBeTruthy()
expect(await videoListPage.hasVideoWarning(videoName)).toBeTruthy()
} else { // Display
expect(await videoListPage.isVideoDisplayed(videoName)).toBeTruthy()
expect(await videoListPage.isVideoBlurred(videoName)).toBeFalsy()
expect(await videoListPage.hasVideoWarning(videoName)).toBeFalsy()
}
if (nsfwTooltip) {
await videoListPage.expectVideoNSFWTooltip(videoName, nsfwTooltip)
}
}
async function checkFilterText (policy: NSFWPolicyType) {
const pagesWithFilters = [
videoListPage.goOnRootAccount.bind(videoListPage),
videoListPage.goOnBrowseVideos.bind(videoListPage),
videoListPage.goOnRootChannel.bind(videoListPage)
]
for (const goOnPage of pagesWithFilters) {
await goOnPage()
const filterText = await videoListPage.getNSFWFilterText()
if (policy === 'do_not_list') {
expect(filterText).toContain('hidden')
} else if (policy === 'warn') {
expect(filterText).toContain('warned')
} else if (policy === 'blur') {
expect(filterText).toContain('blurred')
} else {
expect(filterText).toContain('displayed')
}
}
}
async function checkCommonVideoListPages (policy: NSFWPolicyType, videos: string[], nsfwTooltip?: string) {
const pages = [
videoListPage.goOnRootAccount.bind(videoListPage),
videoListPage.goOnBrowseVideos.bind(videoListPage),
videoListPage.goOnRootChannel.bind(videoListPage),
videoListPage.goOnRootAccountChannels.bind(videoListPage),
videoListPage.goOnHomepage.bind(videoListPage)
]
for (const goOnPage of pages) {
await goOnPage()
for (const video of videos) {
await browser.saveScreenshot(getScreenshotPath('before-test.png'))
await checkVideo({ policy, videoName: video, nsfwTooltip })
}
}
for (const video of videos) {
await videoSearchPage.search(video)
await browser.saveScreenshot(getScreenshotPath('before-test.png'))
await checkVideo({ policy, videoName: video, nsfwTooltip })
}
}
async function updateAdminNSFW (nsfw: NSFWPolicyType) {
await adminConfigPage.updateNSFWSetting(nsfw)
await adminConfigPage.save()
}
async function updateUserNSFW (nsfw: NSFWPolicyType, loggedIn: boolean) {
if (loggedIn) {
await myAccountPage.navigateToMySettings()
await myAccountPage.updateNSFW(nsfw)
return
}
await anonymousSettingsPage.openSettings()
await anonymousSettingsPage.updateNSFW(nsfw)
await anonymousSettingsPage.closeSettings()
}
async function updateUserViolentNSFW (nsfw: NSFWPolicyType, loggedIn: boolean) {
if (loggedIn) {
await myAccountPage.navigateToMySettings()
await myAccountPage.updateViolentFlag(nsfw)
return
}
await anonymousSettingsPage.openSettings()
await anonymousSettingsPage.updateViolentFlag(nsfw)
await anonymousSettingsPage.closeSettings()
}
before(async () => {
await waitServerUp()
})
beforeEach(async () => {
videoListPage = new VideoListPage(isMobileDevice(), isSafari())
adminConfigPage = new AdminConfigPage()
loginPage = new LoginPage(isMobileDevice())
adminUserPage = new AdminUserPage()
videoPublishPage = new VideoPublishPage()
myAccountPage = new MyAccountPage()
videoSearchPage = new VideoSearchPage()
playerPage = new PlayerPage()
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
anonymousSettingsPage = new AnonymousSettingsPage()
await prepareWebBrowser()
})
describe('Preparation', function () {
it('Should login and disable NSFW', async () => {
await loginPage.loginAsRootUser()
await updateUserNSFW('display', true)
})
it('Should set the homepage', async () => {
await adminConfigPage.updateHomepage('<peertube-videos-list data-sort="-publishedAt"></peertube-videos-list>')
await adminConfigPage.save()
})
it('Should create a user', async () => {
await adminUserPage.createUser({
username: 'user_' + seed,
password: 'superpassword'
})
})
it('Should upload NSFW and normal videos', async () => {
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video.mp4')
await videoPublishPage.setAsNSFW()
await videoPublishPage.validSecondStep(nsfwVideo)
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video.mp4')
await videoPublishPage.setAsNSFW({ summary: 'bibi is violent', violent: true })
await videoPublishPage.validSecondStep(violentVideo)
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video2.mp4')
await videoPublishPage.validSecondStep(normalVideo)
})
it('Should logout', async function () {
await loginPage.logout()
})
})
describe('NSFW with an anonymous users using instance default', function () {
it('Should correctly handle do not list', async () => {
await loginPage.loginAsRootUser()
await updateAdminNSFW('do_not_list')
await loginPage.logout()
await checkCommonVideoListPages('do_not_list', [ nsfwVideo, violentVideo ])
await checkCommonVideoListPages('display', [ normalVideo ])
await checkFilterText('do_not_list')
})
it('Should correctly handle blur', async () => {
await loginPage.loginAsRootUser()
await updateAdminNSFW('blur')
await loginPage.logout()
await checkCommonVideoListPages('blur', [ nsfwVideo, violentVideo ])
await checkCommonVideoListPages('display', [ normalVideo ])
await checkFilterText('blur')
})
it('Should not autoplay the video and display a warning on watch/embed page', async function () {
await videoListPage.clickOnVideo(nsfwVideo)
await videoWatchPage.waitWatchVideoName(nsfwVideo)
videoUrl = await browser.getUrl()
const check = async () => {
expect(await playerPage.getPlayButton().isDisplayed()).toBeTruthy()
expect(await playerPage.getNSFWContentText()).toContain('This video contains sensitive content')
expect(await playerPage.getMoreNSFWInfoButton().isDisplayed()).toBeFalsy()
expect(await playerPage.hasPoster()).toBeFalsy()
}
await check()
await videoWatchPage.goOnAssociatedEmbed()
await check()
})
it('Should correctly handle warn', async () => {
await loginPage.loginAsRootUser()
await updateAdminNSFW('warn')
await loginPage.logout()
await checkCommonVideoListPages('warn', [ nsfwVideo, violentVideo ])
await checkCommonVideoListPages('display', [ normalVideo ])
await checkFilterText('warn')
})
it('Should not autoplay the video and display a warning on watch/embed page', async function () {
await videoListPage.clickOnVideo(violentVideo)
await videoWatchPage.waitWatchVideoName(violentVideo)
const check = async () => {
expect(await playerPage.getPlayButton().isDisplayed()).toBeTruthy()
expect(await playerPage.getNSFWContentText()).toContain('This video contains sensitive content')
expect(await playerPage.hasPoster()).toBeTruthy()
const moreButton = playerPage.getMoreNSFWInfoButton()
expect(await moreButton.isDisplayed()).toBeTruthy()
await moreButton.click()
await playerPage.getNSFWDetailsContent().waitForDisplayed()
const moreContent = await playerPage.getNSFWDetailsContent().getText()
expect(moreContent).toContain('Potentially violent content')
expect(moreContent).toContain('bibi is violent')
}
await check()
await videoWatchPage.goOnAssociatedEmbed()
await check()
})
it('Should correctly handle display', async () => {
await loginPage.loginAsRootUser()
await updateAdminNSFW('display')
await loginPage.logout()
await checkCommonVideoListPages('display', [ nsfwVideo, violentVideo, normalVideo ])
await checkFilterText('display')
})
it('Should autoplay the video on watch page', async function () {
await videoListPage.clickOnVideo(nsfwVideo)
await videoWatchPage.waitWatchVideoName(nsfwVideo)
expect(await playerPage.getPlayButton().isDisplayed()).toBeFalsy()
})
})
describe('NSFW settings', function () {
function runSuite (loggedIn: boolean) {
it('Should correctly handle do not list', async () => {
await updateUserNSFW('do_not_list', loggedIn)
await checkCommonVideoListPages('do_not_list', [ nsfwVideo, violentVideo ])
await checkCommonVideoListPages('display', [ normalVideo ])
await checkFilterText('do_not_list')
})
it('Should use a confirm modal when viewing the video and watch the video', async function () {
await go(videoUrl)
const confirmTitle = videoWatchPage.getModalTitleEl()
await confirmTitle.waitForDisplayed()
expect(await confirmTitle.getText()).toContain('Sensitive video')
await videoWatchPage.confirmModal()
await videoWatchPage.waitWatchVideoName(nsfwVideo)
})
it('Should correctly handle blur', async () => {
await updateUserNSFW('blur', loggedIn)
await checkCommonVideoListPages('blur', [ nsfwVideo ], 'This video contains sensitive content')
await checkCommonVideoListPages('blur', [ violentVideo ], 'This video contains sensitive content: violence')
await checkCommonVideoListPages('display', [ normalVideo ])
await checkFilterText('blur')
})
it('Should correctly handle warn', async () => {
await updateUserNSFW('warn', loggedIn)
await checkCommonVideoListPages('warn', [ nsfwVideo ], 'This video contains sensitive content')
await checkCommonVideoListPages('warn', [ violentVideo ], 'This video contains sensitive content: violence')
await checkCommonVideoListPages('display', [ normalVideo ])
await checkFilterText('warn')
})
it('Should correctly handle display', async () => {
await updateUserNSFW('display', loggedIn)
await checkCommonVideoListPages('display', [ nsfwVideo, violentVideo, normalVideo ])
await checkFilterText('display')
})
it('Should update the setting to blur violent video with display NSFW setting', async () => {
await updateUserViolentNSFW('blur', loggedIn)
await checkCommonVideoListPages('display', [ nsfwVideo, normalVideo ])
await checkCommonVideoListPages('blur', [ violentVideo ])
})
it('Should update the setting to hide NSFW videos but warn violent videos', async () => {
await updateUserNSFW('do_not_list', loggedIn)
await updateUserViolentNSFW('warn', loggedIn)
await checkCommonVideoListPages('display', [ normalVideo ])
await checkCommonVideoListPages('warn', [ violentVideo ])
await checkCommonVideoListPages('do_not_list', [ nsfwVideo ])
})
it('Should update the setting to blur NSFW videos and hide violent videos', async () => {
await updateUserNSFW('blur', loggedIn)
await updateUserViolentNSFW('do_not_list', loggedIn)
await checkCommonVideoListPages('display', [ normalVideo ])
await checkCommonVideoListPages('do_not_list', [ violentVideo ])
await checkCommonVideoListPages('blur', [ nsfwVideo ])
})
}
describe('NSFW with an anonymous user', function () {
runSuite(false)
})
describe('NSFW with a logged in users', function () {
before(async () => {
await loginPage.login({ username: 'user_' + seed, password: 'superpassword' })
})
runSuite(true)
after(async () => {
await loginPage.logout()
})
})
})
})

View File

@@ -0,0 +1,119 @@
import { AdminConfigPage } from '../po/admin-config.po'
import { LoginPage } from '../po/login.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { getScreenshotPath, go, isMobileDevice, isSafari, prepareWebBrowser, selectCustomSelect, waitServerUp } from '../utils'
// These tests help to notice crash with invalid translated strings
describe('Page crash', () => {
let videoPublishPage: VideoPublishPage
let loginPage: LoginPage
let videoWatchPage: VideoWatchPage
let adminConfigPage: AdminConfigPage
const languages = [
'العربية',
'Català',
'Čeština',
'Deutsch',
'ελληνικά',
'Esperanto',
'Español',
'Euskara',
'فارسی',
'Suomi',
'Français',
'Gàidhlig',
'Galego',
'Hrvatski',
'Magyar',
'Íslenska',
'Italiano',
'日本語',
'Taqbaylit',
'Norsk bokmål',
'Nederlands',
'Norsk nynorsk',
'Occitan',
'Polski',
'Português (Brasil)',
'Português (Portugal)',
'Pусский',
'Slovenčina',
'Shqip',
'Svenska',
'ไทย',
'Toki Pona',
'Türkçe',
'украї́нська мо́ва',
'Tiếng Việt',
'简体中文(中国)',
'繁體中文(台灣)'
]
before(async () => {
await waitServerUp()
adminConfigPage = new AdminConfigPage()
loginPage = new LoginPage(isMobileDevice())
videoPublishPage = new VideoPublishPage()
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
await prepareWebBrowser()
await loginPage.loginAsRootUser()
})
for (const language of languages) {
describe('For language: ' + language, () => {
it('Should change the language', async function () {
await go('/')
await $('.settings-button').waitForClickable()
await $('.settings-button').click()
await selectCustomSelect('language', language)
await $('my-user-interface-settings .primary-button').waitForClickable()
await $('my-user-interface-settings .primary-button').click()
})
it('Should upload and watch a video', async function () {
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video3.mp4')
await videoPublishPage.validSecondStep('video')
await videoPublishPage.clickOnWatch()
await videoWatchPage.waitWatchVideoName('video')
})
it('Should set a homepage', async function () {
await adminConfigPage.updateHomepage('My custom homepage content')
await adminConfigPage.save()
// All tests
await go('/home')
await $('*=My custom homepage content').waitForDisplayed()
})
it('Should go on client pages and not crash', async function () {
await $('a[href="/videos/overview"]').waitForClickable()
await $('a[href="/videos/overview"]').click()
await $('my-video-overview').waitForExist()
})
it('Should go on videos from subscriptions pages', async function () {
await $('a[href="/videos/subscriptions"]').waitForClickable()
await $('a[href="/videos/subscriptions"]').click()
await $('my-videos-user-subscriptions').waitForExist()
})
after(async () => {
await browser.saveScreenshot(getScreenshotPath(`after-page-crash-test-${language}.png`))
})
})
}
})

View File

@@ -0,0 +1,87 @@
import { AnonymousSettingsPage } from '../po/anonymous-settings.po'
import { LoginPage } from '../po/login.po'
import { MyAccountPage } from '../po/my-account.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { getScreenshotPath, go, isMobileDevice, isSafari, prepareWebBrowser, waitServerUp } from '../utils'
describe('Player settings', () => {
let videoPublishPage: VideoPublishPage
let loginPage: LoginPage
let videoWatchPage: VideoWatchPage
let myAccountPage: MyAccountPage
let anonymousSettingsPage: AnonymousSettingsPage
before(async () => {
await waitServerUp()
loginPage = new LoginPage(isMobileDevice())
videoPublishPage = new VideoPublishPage()
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
myAccountPage = new MyAccountPage()
anonymousSettingsPage = new AnonymousSettingsPage()
await prepareWebBrowser()
})
describe('P2P', function () {
let videoUrl: string
async function goOnVideoWatchPage () {
await go(videoUrl)
await videoWatchPage.waitWatchVideoName('video')
}
async function checkP2P (enabled: boolean) {
await goOnVideoWatchPage()
expect(await videoWatchPage.isPrivacyWarningDisplayed()).toEqual(enabled)
await videoWatchPage.goOnAssociatedEmbed()
expect(await videoWatchPage.isEmbedWarningDisplayed()).toEqual(enabled)
}
before(async () => {
await loginPage.loginAsRootUser()
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video.mp4')
await videoPublishPage.validSecondStep('video')
await videoPublishPage.clickOnWatch()
await videoWatchPage.waitWatchVideoName('video')
videoUrl = await browser.getUrl()
})
beforeEach(async function () {
await goOnVideoWatchPage()
})
it('Should have P2P enabled for a logged in user', async function () {
await checkP2P(true)
})
it('Should disable P2P for a logged in user', async function () {
await myAccountPage.navigateToMySettings()
await myAccountPage.clickOnP2PCheckbox()
await checkP2P(false)
})
it('Should have P2P enabled for anonymous users', async function () {
await loginPage.logout()
await checkP2P(true)
})
it('Should disable P2P for an anonymous user', async function () {
await anonymousSettingsPage.openSettings()
await anonymousSettingsPage.clickOnP2PCheckbox()
await checkP2P(false)
})
})
after(async () => {
await browser.saveScreenshot(getScreenshotPath('after-test.png'))
})
})

View File

@@ -1,7 +1,7 @@
import { AdminPluginPage } from '../po/admin-plugin.po'
import { LoginPage } from '../po/login.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { getCheckbox, getScreenshotPath, isMobileDevice, waitServerUp } from '../utils'
import { getCheckbox, getScreenshotPath, isMobileDevice, prepareWebBrowser, waitServerUp } from '../utils'
describe('Plugins', () => {
let videoPublishPage: VideoPublishPage
@@ -28,7 +28,7 @@ describe('Plugins', () => {
videoPublishPage = new VideoPublishPage()
adminPluginPage = new AdminPluginPage()
await browser.maximizeWindow()
await prepareWebBrowser()
})
it('Should install hello world plugin', async () => {

View File

@@ -2,7 +2,7 @@ import { AdminConfigPage } from '../po/admin-config.po'
import { LoginPage } from '../po/login.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { getScreenshotPath, isMobileDevice, isSafari, waitServerUp } from '../utils'
import { getScreenshotPath, isMobileDevice, isSafari, prepareWebBrowser, waitServerUp } from '../utils'
describe('Publish live', function () {
let videoPublishPage: VideoPublishPage
@@ -18,7 +18,7 @@ describe('Publish live', function () {
adminConfigPage = new AdminConfigPage()
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
await browser.maximizeWindow()
await prepareWebBrowser()
await loginPage.loginAsRootUser()
})

View File

@@ -1,25 +1,42 @@
import { LoginPage } from '../po/login.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { getScreenshotPath, isMobileDevice, waitServerUp } from '../utils'
import { VideoWatchPage } from '../po/video-watch.po'
import { getScreenshotPath, isMobileDevice, isSafari, prepareWebBrowser, waitServerUp } from '../utils'
describe('Publish video', () => {
let videoPublishPage: VideoPublishPage
let loginPage: LoginPage
let videoWatchPage: VideoWatchPage
before(async () => {
await waitServerUp()
loginPage = new LoginPage(isMobileDevice())
videoPublishPage = new VideoPublishPage()
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
await browser.maximizeWindow()
await prepareWebBrowser()
await loginPage.loginAsRootUser()
})
describe('Default upload values', function () {
it('Should have default video values', async function () {
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video3.mp4')
await videoPublishPage.validSecondStep('video')
await videoPublishPage.clickOnWatch()
await videoWatchPage.waitWatchVideoName('video')
expect(await videoWatchPage.getPrivacy()).toBe('Public')
expect(await videoWatchPage.getLicence()).toBe('Unknown')
expect(await videoWatchPage.isDownloadEnabled()).toBeTruthy()
expect(await videoWatchPage.areCommentsEnabled()).toBeTruthy()
})
})
describe('Common', function () {
before(async function () {
await loginPage.loginAsRootUser()
})
it('Should upload a video and on refresh being redirected to the manage page', async function () {
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video.mp4')
@@ -37,16 +54,26 @@ describe('Publish video', () => {
await videoPublishPage.refresh('scheduled')
// check if works? screenshot
expect(videoPublishPage.getScheduleInput()).toBeDisplayed()
const nextDay = new Date()
nextDay.setDate(nextDay.getDate() + 1)
nextDay.setDate(1)
nextDay.setMonth(nextDay.getMonth() + 1)
const inputDate = new Date(await videoPublishPage.getScheduleInput().getValue())
expect(nextDay.getDate()).toEqual(inputDate.getDate())
expect(nextDay.getMonth()).toEqual(inputDate.getMonth())
expect(nextDay.getFullYear()).toEqual(inputDate.getFullYear())
expect(inputDate.getDate()).toEqual(nextDay.getDate())
expect(inputDate.getMonth()).toEqual(nextDay.getMonth())
expect(inputDate.getFullYear()).toEqual(nextDay.getFullYear())
})
})
describe('Import', function () {
it('Should import a video and on refresh being redirected to the manage page', async function () {
await videoPublishPage.navigateTo()
await videoPublishPage.importVideo()
await videoPublishPage.validSecondStep('second video')
await videoPublishPage.refresh('second video')
})
})

View File

@@ -5,11 +5,13 @@ import { SignupPage } from '../po/signup.po'
import {
browserSleep,
findEmailTo,
getEmailPort,
getScreenshotPath,
getVerificationLink,
go,
isMobileDevice,
MockSMTPServer,
prepareWebBrowser,
waitServerUp
} from '../utils'
@@ -75,6 +77,7 @@ describe('Signup', () => {
}) {
await loginPage.loginAsRootUser()
// Ensure we change the state of the form to "dirty" so we can save the form
await adminConfigPage.toggleSignup(options.enabled)
if (options.enabled) {
@@ -103,7 +106,7 @@ describe('Signup', () => {
signupPage = new SignupPage()
adminRegistrationPage = new AdminRegistrationPage()
await browser.maximizeWindow()
await prepareWebBrowser()
})
describe('Signup disabled', function () {
@@ -189,7 +192,7 @@ describe('Signup', () => {
})
it('Should validate the third step (account)', async function () {
await signupPage.fillAccountStep({ username: 'user_2', displayName: 'user_2 display name', password: 'password' })
await signupPage.fillAccountStep({ username: 'user_2', displayName: 'user_2 display name', password: 'superpassword' })
await signupPage.validateStep()
})
@@ -212,7 +215,7 @@ describe('Signup', () => {
})
it('Should display a message when trying to login with this account', async function () {
const error = await loginPage.getLoginError('user_2', 'password')
const error = await loginPage.getLoginError('user_2', 'superpassword')
expect(error).toContain('awaiting approval')
})
@@ -220,14 +223,14 @@ describe('Signup', () => {
it('Should accept the registration', async function () {
await loginPage.loginAsRootUser()
await adminRegistrationPage.navigateToRegistratonsList()
await adminRegistrationPage.navigateToRegistrationsList()
await adminRegistrationPage.accept('user_2', 'moderation response')
await loginPage.logout()
})
it('Should be able to login with this new account', async function () {
await loginPage.login({ username: 'user_2', password: 'password', displayName: 'user_2 display name' })
await loginPage.login({ username: 'user_2', password: 'superpassword', displayName: 'user_2 display name' })
await loginPage.logout()
})
@@ -236,15 +239,9 @@ describe('Signup', () => {
describe('Email verification enabled', function () {
const emails: any[] = []
let emailPort: number
before(async () => {
const key = browser.options.baseUrl + '-emailPort'
// FIXME: typings are wrong, get returns a promise
// FIXME: use * because the key is not properly escaped by the shared store when using get(key)
emailPort = (await (browser.sharedStore.get('*') as unknown as Promise<number>))[key]
await MockSMTPServer.Instance.collectEmails(emailPort, emails)
await MockSMTPServer.Instance.collectEmails(await getEmailPort(), emails)
})
describe('Direct registration', function () {
@@ -340,7 +337,7 @@ describe('Signup', () => {
username: 'user_4',
displayName: 'user_4 display name',
email: 'user_4@example.com',
password: 'password'
password: 'superpassword'
})
await signupPage.validateStep()
})
@@ -364,7 +361,7 @@ describe('Signup', () => {
})
it('Should display a message when trying to login with this account', async function () {
const error = await loginPage.getLoginError('user_4', 'password')
const error = await loginPage.getLoginError('user_4', 'superpassword')
expect(error).toContain('awaiting approval')
})
@@ -372,7 +369,7 @@ describe('Signup', () => {
it('Should accept the registration', async function () {
await loginPage.loginAsRootUser()
await adminRegistrationPage.navigateToRegistratonsList()
await adminRegistrationPage.navigateToRegistrationsList()
await adminRegistrationPage.accept('user_4', 'moderation response 2')
await loginPage.logout()
@@ -404,4 +401,8 @@ describe('Signup', () => {
MockSMTPServer.Instance.kill()
})
})
after(async () => {
await browser.saveScreenshot(getScreenshotPath('after-test.png'))
})
})

View File

@@ -1,83 +1,79 @@
import { AnonymousSettingsPage } from '../po/anonymous-settings.po'
import { AdminConfigPage } from '../po/admin-config.po'
import { LoginPage } from '../po/login.po'
import { MyAccountPage } from '../po/my-account.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { go, isMobileDevice, isSafari, waitServerUp } from '../utils'
import {
browserSleep,
findEmailTo,
getEmailPort,
getScreenshotPath,
getVerificationLink,
go,
isMobileDevice,
MockSMTPServer,
prepareWebBrowser,
waitServerUp
} from '../utils'
describe('User settings', () => {
let videoPublishPage: VideoPublishPage
let loginPage: LoginPage
let videoWatchPage: VideoWatchPage
let myAccountPage: MyAccountPage
let anonymousSettingsPage: AnonymousSettingsPage
let adminConfigPage: AdminConfigPage
const emails: any[] = []
before(async () => {
await waitServerUp()
loginPage = new LoginPage(isMobileDevice())
videoPublishPage = new VideoPublishPage()
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
myAccountPage = new MyAccountPage()
anonymousSettingsPage = new AnonymousSettingsPage()
adminConfigPage = new AdminConfigPage()
await browser.maximizeWindow()
await MockSMTPServer.Instance.collectEmails(await getEmailPort(), emails)
await prepareWebBrowser()
})
describe('P2P', function () {
let videoUrl: string
async function goOnVideoWatchPage () {
await go(videoUrl)
await videoWatchPage.waitWatchVideoName('video')
}
async function checkP2P (enabled: boolean) {
await goOnVideoWatchPage()
expect(await videoWatchPage.isPrivacyWarningDisplayed()).toEqual(enabled)
await videoWatchPage.goOnAssociatedEmbed()
expect(await videoWatchPage.isEmbedWarningDisplayed()).toEqual(enabled)
}
before(async () => {
describe('Email', function () {
before(async function () {
await loginPage.loginAsRootUser()
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video.mp4')
await videoPublishPage.validSecondStep('video')
await videoPublishPage.clickOnWatch()
await videoWatchPage.waitWatchVideoName('video')
await adminConfigPage.toggleSignup(true)
await adminConfigPage.toggleSignupEmailVerification(true)
await adminConfigPage.save()
videoUrl = await browser.getUrl()
await browser.refresh()
})
beforeEach(async function () {
await goOnVideoWatchPage()
})
it('Should have P2P enabled for a logged in user', async function () {
await checkP2P(true)
})
it('Should disable P2P for a logged in user', async function () {
it('Should ask to change the email', async function () {
await myAccountPage.navigateToMySettings()
await myAccountPage.clickOnP2PCheckbox()
await myAccountPage.updateEmail('email2@example.com', loginPage.getRootPassword())
await checkP2P(false)
const pendingEmailBlock = $('.pending-email')
await pendingEmailBlock.waitForDisplayed()
await expect(pendingEmailBlock).toHaveText(expect.stringContaining('email2@example.com is awaiting email verification'))
let email: { text: string }
while (!(email = findEmailTo(emails, 'email2@example.com'))) {
await browserSleep(100)
}
await go(getVerificationLink(email))
const alertBlock = $('.alert-success')
await alertBlock.waitForDisplayed()
await expect(alertBlock).toHaveText(expect.stringContaining('Email updated'))
await myAccountPage.navigateToMySettings()
const changeEmailBlock = $('.change-email .form-group-description')
await changeEmailBlock.waitForDisplayed()
await expect(changeEmailBlock).toHaveText(expect.stringContaining('Your current email is email2@example.com'))
})
})
it('Should have P2P enabled for anonymous users', async function () {
await loginPage.logout()
after(async () => {
MockSMTPServer.Instance.kill()
await checkP2P(true)
})
it('Should disable P2P for an anonymous user', async function () {
await anonymousSettingsPage.openSettings()
await anonymousSettingsPage.clickOnP2PCheckbox()
await checkP2P(false)
})
await browser.saveScreenshot(getScreenshotPath('after-test.png'))
})
})

View File

@@ -4,7 +4,7 @@ import { PlayerPage } from '../po/player.po'
import { SignupPage } from '../po/signup.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { getScreenshotPath, go, isMobileDevice, isSafari, waitServerUp } from '../utils'
import { getScreenshotPath, go, isMobileDevice, isSafari, prepareWebBrowser, waitServerUp } from '../utils'
describe('Password protected videos', () => {
let videoPublishPage: VideoPublishPage
@@ -50,7 +50,7 @@ describe('Password protected videos', () => {
playerPage = new PlayerPage()
myAccountPage = new MyAccountPage()
await browser.maximizeWindow()
await prepareWebBrowser()
})
describe('Owner', function () {

View File

@@ -1,213 +0,0 @@
import { AdminConfigPage } from '../po/admin-config.po'
import { LoginPage } from '../po/login.po'
import { MyAccountPage } from '../po/my-account.po'
import { VideoListPage } from '../po/video-list.po'
import { VideoSearchPage } from '../po/video-search.po'
import { VideoPublishPage } from '../po/video-publish.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { NSFWPolicy } from '../types/common'
import { isMobileDevice, isSafari, waitServerUp } from '../utils'
describe('Videos list', () => {
let videoListPage: VideoListPage
let videoPublishPage: VideoPublishPage
let adminConfigPage: AdminConfigPage
let loginPage: LoginPage
let myAccountPage: MyAccountPage
let videoSearchPage: VideoSearchPage
let videoWatchPage: VideoWatchPage
const seed = Math.random()
const nsfwVideo = seed + ' - nsfw'
const normalVideo = seed + ' - normal'
async function checkNormalVideo () {
expect(await videoListPage.videoExists(normalVideo)).toBeTruthy()
expect(await videoListPage.videoIsBlurred(normalVideo)).toBeFalsy()
}
async function checkNSFWVideo (policy: NSFWPolicy, filterText?: string) {
if (policy === 'do_not_list') {
if (filterText) expect(filterText).toContain('hidden')
expect(await videoListPage.videoExists(nsfwVideo)).toBeFalsy()
return
}
if (policy === 'blur') {
if (filterText) expect(filterText).toContain('blurred')
expect(await videoListPage.videoExists(nsfwVideo)).toBeTruthy()
expect(await videoListPage.videoIsBlurred(nsfwVideo)).toBeTruthy()
return
}
// display
if (filterText) expect(filterText).toContain('displayed')
expect(await videoListPage.videoExists(nsfwVideo)).toBeTruthy()
expect(await videoListPage.videoIsBlurred(nsfwVideo)).toBeFalsy()
}
async function checkCommonVideoListPages (policy: NSFWPolicy) {
const promisesWithFilters = [
videoListPage.goOnRootAccount.bind(videoListPage),
videoListPage.goOnBrowseVideos.bind(videoListPage),
videoListPage.goOnRootChannel.bind(videoListPage)
]
for (const p of promisesWithFilters) {
await p()
const filter = await videoListPage.getNSFWFilter()
const filterText = await filter.getText()
await checkNormalVideo()
await checkNSFWVideo(policy, filterText)
}
const promisesWithoutFilters = [
videoListPage.goOnRootAccountChannels.bind(videoListPage),
videoListPage.goOnHomepage.bind(videoListPage)
]
for (const p of promisesWithoutFilters) {
await p()
await checkNormalVideo()
await checkNSFWVideo(policy)
}
}
async function checkSearchPage (policy: NSFWPolicy) {
await videoSearchPage.search(normalVideo)
await checkNormalVideo()
await videoSearchPage.search(nsfwVideo)
await checkNSFWVideo(policy)
}
async function updateAdminNSFW (nsfw: NSFWPolicy) {
await adminConfigPage.updateNSFWSetting(nsfw)
await adminConfigPage.save()
}
async function updateUserNSFW (nsfw: NSFWPolicy) {
await myAccountPage.navigateToMySettings()
await myAccountPage.updateNSFW(nsfw)
}
before(async () => {
await waitServerUp()
})
beforeEach(async () => {
videoListPage = new VideoListPage(isMobileDevice(), isSafari())
adminConfigPage = new AdminConfigPage()
loginPage = new LoginPage(isMobileDevice())
videoPublishPage = new VideoPublishPage()
myAccountPage = new MyAccountPage()
videoSearchPage = new VideoSearchPage()
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
await browser.maximizeWindow()
})
it('Should login and disable NSFW', async () => {
await loginPage.loginAsRootUser()
await updateUserNSFW('display')
})
it('Should set the homepage', async () => {
await adminConfigPage.updateHomepage('<peertube-videos-list data-sort="-publishedAt"></peertube-videos-list>')
await adminConfigPage.save()
})
it('Should upload 2 videos (NSFW and classic videos)', async () => {
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video.mp4')
await videoPublishPage.setAsNSFW()
await videoPublishPage.validSecondStep(nsfwVideo)
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video2.mp4')
await videoPublishPage.validSecondStep(normalVideo)
})
it('Should logout', async function () {
await loginPage.logout()
})
describe('Anonymous users', function () {
it('Should correctly handle do not list', async () => {
await loginPage.loginAsRootUser()
await updateAdminNSFW('do_not_list')
await loginPage.logout()
await checkCommonVideoListPages('do_not_list')
await checkSearchPage('do_not_list')
})
it('Should correctly handle blur', async () => {
await loginPage.loginAsRootUser()
await updateAdminNSFW('blur')
await loginPage.logout()
await checkCommonVideoListPages('blur')
await checkSearchPage('blur')
})
it('Should correctly handle display', async () => {
await loginPage.loginAsRootUser()
await updateAdminNSFW('display')
await loginPage.logout()
await checkCommonVideoListPages('display')
await checkSearchPage('display')
})
})
describe('Logged in users', function () {
before(async () => {
await loginPage.loginAsRootUser()
})
it('Should correctly handle do not list', async () => {
await updateUserNSFW('do_not_list')
await checkCommonVideoListPages('do_not_list')
await checkSearchPage('do_not_list')
})
it('Should correctly handle blur', async () => {
await updateUserNSFW('blur')
await checkCommonVideoListPages('blur')
await checkSearchPage('blur')
})
it('Should correctly handle display', async () => {
await updateUserNSFW('display')
await checkCommonVideoListPages('display')
await checkSearchPage('display')
})
after(async () => {
await loginPage.logout()
})
})
describe('Default upload values', function () {
it('Should have default video values', async function () {
await loginPage.loginAsRootUser()
await videoPublishPage.navigateTo()
await videoPublishPage.uploadVideo('video3.mp4')
await videoPublishPage.validSecondStep('video')
await videoPublishPage.clickOnWatch()
await videoWatchPage.waitWatchVideoName('video')
expect(await videoWatchPage.getPrivacy()).toBe('Public')
expect(await videoWatchPage.getLicence()).toBe('Unknown')
expect(await videoWatchPage.isDownloadEnabled()).toBeTruthy()
expect(await videoWatchPage.areCommentsEnabled()).toBeTruthy()
})
})
})

View File

@@ -1 +0,0 @@
export type NSFWPolicy = 'do_not_list' | 'blur' | 'display'

View File

@@ -1,29 +1,31 @@
async function browserSleep (amount: number) {
export async function browserSleep (amount: number) {
await browser.pause(amount)
}
function isMobileDevice () {
// ---------------------------------------------------------------------------
export function isMobileDevice () {
const platformName = (browser.capabilities['platformName'] || '').toLowerCase()
return platformName === 'android' || platformName === 'ios'
}
function isAndroid () {
export function isAndroid () {
const platformName = (browser.capabilities['platformName'] || '').toLowerCase()
return platformName === 'android'
}
function isSafari () {
export function isSafari () {
return browser.capabilities['browserName'] &&
browser.capabilities['browserName'].toLowerCase() === 'safari'
browser.capabilities['browserName'].toLowerCase() === 'safari'
}
function isIOS () {
export function isIOS () {
return isMobileDevice() && isSafari()
}
async function go (url: string) {
export async function go (url: string) {
await browser.url(url)
await browser.execute(() => {
@@ -33,7 +35,20 @@ async function go (url: string) {
})
}
async function waitServerUp () {
// ---------------------------------------------------------------------------
export async function prepareWebBrowser () {
if (isMobileDevice()) return
// Window size on chromium doesn't seem to work in "new" headless mode
if (process.env.MOZ_HEADLESS_WIDTH) {
await browser.setWindowSize(+process.env.MOZ_HEADLESS_WIDTH, +process.env.MOZ_HEADLESS_HEIGHT)
}
await browser.maximizeWindow()
}
export async function waitServerUp () {
await browser.waitUntil(async () => {
await go('/')
await browserSleep(500)
@@ -41,13 +56,3 @@ async function waitServerUp () {
return $('<my-app>').isDisplayed()
}, { timeout: 20 * 1000 })
}
export {
isMobileDevice,
isSafari,
isIOS,
isAndroid,
waitServerUp,
go,
browserSleep
}

View File

@@ -38,25 +38,38 @@ export async function clickOnRadio (name: string) {
export async function selectCustomSelect (id: string, valueLabel: string) {
const wrapper = $(`[formcontrolname=${id}] span[role=combobox]`)
await wrapper.waitForExist()
await wrapper.scrollIntoView({ block: 'center' })
await wrapper.waitForClickable()
await wrapper.click()
const option = await $$(`[formcontrolname=${id}] li[role=option]`).filter(async o => {
const text = await o.getText()
const getOption = async () => {
const options = await $$(`[formcontrolname=${id}] li[role=option]`).filter(async o => {
const text = await o.getText()
return text.trimStart().startsWith(valueLabel)
}).then(options => options[0])
return text.trimStart().startsWith(valueLabel)
})
await option.waitForDisplayed()
if (options.length === 0) return undefined
return option.click()
return options[0]
}
await browser.waitUntil(async () => {
const option = await getOption()
if (!option) return false
return option.isDisplayed()
})
return (await getOption()).click()
}
export async function findParentElement (
el: WebdriverIO.Element,
finder: (el: WebdriverIO.Element) => Promise<boolean>
el: ChainablePromiseElement,
finder: (el: ChainablePromiseElement) => Promise<boolean>
) {
if (await finder(el) === true) return el
return findParentElement(await el.parentElement(), finder)
return findParentElement(el.parentElement(), finder)
}

View File

@@ -1,4 +1,4 @@
function getVerificationLink (email: { text: string }) {
export function getVerificationLink (email: { text: string }) {
const { text } = email
const regexp = /\[(?<link>http:\/\/[^\]]+)\]/g
@@ -9,13 +9,15 @@ function getVerificationLink (email: { text: string }) {
for (const match of matched) {
const link = match.groups.link
if (link.includes('/verify-account/')) return link
if (link.includes('/verify-account/')) {
return link.replace('127.0.0.1', 'localhost')
}
}
throw new Error('Could not find /verify-account/ link')
}
function findEmailTo (emails: { text: string, to: { address: string }[] }[], to: string) {
export function findEmailTo (emails: { text: string, to: { address: string }[] }[], to: string) {
for (const email of emails) {
for (const { address } of email.to) {
if (address === to) return email
@@ -25,7 +27,12 @@ function findEmailTo (emails: { text: string, to: { address: string }[] }[], to:
return undefined
}
export {
getVerificationLink,
findEmailTo
export async function getEmailPort () {
const key = browser.options.baseUrl + '-emailPort'
// FIXME: typings are wrong, get returns a promise
// FIXME: use * because the key is not properly escaped by the shared store when using get(key)
const emailPort = (await (browser.sharedStore.get('*') as unknown as Promise<number>))[key]
if (!emailPort) throw new Error('Invalid email port')
return emailPort
}

View File

@@ -1,17 +1,13 @@
import { mkdirSync } from 'fs'
import { join } from 'path'
import { mkdir, rm } from 'node:fs/promises'
import { join } from 'node:path'
const SCREENSHOTS_DIRECTORY = 'screenshots'
function createScreenshotsDirectory () {
mkdirSync(SCREENSHOTS_DIRECTORY, { recursive: true })
export async function createScreenshotsDirectory () {
await rm(SCREENSHOTS_DIRECTORY, { recursive: true, force: true })
await mkdir(SCREENSHOTS_DIRECTORY, { recursive: true })
}
function getScreenshotPath (filename: string) {
export function getScreenshotPath (filename: string) {
return join(SCREENSHOTS_DIRECTORY, filename)
}
export {
createScreenshotsDirectory,
getScreenshotPath
}

View File

@@ -1,5 +1,5 @@
import { ChildProcessWithoutNullStreams } from 'child_process'
import { basename } from 'path'
import { ChildProcessWithoutNullStreams } from 'node:child_process'
import { basename } from 'node:path'
import { setValue } from '@wdio/shared-store-service'
import { createScreenshotsDirectory } from './files'
import { runCommand, runServer } from './server'
@@ -81,7 +81,7 @@ function buildConfig (suiteFile: string = undefined) {
}
}
if (filename === 'signup.e2e-spec.ts') {
if (filename === 'signup.e2e-spec.ts' || filename === 'user-settings.e2e-spec.ts') {
return {
signup: {
limit: -1

View File

@@ -1,5 +1,5 @@
import { exec, spawn } from 'child_process'
import { join, resolve } from 'path'
import { exec, spawn } from 'node:child_process'
import { join, resolve } from 'node:path'
function runServer (appInstance: number, config: any = {}) {
const env = Object.create(process.env)

View File

@@ -13,7 +13,9 @@ const FIXTURE_URLS = {
HLS_EMBED: 'https://peertube2.cpy.re/videos/embed/969bf103-7818-43b5-94a0-de159e13de50',
HLS_PLAYLIST_EMBED: 'https://peertube2.cpy.re/video-playlists/embed/73804a40-da9a-40c2-b1eb-2c6d9eec8f0a',
LIVE_VIDEO: 'https://peertube2.cpy.re/w/oBw6LwsMWWRkmXYfuYRpJd'
LIVE_VIDEO: 'https://peertube2.cpy.re/w/oBw6LwsMWWRkmXYfuYRpJd',
IMPORT_URL: 'https://download.cpy.re/peertube/good_video.mp4'
}
export {

View File

@@ -7,6 +7,7 @@
"module": "commonjs",
"target": "ES2018",
"typeRoots": [
"../node_modules/@wdio",
"../node_modules/@types",
"../node_modules"
],

View File

@@ -95,18 +95,18 @@ module.exports = {
{
browserName: 'Chrome',
...buildBStackMobileOptions({ sessionName: 'Latest Chrome Android', deviceName: 'Samsung Galaxy S8', osVersion: '7.0' })
...buildBStackMobileOptions({ sessionName: 'Latest Chrome Android', deviceName: 'Samsung Galaxy S10', osVersion: '9.0' })
},
{
browserName: 'Safari',
...buildBStackMobileOptions({ sessionName: 'Safari iPhone', deviceName: 'iPhone 11', osVersion: '14' })
...buildBStackMobileOptions({ sessionName: 'Safari iPhone', deviceName: 'iPhone 12', osVersion: '14' })
},
{
browserName: 'Safari',
...buildBStackMobileOptions({ sessionName: 'Safari iPad', deviceName: 'iPad Pro 11 2020', osVersion: '14' })
...buildBStackMobileOptions({ sessionName: 'Safari iPad', deviceName: 'iPad Pro 12.9 2021', osVersion: '14' })
}
],
@@ -121,7 +121,8 @@ module.exports = {
services: [
[
'browserstack', { browserstackLocal: true }
'browserstack',
{ browserstackLocal: true }
]
],
@@ -135,8 +136,8 @@ module.exports = {
require('./src/commands/upload')
// Force keep alive: https://www.browserstack.com/docs/automate/selenium/error-codes/keep-alive-not-used#Node_JS
const http = require('http')
const https = require('https')
const http = require('node:http')
const https = require('node:https')
const keepAliveTimeout = 30 * 1000
@@ -174,6 +175,5 @@ module.exports = {
onPrepare: onBrowserStackPrepare,
onComplete: onBrowserStackComplete
} as WebdriverIO.Config
}

View File

@@ -28,7 +28,7 @@ module.exports = {
'browserName': 'chrome',
'acceptInsecureCerts': true,
'goog:chromeOptions': {
args: [ '--disable-gpu', windowSizeArg ],
args: [ '--headless', '--disable-gpu', windowSizeArg ],
prefs
}
}

View File

@@ -102,13 +102,7 @@ export const config = {
bail: true
},
autoCompileOpts: {
autoCompile: true,
tsNodeOpts: {
project: require('path').join(__dirname, './tsconfig.json')
}
},
tsConfigPath: require('node:path').join(__dirname, './tsconfig.json'),
before: function () {
require('./src/commands/upload')

211
client/eslint.config.mjs Normal file
View File

@@ -0,0 +1,211 @@
import { defineConfig, globalIgnores } from 'eslint/config'
import love from 'eslint-config-love'
import stylistic from '@stylistic/eslint-plugin'
import angular from 'angular-eslint'
export default defineConfig([
globalIgnores([
'**/node_modules/',
'**/dist',
'**/build',
'.angular'
]),
{
extends: [
love,
angular.configs.tsRecommended
],
processor: angular.processInlineTemplates,
plugins: {
'@stylistic': stylistic
},
files: [
'src/**/*.ts',
'e2e/**/*.ts'
],
rules: {
'@angular-eslint/component-selector': [
'error',
{
'type': [ 'element', 'attribute' ],
'prefix': 'my',
'style': 'kebab-case'
}
],
'@angular-eslint/directive-selector': [
'error',
{
'type': [ 'element', 'attribute' ],
'prefix': 'my',
'style': 'camelCase'
}
],
'@angular-eslint/use-component-view-encapsulation': 'error',
'@typescript-eslint/prefer-readonly': 'off',
"n/no-callback-literal": "off",
'@stylistic/semi': [ 'error', 'never' ],
'eol-last': [ 'error', 'always' ],
'indent': 'off',
'no-lone-blocks': 'off',
'no-mixed-operators': 'off',
'max-len': [ 'error', {
code: 140
} ],
'array-bracket-spacing': [ 'error', 'always' ],
'quote-props': [ 'error', 'consistent-as-needed' ],
'padded-blocks': 'off',
'no-async-promise-executor': 'off',
'dot-notation': 'off',
'promise/param-names': 'off',
'import/first': 'off',
'operator-linebreak': [ 'error', 'after', {
overrides: {
'?': 'before',
':': 'before'
}
} ],
'@typescript-eslint/consistent-type-assertions': [ 'error', {
assertionStyle: 'as'
} ],
'@typescript-eslint/array-type': [ 'error', {
default: 'array'
} ],
'@typescript-eslint/restrict-template-expressions': [ 'off', {
allowNumber: 'true'
} ],
'@typescript-eslint/no-this-alias': [ 'error', {
allowDestructuring: true,
allowedNames: [ 'self' ]
} ],
'@typescript-eslint/return-await': 'off',
'@typescript-eslint/no-base-to-string': 'off',
'@typescript-eslint/quotes': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/promise-function-async': 'off',
'@typescript-eslint/no-dynamic-delete': 'off',
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'off',
'@typescript-eslint/strict-boolean-expressions': 'off',
'@typescript-eslint/consistent-type-definitions': 'off',
'@typescript-eslint/no-misused-promises': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/no-extraneous-class': 'off',
'@typescript-eslint/prefer-nullish-coalescing': 'off',
'@typescript-eslint/consistent-indexed-object-style': 'off',
'@typescript-eslint/restrict-plus-operands': 'off',
'@typescript-eslint/no-unnecessary-condition': 'off',
'@typescript-eslint/consistent-type-imports': 'off',
'no-implicit-globals': 'off',
'@typescript-eslint/no-confusing-void-expression': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'logical-assignment-operators': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-magic-numbers': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-type-assertion': 'off',
'@typescript-eslint/prefer-destructuring': 'off',
'promise/avoid-new': 'off',
'@typescript-eslint/class-methods-use-this': 'off',
'arrow-body-style': 'off',
'@typescript-eslint/use-unknown-in-catch-callback-variable': 'off',
'@typescript-eslint/consistent-type-exports': 'off',
'@typescript-eslint/init-declarations': 'off',
'no-console': 'off',
'@typescript-eslint/dot-notation': 'off',
'@typescript-eslint/method-signature-style': 'off',
'eslint-comments/require-description': 'off',
'max-lines': 'off',
'@typescript-eslint/no-misused-spread': 'off',
'consistent-this': 'off',
'@typescript-eslint/no-empty-function': 'off',
'prefer-regex-literals': 'off',
'@typescript-eslint/prefer-regexp-exec': 'off',
'@typescript-eslint/prefer-promise-reject-errors': 'off',
'@typescript-eslint/no-unnecessary-template-expression': 'off',
'@typescript-eslint/no-loop-func': 'off',
'@typescript-eslint/switch-exhaustiveness-check': 'off',
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-import-type-side-effects': 'off',
'@typescript-eslint/no-require-imports': 'off',
'no-useless-return': 'off',
'no-return-assign': 'off',
'@typescript-eslint/unbound-method': 'off',
'import/no-named-default': 'off',
'@typescript-eslint/prefer-reduce-type-parameter': 'off',
"@typescript-eslint/no-deprecated": [ 'error', {
allow: [
{ from: 'package', package: 'video.js', name: 'options'}
]
}],
// Can be interesting to enable
'@typescript-eslint/no-unsafe-return': 'off',
// Can be interesting to enable
'complexity': 'off',
// Interesting but has a bug with specific cases
'@typescript-eslint/no-unnecessary-type-parameters': 'off',
// TODO: enable
'@typescript-eslint/prefer-as-const': 'off',
// TODO: enable
'@typescript-eslint/max-params': 'off',
// TODO: enable
'@typescript-eslint/no-unsafe-function-type': 'off',
// TODO: enable
'@typescript-eslint/no-deprecated': 'off',
// TODO: enable
'@typescript-eslint/no-floating-promises': 'off',
// TODO: enable but it fails in our CI
'@typescript-eslint/no-redundant-type-constituents': 'off',
// We use many nested callbacks in our tests
'max-nested-callbacks': 'off',
'no-param-reassign': 'off',
'no-negated-condition': 'off',
'radix': 'off',
'no-plusplus': 'off',
'@typescript-eslint/no-unnecessary-type-conversion': 'off',
'no-promise-executor-return': 'off'
},
languageOptions: {
parserOptions: {
projectService: {
allowDefaultProject: [ 'src/standalone/build-tools/vite-utils.ts' ]
}
}
}
},
{
files: [ '**/*.html' ],
extends: [
angular.configs.templateRecommended,
angular.configs.templateAccessibility,
],
rules: {
// TODO: enable
'@angular-eslint/template/button-has-type': 'off'
}
}
])

View File

@@ -1,6 +1,6 @@
{
"name": "peertube-client",
"version": "7.1.0",
"version": "7.3.0",
"private": true,
"license": "AGPL-3.0",
"author": {
@@ -14,7 +14,7 @@
},
"scripts": {
"lint": "npm run lint-ts && npm run lint-scss",
"lint-ts": "eslint --cache --ext .ts src/standalone/**/*.ts && npm run ng lint",
"lint-ts": "eslint",
"lint-scss": "stylelint 'src/**/*.scss'",
"eslint": "eslint",
"ng": "ng",
@@ -34,96 +34,90 @@
],
"typings": "*.d.ts",
"devDependencies": {
"@angular-eslint/builder": "^19.0.2",
"@angular-eslint/eslint-plugin": "^19.0.2",
"@angular-eslint/eslint-plugin-template": "^19.0.2",
"@angular-eslint/schematics": "^19.0.2",
"@angular-eslint/template-parser": "^19.0.2",
"@angular/animations": "^19.1.4",
"@angular/build": "^19.1.5",
"@angular/cdk": "^19.1.2",
"@angular/cli": "^19.1.5",
"@angular/common": "^19.1.4",
"@angular/compiler": "^19.1.4",
"@angular/compiler-cli": "^19.1.4",
"@angular/core": "^19.1.4",
"@angular/forms": "^19.1.4",
"@angular/localize": "^19.1.4",
"@angular/platform-browser": "^19.1.4",
"@angular/platform-browser-dynamic": "^19.1.4",
"@angular/router": "^19.1.4",
"@angular/service-worker": "^19.1.4",
"@ng-bootstrap/ng-bootstrap": "^18.0.0",
"@angular/animations": "^20.3.11",
"@angular/build": "^20.3.10",
"@angular/cdk": "^20.2.13",
"@angular/cli": "^20.3.10",
"@angular/common": "^20.3.11",
"@angular/compiler": "^20.3.11",
"@angular/compiler-cli": "^20.3.11",
"@angular/core": "^20.3.11",
"@angular/forms": "^20.3.11",
"@angular/localize": "^20.3.11",
"@angular/platform-browser": "^20.3.11",
"@angular/platform-browser-dynamic": "^20.3.11",
"@angular/router": "^20.3.11",
"@angular/service-worker": "^20.3.11",
"@ng-bootstrap/ng-bootstrap": "^19.0.1",
"@ngx-loading-bar/core": "^7.0.0",
"@ngx-loading-bar/http-client": "^7.0.0",
"@ngx-loading-bar/router": "^7.0.0",
"@peertube/maildev": "^1.2.0",
"@peertube/xliffmerge": "^2.0.3",
"@peertube/player": "workspace:*",
"@peertube/xliffmerge": "^2.0.4",
"@plussub/srt-vtt-parser": "^2.0.5",
"@popperjs/core": "^2.11.5",
"@types/chart.js": "^2.9.37",
"@types/core-js": "^2.5.2",
"@types/debug": "^4.1.5",
"@types/jschannel": "^1.0.0",
"@types/linkifyjs": "^2.1.2",
"@types/lodash-es": "^4.17.0",
"@types/markdown-it": "^14.1.1",
"@types/node": "^18.13.0",
"@types/qrcode": "^1.5.5",
"@types/sanitize-html": "2.11.0",
"@types/sha.js": "^2.4.0",
"@types/video.js": "^7.3.40",
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.2",
"@wdio/browserstack-service": "^8.10.5",
"@wdio/cli": "^8.10.5",
"@wdio/local-runner": "^8.10.5",
"@wdio/mocha-framework": "^8.10.4",
"@wdio/shared-store-service": "^8.10.5",
"@wdio/spec-reporter": "^8.10.5",
"angularx-qrcode": "19.0.0",
"bootstrap": "^5.1.3",
"@popperjs/core": "^2.11.8",
"@primeng/themes": "^19.1.4",
"@stylistic/eslint-plugin": "^5.5.0",
"@types/core-js": "^2.5.8",
"@types/debug": "^4.1.12",
"@types/jschannel": "^1.0.6",
"@types/linkifyjs": "^2.1.7",
"@types/lodash-es": "^4.17.12",
"@types/markdown-it": "^14.1.2",
"@types/node": "^20.19.25",
"@types/qrcode": "^1.5.6",
"@types/sanitize-html": "2.16.0",
"@types/sha.js": "^2.4.4",
"@wdio/browserstack-service": "^9.20.0",
"@wdio/cli": "^9.20.0",
"@wdio/globals": "^9.17.0",
"@wdio/local-runner": "^9.20.0",
"@wdio/mocha-framework": "^9.20.0",
"@wdio/shared-store-service": "^9.20.0",
"@wdio/spec-reporter": "^9.20.0",
"angular-eslint": "^20.6.0",
"angularx-qrcode": "20.0.0",
"bootstrap": "^5.3.8",
"buffer": "^6.0.3",
"chart.js": "^4.3.0",
"chartjs-plugin-zoom": "~2.0.1",
"color-bits": "^1.0.4",
"core-js": "^3.22.8",
"debug": "^4.3.1",
"dompurify": "^3.1.6",
"eslint": "^8.28.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-jsdoc": "^48.1.0",
"eslint-plugin-prefer-arrow": "latest",
"expect-webdriverio": "^4.2.3",
"hls.js": "~1.5.11",
"intl-messageformat": "^10.1.0",
"chart.js": "^4.5.1",
"chartjs-plugin-zoom": "~2.2.0",
"color-bits": "^1.1.1",
"core-js": "^3.46.0",
"debug": "^4.4.3",
"dompurify": "^3.3.0",
"eslint": "^9.39.1",
"eslint-config-love": "^133.0.0",
"expect-webdriverio": "^5.4.3",
"hls.js": "~1.6.14",
"intl-messageformat": "^10.7.18",
"jschannel": "^1.0.2",
"linkify-html": "^4.0.2",
"linkifyjs": "^4.0.2",
"lodash-es": "^4.17.4",
"linkify-html": "^4.3.2",
"linkifyjs": "^4.3.2",
"lodash-es": "^4.17.21",
"markdown-it": "14.1.0",
"markdown-it-emoji": "^3.0.0",
"ngx-uploadx": "^7.0.0",
"p2p-media-loader-core": "^2.1.2",
"p2p-media-loader-hlsjs": "^2.1.2",
"primeng": "^17",
"rxjs": "^7.3.0",
"sass-embedded": "^1.83.4",
"sha.js": "^2.4.11",
"socket.io-client": "^4.5.4",
"stylelint": "^16.2.1",
"stylelint-config-sass-guidelines": "^11.0.0",
"stylelint-order": "^6.0.4",
"tinykeys": "^2.1.0",
"ngx-uploadx": "^7.0.1",
"p2p-media-loader-core": "^2.2.1",
"p2p-media-loader-hlsjs": "^2.2.1",
"primeng": "^19.1.4",
"rxjs": "^7.8.2",
"sass-embedded": "^1.93.3",
"sha.js": "^2.4.12",
"socket.io-client": "^4.8.1",
"stylelint": "^16.25.0",
"stylelint-config-sass-guidelines": "^12.1.0",
"stylelint-order": "^7.0.0",
"tinykeys": "^3.0.0",
"ts-node": "^10.9.2",
"tslib": "^2.4.0",
"type-fest": "^4.37.0",
"typescript": "~5.7.3",
"video.js": "^7.19.2",
"vite": "^6.0.11",
"vite-plugin-checker": "^0.8.0",
"vite-plugin-node-polyfills": "^0.23.0",
"zone.js": "~0.15.0"
},
"dependencies": {}
"tslib": "^2.8.1",
"type-fest": "^5.2.0",
"typescript": "~5.9.3",
"ua-parser-js": "^2.0.6",
"video.js": "^8.23.4",
"vite": "^7.2.2",
"vite-plugin-checker": "^0.11.0",
"vite-plugin-node-polyfills": "^0.24.0",
"zone.js": "~0.15.1"
}
}

View File

@@ -10,9 +10,11 @@
type="text" id="fromName" class="form-control"
formControlName="fromName" [ngClass]="{ 'input-error': formErrors.fromName }"
autocomplete="name"
>
>
<div *ngIf="formErrors.fromName" class="form-error" role="alert">{{ formErrors.fromName }}</div>
@if (formErrors.fromName) {
<div class="form-error" role="alert">{{ formErrors.fromName }}</div>
}
</div>
<div class="form-group">
@@ -21,9 +23,11 @@
type="text" id="fromEmail" class="form-control"
formControlName="fromEmail" [ngClass]="{ 'input-error': formErrors['fromEmail'] }"
i18n-placeholder placeholder="Example: john@example.com" autocomplete="email"
>
>
<div *ngIf="formErrors.fromEmail" class="form-error" role="alert">{{ formErrors.fromEmail }}</div>
@if (formErrors.fromEmail) {
<div class="form-error" role="alert">{{ formErrors.fromEmail }}</div>
}
</div>
<div class="form-group">
@@ -31,19 +35,25 @@
<input
type="text" id="subject" class="form-control"
formControlName="subject" [ngClass]="{ 'input-error': formErrors['subject'] }"
>
>
<div *ngIf="formErrors.subject" class="form-error" role="alert">{{ formErrors.subject }}</div>
@if (formErrors.subject) {
<div class="form-error" role="alert">{{ formErrors.subject }}</div>
}
</div>
<div class="form-group">
<label i18n for="body">Your message</label>
<textarea id="body" formControlName="body" class="form-control" [ngClass]="{ 'input-error': formErrors['body'] }"></textarea>
<div *ngIf="formErrors.body" class="form-error" role="alert">{{ formErrors.body }}</div>
@if (formErrors.body) {
<div class="form-error" role="alert">{{ formErrors.body }}</div>
}
</div>
<my-alert *ngIf="error" type="danger">{{ error }}</my-alert>
@if (error) {
<my-alert type="danger">{{ error }}</my-alert>
}
<input type="submit" i18n-value value="Submit" class="peertube-button primary-button" [disabled]="!form.valid" />
</form>

View File

@@ -1,4 +1,4 @@
import { NgClass, NgIf } from '@angular/common'
import { NgClass } from '@angular/common'
import { Component, OnInit, inject } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { ActivatedRoute } from '@angular/router'
@@ -23,7 +23,7 @@ type Prefill = {
@Component({
templateUrl: './about-contact.component.html',
styleUrls: [ './about-contact.component.scss' ],
imports: [ NgIf, FormsModule, ReactiveFormsModule, NgClass, AlertComponent ]
imports: [ FormsModule, ReactiveFormsModule, NgClass, AlertComponent ]
})
export class AboutContactComponent extends FormReactive implements OnInit {
protected formReactiveService = inject(FormReactiveService)

View File

@@ -14,39 +14,46 @@
</div>
<div class="follows">
<div i18n class="no-results" *ngIf="subscriptionsPagination.totalItems === 0">{{ instanceName }} does not have subscriptions.</div>
@if (subscriptionsPagination.totalItems === 0) {
<div i18n class="no-results">{{ instanceName }} does not have subscriptions.</div>
}
<div *ngFor="let subscription of subscriptions" class="follow-block">
<my-actor-avatar [actor]="subscription" actorType="instance" size="32"></my-actor-avatar>
<div>
<a class="follow-name" [href]="subscription.url" target="_blank" rel="noopener noreferrer">{{ subscription.name }}</a>
@for (subscription of subscriptions; track subscription) {
<div class="follow-block">
<my-actor-avatar [actor]="subscription" actorType="instance" size="32"></my-actor-avatar>
<div class="ellipsis">
<a class="follow-name" [href]="subscription.url" target="_blank" rel="noopener noreferrer">{{ subscription.name }}</a>
</div>
</div>
</div>
}
</div>
<div class="text-center">
<my-button *ngIf="canLoadMoreSubscriptions()" class="mt-3 mx-auto" (click)="loadMoreSubscriptions()" theme="secondary" i18n>Show more subscriptions</my-button>
@if (canLoadMoreSubscriptions()) {
<my-button class="mt-3 mx-auto" (click)="loadMoreSubscriptions()" theme="secondary" i18n>Show more subscriptions</my-button>
}
</div>
<div *ngIf="serverStats" class="stats mt-4">
<h4 i18n>Our network in figures</h4>
@if (serverStats) {
<div class="stats mt-4">
<h4 i18n>Our network in figures</h4>
<div myPluginSelector pluginSelectorId="about-instance-network-statistics">
<div class="stat">
<strong>{{ serverStats.totalVideos | number }}</strong>
<a routerLink="/videos/browse" [queryParams]="{ scope: 'federated' }" i18n>total videos</a>
<my-global-icon iconName="videos"></my-global-icon>
</div>
<div myPluginSelector pluginSelectorId="about-instance-network-statistics">
<div class="stat">
<strong>{{ serverStats.totalVideos | number }}</strong>
<a routerLink="/videos/browse" [queryParams]="{ scope: 'federated' }" i18n>total videos</a>
<my-global-icon iconName="videos"></my-global-icon>
</div>
<div class="stat">
<strong>{{ serverStats.totalVideoComments | number }}</strong>
<div i18n>total comments</div>
<my-global-icon iconName="message-circle"></my-global-icon>
<div class="stat">
<strong>{{ serverStats.totalVideoComments | number }}</strong>
<div i18n>total comments</div>
<my-global-icon iconName="message-circle"></my-global-icon>
</div>
</div>
</div>
</div>
}
</div>
<div class="followers">
@@ -63,18 +70,24 @@
</div>
<div class="follows">
<div i18n class="no-results" *ngIf="followersPagination.totalItems === 0">{{ instanceName }} does not have followers.</div>
@if (followersPagination.totalItems === 0) {
<div i18n class="no-results">{{ instanceName }} does not have followers.</div>
}
<div *ngFor="let follower of followers" class="follow-block">
<my-actor-avatar [actor]="follower" actorType="instance" size="32"></my-actor-avatar>
@for (follower of followers; track follower) {
<div class="follow-block">
<my-actor-avatar [actor]="follower" actorType="instance" size="32"></my-actor-avatar>
<div>
<a class="follow-name" [href]="follower.url" target="_blank" rel="noopener noreferrer">{{ follower.name }}</a>
<div class="ellipsis">
<a class="follow-name" [href]="follower.url" target="_blank" rel="noopener noreferrer">{{ follower.name }}</a>
</div>
</div>
</div>
}
<div class="text-center">
<my-button *ngIf="canLoadMoreFollowers()" class="mt-3 mx-auto" (click)="loadMoreFollowers()" theme="secondary" i18n>Show more followers</my-button>
@if (canLoadMoreFollowers()) {
<my-button class="mt-3 mx-auto" (click)="loadMoreFollowers()" theme="secondary" i18n>Show more followers</my-button>
}
</div>
</div>
</div>

View File

@@ -1,4 +1,4 @@
import { DecimalPipe, NgFor, NgIf } from '@angular/common'
import { DecimalPipe } from '@angular/common'
import { Component, OnInit, inject } from '@angular/core'
import { RouterLink } from '@angular/router'
import { ComponentPagination, hasMoreItems, Notifier, RestService, ServerService } from '@app/core'
@@ -17,8 +17,6 @@ import { SubscriptionImageComponent } from './subscription-image.component'
templateUrl: './about-follows.component.html',
styleUrls: [ './about-follows.component.scss' ],
imports: [
NgIf,
NgFor,
ActorAvatarComponent,
ButtonComponent,
PluginSelectorDirective,

View File

@@ -47,5 +47,7 @@
</defs>
</svg>
<img *ngIf="avatarUrl" [src]="avatarUrl" alt="">
@if (avatarUrl) {
<img [src]="avatarUrl" alt="">
}
</div>

View File

@@ -1,4 +1,3 @@
import { CommonModule } from '@angular/common'
import { Component, OnInit, inject } from '@angular/core'
import { ServerService } from '@app/core'
import { Actor } from '@app/shared/shared-main/account/actor.model'
@@ -8,9 +7,7 @@ import { Actor } from '@app/shared/shared-main/account/actor.model'
templateUrl: './follower-image.component.html',
styleUrls: [ './follower-image.component.scss' ],
standalone: true,
imports: [
CommonModule
]
imports: []
})
export class FollowerImageComponent implements OnInit {
private server = inject(ServerService)

View File

@@ -1,5 +1,7 @@
<div class="root" aria-hidden="true">
<img *ngIf="avatarUrl" [src]="avatarUrl" alt="">
@if (avatarUrl) {
<img [src]="avatarUrl" alt="">
}
<svg width="125" height="129" viewBox="0 0 125 129" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M43.4996 129L18.9946 27.2709L36.8651 13.7961L124.924 67.6037L43.4996 129Z"

View File

@@ -1,4 +1,3 @@
import { CommonModule } from '@angular/common'
import { Component, OnInit, inject } from '@angular/core'
import { ServerService } from '@app/core'
import { Actor } from '@app/shared/shared-main/account/actor.model'
@@ -8,7 +7,7 @@ import { Actor } from '@app/shared/shared-main/account/actor.model'
templateUrl: './subscription-image.component.html',
styleUrls: [ './subscription-image.component.scss' ],
standalone: true,
imports: [ CommonModule ]
imports: []
})
export class SubscriptionImageComponent implements OnInit {
private server = inject(ServerService)

View File

@@ -1,29 +1,47 @@
<div class="block specifics" *ngIf="categories.length !== 0 || languages.length !== 0 || config.instance.isNSFW">
<h4 i18n>Specifics</h4>
@if (categories.length !== 0 || languages.length !== 0 || config.instance.isNSFW) {
<div class="block specifics">
<h4 i18n>Specifics</h4>
<div *ngIf="languages.length !== 0" class="d-inline-block me-2">
<span class="text-content top-2px" i18n>Language: </span>
<span *ngFor="let language of languages" class="pt-badge badge-primary me-1">{{ language }}</span>
@if (languages.length !== 0) {
<div class="d-inline-block me-2">
<span class="text-content top-1px me-1" i18n>Language: </span>
@for (language of languages; track language) {
<span class="pt-badge badge-primary me-1">{{ language }}</span>
}
</div>
}
@if (categories.length !== 0) {
<div class="d-inline-block mt-2">
<span class="text-content top-1px me-1" i18n>Categories: </span>
@for (category of categories; track category) {
<span class="pt-badge badge-secondary me-1">{{ category }}</span>
}
</div>
}
@if (config.instance.isNSFW) {
<div i18n class="fw-bold text-content mt-3">{{ config.instance.name }} is dedicated to sensitive content.</div>
}
</div>
}
<div *ngIf="categories.length !== 0" class="d-inline-block mt-2">
<span class="text-content top-2px" i18n>Categories: </span>
<span *ngFor="let category of categories" class="pt-badge badge-secondary me-1">{{ category }}</span>
@if (descriptionElement) {
<div class="block description">
<h4 i18n>Description</h4>
<my-custom-markup-container class="text-content" [content]="descriptionElement"></my-custom-markup-container>
</div>
}
<div i18n *ngIf="config.instance.isNSFW" class="fw-bold text-content mt-3">{{ config.instance.name }} is dedicated to sensitive/NSFW content.</div>
</div>
@if (aboutHTML.terms) {
<div class="block terms">
<h4 i18n class="section-title">Terms</h4>
<div class="block description">
<h4 i18n>Description</h4>
<my-custom-markup-container class="text-content" [content]="descriptionElement"></my-custom-markup-container>
</div>
<div class="block terms">
<h4 i18n class="section-title">Terms</h4>
<div class="text-content" [innerHTML]="aboutHTML.terms"></div>
</div>
<div class="text-content" [innerHTML]="aboutHTML.terms"></div>
</div>
}
<my-support-modal #supportModal [name]="config.instance.name" [content]="config.instance.support.text"></my-support-modal>

View File

@@ -1,4 +1,3 @@
import { NgFor, NgIf } from '@angular/common'
import { Component, OnInit, inject, viewChild } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { ServerService } from '@app/core'
@@ -12,8 +11,6 @@ import { ResolverData } from '../about-instance.resolver'
templateUrl: './about-instance-home.component.html',
styleUrls: [ './about-instance-common.component.scss' ],
imports: [
NgIf,
NgFor,
CustomMarkupContainerComponent,
SupportModalComponent
]

View File

@@ -1,13 +1,17 @@
<div myPluginSelector pluginSelectorId="about-instance-moderation">
<div class="block moderation-information" *ngIf="aboutHTML.moderationInformation">
<h4 i18n class="section-title">Moderation information</h4>
<div [innerHTML]="aboutHTML.moderationInformation"></div>
</div>
@if (aboutHTML.moderationInformation) {
<div class="block moderation-information">
<h4 i18n class="section-title">Moderation information</h4>
<div [innerHTML]="aboutHTML.moderationInformation"></div>
</div>
}
<div class="block code-of-conduct" *ngIf="aboutHTML.codeOfConduct">
<h4 i18n class="section-title">Code of conduct</h4>
<div [innerHTML]="aboutHTML.codeOfConduct"></div>
</div>
@if (aboutHTML.codeOfConduct) {
<div class="block code-of-conduct">
<h4 i18n class="section-title">Code of conduct</h4>
<div [innerHTML]="aboutHTML.codeOfConduct"></div>
</div>
}
</div>

View File

@@ -1,15 +1,14 @@
import { CommonModule } from '@angular/common'
import { Component, OnInit, inject } from '@angular/core'
import { ActivatedRoute } from '@angular/router'
import { ServerService } from '@app/core'
import { AboutHTML } from '@app/shared/shared-main/instance/instance.service'
import { ResolverData } from '../about-instance.resolver'
import { PluginSelectorDirective } from '@app/shared/shared-main/plugins/plugin-selector.directive'
import { ResolverData } from '../about-instance.resolver'
@Component({
templateUrl: './about-instance-moderation.component.html',
styleUrls: [ './about-instance-common.component.scss' ],
imports: [ CommonModule, PluginSelectorDirective ]
imports: [ PluginSelectorDirective ]
})
export class AboutInstanceModerationComponent implements OnInit {
private route = inject(ActivatedRoute)

View File

@@ -1,19 +1,27 @@
<div class="block administrator" *ngIf="aboutHTML.administrator">
<h4 i18n>Who we are</h4>
<div class="text-content" [innerHTML]="aboutHTML.administrator"></div>
</div>
@if (aboutHTML.administrator) {
<div class="block administrator">
<h4 i18n>Who we are</h4>
<div class="text-content" [innerHTML]="aboutHTML.administrator"></div>
</div>
}
<div class="block creation-reason" *ngIf="aboutHTML.creationReason">
<h4 i18n>Why we created {{ instanceName }}</h4>
<div class="text-content" [innerHTML]="aboutHTML.creationReason"></div>
</div>
@if (aboutHTML.creationReason) {
<div class="block creation-reason">
<h4 i18n>Why we created {{ instanceName }}</h4>
<div class="text-content" [innerHTML]="aboutHTML.creationReason"></div>
</div>
}
<div class="block maintenance-lifetime" *ngIf="aboutHTML.maintenanceLifetime">
<h4 i18n>How long we plan to maintain {{ instanceName }}</h4>
<div [innerHTML]="aboutHTML.maintenanceLifetime"></div>
</div>
@if (aboutHTML.maintenanceLifetime) {
<div class="block maintenance-lifetime">
<h4 i18n>How long we plan to maintain {{ instanceName }}</h4>
<div [innerHTML]="aboutHTML.maintenanceLifetime"></div>
</div>
}
<div class="block business-model" *ngIf="aboutHTML.businessModel">
<h4 i18n>How we will pay for keeping {{ instanceName }} running</h4>
<div class="text-content" [innerHTML]="aboutHTML.businessModel"></div>
</div>
@if (aboutHTML.businessModel) {
<div class="block business-model">
<h4 i18n>How we will pay for keeping {{ instanceName }} running</h4>
<div class="text-content" [innerHTML]="aboutHTML.businessModel"></div>
</div>
}

View File

@@ -1,4 +1,3 @@
import { CommonModule } from '@angular/common'
import { Component, OnInit, inject } from '@angular/core'
import { ActivatedRoute } from '@angular/router'
import { ServerService } from '@app/core'
@@ -8,7 +7,7 @@ import { ResolverData } from '../about-instance.resolver'
@Component({
templateUrl: './about-instance-team.component.html',
styleUrls: [ './about-instance-common.component.scss' ],
imports: [ CommonModule ]
imports: []
})
export class AboutInstanceTeamComponent implements OnInit {
private route = inject(ActivatedRoute)

View File

@@ -1,7 +1,9 @@
<div *ngIf="aboutHTML.hardwareInformation" myPluginSelector pluginSelectorId="about-instance-other-information">
<h4 i18n class="section-title">Hardware information</h4>
<div [innerHTML]="aboutHTML.hardwareInformation"></div>
</div>
@if (aboutHTML.hardwareInformation) {
<div myPluginSelector pluginSelectorId="about-instance-other-information">
<h4 i18n class="section-title">Hardware information</h4>
<div [innerHTML]="aboutHTML.hardwareInformation"></div>
</div>
}
<div myPluginSelector pluginSelectorId="about-instance-features">
<h4 class="visually-hidden" i18n>FEATURES</h4>

View File

@@ -1,4 +1,3 @@
import { CommonModule } from '@angular/common'
import { Component, OnInit, inject } from '@angular/core'
import { ActivatedRoute } from '@angular/router'
import { ServerService } from '@app/core'
@@ -10,7 +9,7 @@ import { InstanceFeaturesTableComponent } from '@app/shared/shared-instance/inst
@Component({
templateUrl: './about-instance-tech.component.html',
styleUrls: [ './about-instance-common.component.scss' ],
imports: [ CommonModule, PluginSelectorDirective, InstanceFeaturesTableComponent ]
imports: [ PluginSelectorDirective, InstanceFeaturesTableComponent ]
})
export class AboutInstanceTechComponent implements OnInit {
private route = inject(ActivatedRoute)

Some files were not shown because too many files have changed in this diff Show More