aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-04-09 15:17:46 +0200
committerChocobozzz <me@florianbigard.com>2021-04-09 15:21:06 +0200
commitd2466f0ac9c9877df10f62b7ac20bc3253a2a84a (patch)
tree428fb76968ab854452458962f975066478ec8486
parent22820226e54dee61287666a178df2176fafb202a (diff)
downloadPeerTube-d2466f0ac9c9877df10f62b7ac20bc3253a2a84a.tar.gz
PeerTube-d2466f0ac9c9877df10f62b7ac20bc3253a2a84a.tar.zst
PeerTube-d2466f0ac9c9877df10f62b7ac20bc3253a2a84a.zip
Update plugins doc
-rw-r--r--shared/models/plugins/register-server-setting.model.ts2
-rw-r--r--support/doc/plugins/guide.md314
2 files changed, 196 insertions, 120 deletions
diff --git a/shared/models/plugins/register-server-setting.model.ts b/shared/models/plugins/register-server-setting.model.ts
index 6bc25b4ae..9f45c3c37 100644
--- a/shared/models/plugins/register-server-setting.model.ts
+++ b/shared/models/plugins/register-server-setting.model.ts
@@ -1,6 +1,6 @@
1import { RegisterClientFormFieldOptions } from './register-client-form-field.model' 1import { RegisterClientFormFieldOptions } from './register-client-form-field.model'
2 2
3export type RegisterServerSettingOptions = RegisterClientFormFieldOptions & { 3export type RegisterServerSettingOptions = RegisterClientFormFieldOptions & {
4 // If the setting is not private, anyone can view its value (client code included) 4 // If the setting is not private, anyone can view its value (client code included)
5 // If the setting is private, only server-side hooks can access it 5 // If the setting is private, only server-side hooks can access it
6 // Mainly used by the PeerTube client to get admin config 6 // Mainly used by the PeerTube client to get admin config
diff --git a/support/doc/plugins/guide.md b/support/doc/plugins/guide.md
index 20cbec5c7..f5e753b79 100644
--- a/support/doc/plugins/guide.md
+++ b/support/doc/plugins/guide.md
@@ -8,14 +8,15 @@
8 - [Hooks](#hooks) 8 - [Hooks](#hooks)
9 - [Static files](#static-files) 9 - [Static files](#static-files)
10 - [CSS](#css) 10 - [CSS](#css)
11 - [Server helpers (only for plugins)](#server-helpers-only-for-plugins) 11 - [Server API (only for plugins)](#server-api-only-for-plugins)
12 - [Settings](#settings) 12 - [Settings](#settings)
13 - [Storage](#storage) 13 - [Storage](#storage)
14 - [Update video constants](#update-video-constants) 14 - [Update video constants](#update-video-constants)
15 - [Add custom routes](#add-custom-routes) 15 - [Add custom routes](#add-custom-routes)
16 - [Add external auth methods](#add-external-auth-methods) 16 - [Add external auth methods](#add-external-auth-methods)
17 - [Add new transcoding profiles](#add-new-transcoding-profiles) 17 - [Add new transcoding profiles](#add-new-transcoding-profiles)
18 - [Client helpers (themes & plugins)](#client-helpers-themes--plugins) 18 - [Helpers](#helpers)
19 - [Client API (themes & plugins)](#client-api-themes--plugins)
19 - [Plugin static route](#plugin-static-route) 20 - [Plugin static route](#plugin-static-route)
20 - [Notifier](#notifier) 21 - [Notifier](#notifier)
21 - [Markdown Renderer](#markdown-renderer) 22 - [Markdown Renderer](#markdown-renderer)
@@ -24,6 +25,7 @@
24 - [Get public settings](#get-public-settings) 25 - [Get public settings](#get-public-settings)
25 - [Get server config](#get-server-config) 26 - [Get server config](#get-server-config)
26 - [Add custom fields to video form](#add-custom-fields-to-video-form) 27 - [Add custom fields to video form](#add-custom-fields-to-video-form)
28 - [Register settings script](#register-settings-script)
27 - [Publishing](#publishing) 29 - [Publishing](#publishing)
28- [Write a plugin/theme](#write-a-plugintheme) 30- [Write a plugin/theme](#write-a-plugintheme)
29 - [Clone the quickstart repository](#clone-the-quickstart-repository) 31 - [Clone the quickstart repository](#clone-the-quickstart-repository)
@@ -154,31 +156,35 @@ body#custom-css {
154} 156}
155``` 157```
156 158
157### Server helpers (only for plugins) 159### Server API (only for plugins)
158 160
159#### Settings 161#### Settings
160 162
161Plugins can register settings, that PeerTube will inject in the administration interface. 163Plugins can register settings, that PeerTube will inject in the administration interface.
164The following fields will be automatically translated using the plugin translation files: `label`, `html`, `descriptionHTML`, `options.label`.
165**These fields are injected in the plugin settings page as HTML, so pay attention to your translation files.**
162 166
163Example: 167Example:
164 168
165```js 169```js
166registerSetting({ 170function register (...) {
167 name: 'admin-name', 171 registerSetting({
168 label: 'Admin name', 172 name: 'admin-name',
169 type: 'input', 173 label: 'Admin name',
170 // type: input | input-checkbox | input-password | input-textarea | markdown-text | markdown-enhanced 174 type: 'input',
171 default: 'my super name' 175 // type: input | input-checkbox | input-password | input-textarea | markdown-text | markdown-enhanced | 'select' | 'html'
172}) 176 default: 'my super name'
177 })
173 178
174const adminName = await settingsManager.getSetting('admin-name') 179 const adminName = await settingsManager.getSetting('admin-name')
175 180
176const result = await settingsManager.getSettings([ 'admin-name', 'admin-password' ]) 181 const result = await settingsManager.getSettings([ 'admin-name', 'admin-password' ])
177result['admin-name] 182 result['admin-name]
178 183
179settingsManager.onSettingsChange(settings => { 184 settingsManager.onSettingsChange(settings => {
180 settings['admin-name]) 185 settings['admin-name])
181}) 186 })
187}
182``` 188```
183 189
184#### Storage 190#### Storage
@@ -188,8 +194,10 @@ Plugins can store/load JSON data, that PeerTube will store in its database (so d
188Example: 194Example:
189 195
190```js 196```js
191const value = await storageManager.getData('mykey') 197function register (...) {
192await storageManager.storeData('mykey', { subkey: 'value' }) 198 const value = await storageManager.getData('mykey')
199 await storageManager.storeData('mykey', { subkey: 'value' })
200}
193``` 201```
194 202
195#### Update video constants 203#### Update video constants
@@ -197,17 +205,19 @@ await storageManager.storeData('mykey', { subkey: 'value' })
197You can add/delete video categories, licences or languages using the appropriate managers: 205You can add/delete video categories, licences or languages using the appropriate managers:
198 206
199```js 207```js
200videoLanguageManager.addLanguage('al_bhed', 'Al Bhed') 208function register (...) {
201videoLanguageManager.deleteLanguage('fr') 209 videoLanguageManager.addLanguage('al_bhed', 'Al Bhed')
210 videoLanguageManager.deleteLanguage('fr')
202 211
203videoCategoryManager.addCategory(42, 'Best category') 212 videoCategoryManager.addCategory(42, 'Best category')
204videoCategoryManager.deleteCategory(1) // Music 213 videoCategoryManager.deleteCategory(1) // Music
205 214
206videoLicenceManager.addLicence(42, 'Best licence') 215 videoLicenceManager.addLicence(42, 'Best licence')
207videoLicenceManager.deleteLicence(7) // Public domain 216 videoLicenceManager.deleteLicence(7) // Public domain
208 217
209videoPrivacyManager.deletePrivacy(2) // Remove Unlisted video privacy 218 videoPrivacyManager.deletePrivacy(2) // Remove Unlisted video privacy
210playlistPrivacyManager.deletePlaylistPrivacy(3) // Remove Private video playlist privacy 219 playlistPrivacyManager.deletePlaylistPrivacy(3) // Remove Private video playlist privacy
220}
211``` 221```
212 222
213#### Add custom routes 223#### Add custom routes
@@ -215,8 +225,10 @@ playlistPrivacyManager.deletePlaylistPrivacy(3) // Remove Private video playlist
215You can create custom routes using an [express Router](https://expressjs.com/en/4x/api.html#router) for your plugin: 225You can create custom routes using an [express Router](https://expressjs.com/en/4x/api.html#router) for your plugin:
216 226
217```js 227```js
218const router = getRouter() 228function register (...) {
219router.get('/ping', (req, res) => res.json({ message: 'pong' })) 229 const router = getRouter()
230 router.get('/ping', (req, res) => res.json({ message: 'pong' }))
231}
220``` 232```
221 233
222The `ping` route can be accessed using: 234The `ping` route can be accessed using:
@@ -229,80 +241,86 @@ The `ping` route can be accessed using:
229If you want to add a classic username/email and password auth method (like [LDAP](https://framagit.org/framasoft/peertube/official-plugins/-/tree/master/peertube-plugin-auth-ldap) for example): 241If you want to add a classic username/email and password auth method (like [LDAP](https://framagit.org/framasoft/peertube/official-plugins/-/tree/master/peertube-plugin-auth-ldap) for example):
230 242
231```js 243```js
232registerIdAndPassAuth({ 244function register (...) {
233 authName: 'my-auth-method',
234 245
235 // PeerTube will try all id and pass plugins in the weight DESC order 246 registerIdAndPassAuth({
236 // Exposing this value in the plugin settings could be interesting 247 authName: 'my-auth-method',
237 getWeight: () => 60,
238 248
239 // Optional function called by PeerTube when the user clicked on the logout button 249 // PeerTube will try all id and pass plugins in the weight DESC order
240 onLogout: user => { 250 // Exposing this value in the plugin settings could be interesting
241 console.log('User %s logged out.', user.username') 251 getWeight: () => 60,
242 },
243 252
244 // Optional function called by PeerTube when the access token or refresh token are generated/refreshed 253 // Optional function called by PeerTube when the user clicked on the logout button
245 hookTokenValidity: ({ token, type }) => { 254 onLogout: user => {
246 if (type === 'access') return { valid: true } 255 console.log('User %s logged out.', user.username')
247 if (type === 'refresh') return { valid: false } 256 },
248 },
249 257
250 // Used by PeerTube when the user tries to authenticate 258 // Optional function called by PeerTube when the access token or refresh token are generated/refreshed
251 login: ({ id, password }) => { 259 hookTokenValidity: ({ token, type }) => {
252 if (id === 'user' && password === 'super password') { 260 if (type === 'access') return { valid: true }
253 return { 261 if (type === 'refresh') return { valid: false }
254 username: 'user' 262 },
255 email: 'user@example.com' 263
256 role: 2 264 // Used by PeerTube when the user tries to authenticate
257 displayName: 'User display name' 265 login: ({ id, password }) => {
266 if (id === 'user' && password === 'super password') {
267 return {
268 username: 'user'
269 email: 'user@example.com'
270 role: 2
271 displayName: 'User display name'
272 }
258 } 273 }
259 }
260 274
261 // Auth failed 275 // Auth failed
262 return null 276 return null
263 } 277 }
264}) 278 })
265 279
266// Unregister this auth method 280 // Unregister this auth method
267unregisterIdAndPassAuth('my-auth-method') 281 unregisterIdAndPassAuth('my-auth-method')
282}
268``` 283```
269 284
270You can also add an external auth method (like [OpenID](https://framagit.org/framasoft/peertube/official-plugins/-/tree/master/peertube-plugin-auth-openid-connect), [SAML2](https://framagit.org/framasoft/peertube/official-plugins/-/tree/master/peertube-plugin-auth-saml2) etc): 285You can also add an external auth method (like [OpenID](https://framagit.org/framasoft/peertube/official-plugins/-/tree/master/peertube-plugin-auth-openid-connect), [SAML2](https://framagit.org/framasoft/peertube/official-plugins/-/tree/master/peertube-plugin-auth-saml2) etc):
271 286
272```js 287```js
273// result contains the userAuthenticated auth method you can call to authenticate a user 288function register (...) {
274const result = registerExternalAuth({
275 authName: 'my-auth-method',
276 289
277 // Will be displayed in a button next to the login form 290 // result contains the userAuthenticated auth method you can call to authenticate a user
278 authDisplayName: () => 'Auth method' 291 const result = registerExternalAuth({
292 authName: 'my-auth-method',
279 293
280 // If the user click on the auth button, PeerTube will forward the request in this function 294 // Will be displayed in a button next to the login form
281 onAuthRequest: (req, res) => { 295 authDisplayName: () => 'Auth method'
282 res.redirect('https://external-auth.example.com/auth')
283 },
284 296
285 // Same than registerIdAndPassAuth option 297 // If the user click on the auth button, PeerTube will forward the request in this function
286 // onLogout: ... 298 onAuthRequest: (req, res) => {
299 res.redirect('https://external-auth.example.com/auth')
300 },
287 301
288 // Same than registerIdAndPassAuth option 302 // Same than registerIdAndPassAuth option
289 // hookTokenValidity: ... 303 // onLogout: ...
290})
291 304
292router.use('/external-auth-callback', (req, res) => { 305 // Same than registerIdAndPassAuth option
293 // Forward the request to PeerTube 306 // hookTokenValidity: ...
294 result.userAuthenticated({ 307 })
295 req, 308
296 res, 309 router.use('/external-auth-callback', (req, res) => {
297 username: 'user' 310 // Forward the request to PeerTube
298 email: 'user@example.com' 311 result.userAuthenticated({
299 role: 2 312 req,
300 displayName: 'User display name' 313 res,
314 username: 'user'
315 email: 'user@example.com'
316 role: 2
317 displayName: 'User display name'
318 })
301 }) 319 })
302})
303 320
304// Unregister this external auth method 321 // Unregister this external auth method
305unregisterExternalAuth('my-auth-method) 322 unregisterExternalAuth('my-auth-method)
323}
306``` 324```
307 325
308#### Add new transcoding profiles 326#### Add new transcoding profiles
@@ -393,15 +411,41 @@ async function register ({
393 } 411 }
394``` 412```
395 413
396### Client helpers (themes & plugins) 414### Helpers
415
416PeerTube provides your plugin some helpers. For example:
417
418```js
419async function register ({
420 peertubeHelpers
421}) {
422 // Block a server
423 {
424 const serverActor = await peertubeHelpers.server.getServerActor()
425
426 await peertubeHelpers.moderation.blockServer({ byAccountId: serverActor.Account.id, hostToBlock: '...' })
427 }
428
429 // Load a video
430 {
431 const video = await peertubeHelpers.videos.loadByUrl('...')
432 }
433}
434```
435
436See the [plugin API reference](https://docs.joinpeertube.org/api-plugins) to see the complete helpers list.
437
438### Client API (themes & plugins)
397 439
398#### Plugin static route 440#### Plugin static route
399 441
400To get your plugin static route: 442To get your plugin static route:
401 443
402```js 444```js
403const baseStaticUrl = peertubeHelpers.getBaseStaticRoute() 445function register (...) {
404const imageUrl = baseStaticUrl + '/images/chocobo.png' 446 const baseStaticUrl = peertubeHelpers.getBaseStaticRoute()
447 const imageUrl = baseStaticUrl + '/images/chocobo.png'
448}
405``` 449```
406 450
407#### Notifier 451#### Notifier
@@ -409,9 +453,11 @@ const imageUrl = baseStaticUrl + '/images/chocobo.png'
409To notify the user with the PeerTube ToastModule: 453To notify the user with the PeerTube ToastModule:
410 454
411```js 455```js
412const { notifier } = peertubeHelpers 456function register (...) {
413notifier.success('Success message content.') 457 const { notifier } = peertubeHelpers
414notifier.error('Error message content.') 458 notifier.success('Success message content.')
459 notifier.error('Error message content.')
460}
415``` 461```
416 462
417#### Markdown Renderer 463#### Markdown Renderer
@@ -419,13 +465,15 @@ notifier.error('Error message content.')
419To render a formatted markdown text to HTML: 465To render a formatted markdown text to HTML:
420 466
421```js 467```js
422const { markdownRenderer } = peertubeHelpers 468function register (...) {
469 const { markdownRenderer } = peertubeHelpers
423 470
424await markdownRenderer.textMarkdownToHTML('**My Bold Text**') 471 await markdownRenderer.textMarkdownToHTML('**My Bold Text**')
425// return <strong>My Bold Text</strong> 472 // return <strong>My Bold Text</strong>
426 473
427await markdownRenderer.enhancedMarkdownToHTML('![alt-img](http://.../my-image.jpg)') 474 await markdownRenderer.enhancedMarkdownToHTML('![alt-img](http://.../my-image.jpg)')
428// return <img alt=alt-img src=http://.../my-image.jpg /> 475 // return <img alt=alt-img src=http://.../my-image.jpg />
476}
429``` 477```
430 478
431#### Custom Modal 479#### Custom Modal
@@ -433,17 +481,19 @@ await markdownRenderer.enhancedMarkdownToHTML('![alt-img](http://.../my-image.jp
433To show a custom modal: 481To show a custom modal:
434 482
435```js 483```js
436 peertubeHelpers.showModal({ 484function register (...) {
437 title: 'My custom modal title', 485 peertubeHelpers.showModal({
438 content: '<p>My custom modal content</p>', 486 title: 'My custom modal title',
439 // Optionals parameters : 487 content: '<p>My custom modal content</p>',
440 // show close icon 488 // Optionals parameters :
441 close: true, 489 // show close icon
442 // show cancel button and call action() after hiding modal 490 close: true,
443 cancel: { value: 'cancel', action: () => {} }, 491 // show cancel button and call action() after hiding modal
444 // show confirm button and call action() after hiding modal 492 cancel: { value: 'cancel', action: () => {} },
445 confirm: { value: 'confirm', action: () => {} }, 493 // show confirm button and call action() after hiding modal
446 }) 494 confirm: { value: 'confirm', action: () => {} },
495 })
496}
447``` 497```
448 498
449#### Translate 499#### Translate
@@ -451,8 +501,10 @@ To show a custom modal:
451You can translate some strings of your plugin (PeerTube will use your `translations` object of your `package.json` file): 501You can translate some strings of your plugin (PeerTube will use your `translations` object of your `package.json` file):
452 502
453```js 503```js
454peertubeHelpers.translate('User name') 504function register (...) {
455 .then(translation => console.log('Translated User name by ' + translation)) 505 peertubeHelpers.translate('User name')
506 .then(translation => console.log('Translated User name by ' + translation))
507}
456``` 508```
457 509
458#### Get public settings 510#### Get public settings
@@ -460,24 +512,28 @@ peertubeHelpers.translate('User name')
460To get your public plugin settings: 512To get your public plugin settings:
461 513
462```js 514```js
463peertubeHelpers.getSettings() 515function register (...) {
464 .then(s => { 516 peertubeHelpers.getSettings()
465 if (!s || !s['site-id'] || !s['url']) { 517 .then(s => {
466 console.error('Matomo settings are not set.') 518 if (!s || !s['site-id'] || !s['url']) {
467 return 519 console.error('Matomo settings are not set.')
468 } 520 return
521 }
469 522
470 // ... 523 // ...
471 }) 524 })
525}
472``` 526```
473 527
474#### Get server config 528#### Get server config
475 529
476```js 530```js
477peertubeHelpers.getServerConfig() 531function register (...) {
478 .then(config => { 532 peertubeHelpers.getServerConfig()
479 console.log('Fetched server config.', config) 533 .then(config => {
480 }) 534 console.log('Fetched server config.', config)
535 })
536}
481``` 537```
482 538
483#### Add custom fields to video form 539#### Add custom fields to video form
@@ -540,6 +596,26 @@ async function register ({
540 }) 596 })
541} 597}
542``` 598```
599
600#### Register settings script
601
602To hide some fields in your settings plugin page depending on the form state:
603
604```js
605async function register ({ registerSettingsScript }) {
606 registerSettingsScript({
607 isSettingHidden: options => {
608 if (options.setting.name === 'my-setting' && options.formValues['field45'] === '2') {
609 return true
610 }
611
612 return false
613 }
614 })
615}
616```
617
618
543### Publishing 619### Publishing
544 620
545PeerTube plugins and themes should be published on [NPM](https://www.npmjs.com/) so that PeerTube indexes 621PeerTube plugins and themes should be published on [NPM](https://www.npmjs.com/) so that PeerTube indexes