]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - support/doc/plugins/guide.md
1aae65a1c11961a9d76fa8c8d1c8c35e5d7f69ed
[github/Chocobozzz/PeerTube.git] / support / doc / plugins / guide.md
1 # Plugins & Themes
2
3 <!-- START doctoc generated TOC please keep comment here to allow auto update -->
4 <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
5
6
7 - [Concepts](#concepts)
8 - [Hooks](#hooks)
9 - [Static files](#static-files)
10 - [CSS](#css)
11 - [Server helpers (only for plugins)](#server-helpers-only-for-plugins)
12 - [Settings](#settings)
13 - [Storage](#storage)
14 - [Update video constants](#update-video-constants)
15 - [Client helpers (themes & plugins)](#client-helpers-themes--plugins)
16 - [Plugin static route](#plugin-static-route)
17 - [Translate](#translate)
18 - [Get public settings](#get-public-settings)
19 - [Publishing](#publishing)
20 - [Write a plugin/theme](#write-a-plugintheme)
21 - [Clone the quickstart repository](#clone-the-quickstart-repository)
22 - [Configure your repository](#configure-your-repository)
23 - [Update README](#update-readme)
24 - [Update package.json](#update-packagejson)
25 - [Write code](#write-code)
26 - [Add translations](#add-translations)
27 - [Test your plugin/theme](#test-your-plugintheme)
28 - [Publish](#publish)
29 - [Plugin & Theme hooks/helpers API](#plugin--theme-hookshelpers-api)
30 - [Tips](#tips)
31 - [Compatibility with PeerTube](#compatibility-with-peertube)
32 - [Spam/moderation plugin](#spammoderation-plugin)
33
34 <!-- END doctoc generated TOC please keep comment here to allow auto update -->
35
36 ## Concepts
37
38 Themes are exactly the same than plugins, except that:
39 * Their name starts with `peertube-theme-` instead of `peertube-plugin-`
40 * They cannot declare server code (so they cannot register server hooks or settings)
41 * CSS files are loaded by client only if the theme is chosen by the administrator or the user
42
43 ### Hooks
44
45 A plugin registers functions in JavaScript to execute when PeerTube (server and client) fires events. There are 3 types of hooks:
46 * `filter`: used to filter functions parameters or return values.
47 For example to replace words in video comments, or change the videos list behaviour
48 * `action`: used to do something after a certain trigger. For example to send a hook every time a video is published
49 * `static`: same than `action` but PeerTube waits their execution
50
51 On server side, these hooks are registered by the `library` file defined in `package.json`.
52
53 ```json
54 {
55 ...,
56 "library": "./main.js",
57 ...,
58 }
59 ```
60
61 And `main.js` defines a `register` function:
62
63 Example:
64
65 ```js
66 async function register ({
67 registerHook,
68 registerSetting,
69 settingsManager,
70 storageManager,
71 videoCategoryManager,
72 videoLicenceManager,
73 videoLanguageManager
74 }) {
75 registerHook({
76 target: 'action:application.listening',
77 handler: () => displayHelloWorld()
78 })
79 }
80 ```
81
82
83 On client side, these hooks are registered by the `clientScripts` files defined in `package.json`.
84 All client scripts have scopes so PeerTube client only loads scripts it needs:
85
86 ```json
87 {
88 ...,
89 "clientScripts": [
90 {
91 "script": "client/common-client-plugin.js",
92 "scopes": [ "common" ]
93 },
94 {
95 "script": "client/video-watch-client-plugin.js",
96 "scopes": [ "video-watch" ]
97 }
98 ],
99 ...
100 }
101 ```
102
103 And these scripts also define a `register` function:
104
105 ```js
106 function register ({ registerHook, peertubeHelpers }) {
107 registerHook({
108 target: 'action:application.init',
109 handler: () => onApplicationInit(peertubeHelpers)
110 })
111 }
112 ```
113
114 ### Static files
115
116 Plugins can declare static directories that PeerTube will serve (images for example)
117 from `/plugins/{plugin-name}/{plugin-version}/static/`
118 or `/themes/{theme-name}/{theme-version}/static/` routes.
119
120 ### CSS
121
122 Plugins can declare CSS files that PeerTube will automatically inject in the client.
123 If you need to override existing style, you can use the `#custom-css` selector:
124
125 ```
126 body#custom-css {
127 color: red;
128 }
129
130 #custom-css .header {
131 background-color: red;
132 }
133 ```
134
135 ### Server helpers (only for plugins)
136
137 #### Settings
138
139 Plugins can register settings, that PeerTube will inject in the administration interface.
140
141 Example:
142
143 ```js
144 registerSetting({
145 name: 'admin-name',
146 label: 'Admin name',
147 type: 'input',
148 default: 'my super name'
149 })
150
151 const adminName = await settingsManager.getSetting('admin-name')
152 ```
153
154 #### Storage
155
156 Plugins can store/load JSON data, that PeerTube will store in its database (so don't put files in there).
157
158 Example:
159
160 ```js
161 const value = await storageManager.getData('mykey')
162 await storageManager.storeData('mykey', { subkey: 'value' })
163 ```
164
165 #### Update video constants
166
167 You can add/delete video categories, licences or languages using the appropriate managers:
168
169 ```js
170 videoLanguageManager.addLanguage('al_bhed', 'Al Bhed')
171 videoLanguageManager.deleteLanguage('fr')
172
173 videoCategoryManager.addCategory(42, 'Best category')
174 videoCategoryManager.deleteCategory(1) // Music
175
176 videoLicenceManager.addLicence(42, 'Best licence')
177 videoLicenceManager.deleteLicence(7) // Public domain
178 ```
179
180 ### Client helpers (themes & plugins)
181
182 ### Plugin static route
183
184 To get your plugin static route:
185
186 ```js
187 const baseStaticUrl = peertubeHelpers.getBaseStaticRoute()
188 const imageUrl = baseStaticUrl + '/images/chocobo.png'
189 ```
190
191 #### Translate
192
193 You can translate some strings of your plugin (PeerTube will use your `translations` object of your `package.json` file):
194
195 ```js
196 peertubeHelpers.translate('User name')
197 .then(translation => console.log('Translated User name by ' + translation))
198 ```
199
200 #### Get public settings
201
202 To get your public plugin settings:
203
204 ```js
205 peertubeHelpers.getSettings()
206 .then(s => {
207 if (!s || !s['site-id'] || !s['url']) {
208 console.error('Matomo settings are not set.')
209 return
210 }
211
212 // ...
213 })
214 ```
215
216
217 ### Publishing
218
219 PeerTube plugins and themes should be published on [NPM](https://www.npmjs.com/) so that PeerTube indexes
220 take into account your plugin (after ~ 1 day). An official PeerTube index is available on https://packages.joinpeertube.org/ (it's just a REST API, so don't expect a beautiful website).
221
222 ## Write a plugin/theme
223
224 Steps:
225 * Find a name for your plugin or your theme (must not have spaces, it can only contain lowercase letters and `-`)
226 * Add the appropriate prefix:
227 * If you develop a plugin, add `peertube-plugin-` prefix to your plugin name (for example: `peertube-plugin-mysupername`)
228 * If you develop a theme, add `peertube-theme-` prefix to your theme name (for example: `peertube-theme-mysupertheme`)
229 * Clone the quickstart repository
230 * Configure your repository
231 * Update `README.md`
232 * Update `package.json`
233 * Register hooks, add CSS and static files
234 * Test your plugin/theme with a local PeerTube installation
235 * Publish your plugin/theme on NPM
236
237 ### Clone the quickstart repository
238
239 If you develop a plugin, clone the `peertube-plugin-quickstart` repository:
240
241 ```
242 $ git clone https://framagit.org/framasoft/peertube/peertube-plugin-quickstart.git peertube-plugin-mysupername
243 ```
244
245 If you develop a theme, clone the `peertube-theme-quickstart` repository:
246
247 ```
248 $ git clone https://framagit.org/framasoft/peertube/peertube-theme-quickstart.git peertube-theme-mysupername
249 ```
250
251 ### Configure your repository
252
253 Set your repository URL:
254
255 ```
256 $ cd peertube-plugin-mysupername # or cd peertube-theme-mysupername
257 $ git remote set-url origin https://your-git-repo
258 ```
259
260 ### Update README
261
262 Update `README.md` file:
263
264 ```
265 $ $EDITOR README.md
266 ```
267
268 ### Update package.json
269
270 Update the `package.json` fields:
271 * `name` (should start with `peertube-plugin-` or `peertube-theme-`)
272 * `description`
273 * `homepage`
274 * `author`
275 * `bugs`
276 * `engine.peertube` (the PeerTube version compatibility, must be `>=x.y.z` and nothing else)
277
278 **Caution:** Don't update or remove other keys, or PeerTube will not be able to index/install your plugin.
279 If you don't need static directories, use an empty `object`:
280
281 ```json
282 {
283 ...,
284 "staticDirs": {},
285 ...
286 }
287 ```
288
289 And if you don't need CSS or client script files, use an empty `array`:
290
291 ```json
292 {
293 ...,
294 "css": [],
295 "clientScripts": [],
296 ...
297 }
298 ```
299
300 ### Write code
301
302 Now you can register hooks or settings, write CSS and add static directories to your plugin or your theme :)
303
304 **Caution:** It's up to you to check the code you write will be compatible with the PeerTube NodeJS version,
305 and will be supported by web browsers.
306 If you want to write modern JavaScript, please use a transpiler like [Babel](https://babeljs.io/).
307
308 ### Add translations
309
310 If you want to translate strings of your plugin (like labels of your registered settings), create a file and add it to `package.json`:
311
312 ```json
313 {
314 ...,
315 "translations": {
316 "fr-FR": "./languages/fr.json",
317 "pt-BR": "./languages/pt-BR.json"
318 },
319 ...
320 }
321 ```
322
323 The key should be one of the locales defined in [i18n.ts](https://github.com/Chocobozzz/PeerTube/blob/develop/shared/models/i18n/i18n.ts).
324 You **must** use the complete locales (`fr-FR` instead of `fr`).
325
326 ### Test your plugin/theme
327
328 You'll need to have a local PeerTube instance:
329 * Follow the [dev prerequisites](https://github.com/Chocobozzz/PeerTube/blob/develop/.github/CONTRIBUTING.md#prerequisites)
330 (to clone the repository, install dependencies and prepare the database)
331 * Build PeerTube (`--light` to only build the english language):
332
333 ```
334 $ npm run build -- --light
335 ```
336
337 * Build the CLI:
338
339 ```
340 $ npm run setup:cli
341 ```
342
343 * Run PeerTube (you can access to your instance on http://localhost:9000):
344
345 ```
346 $ NODE_ENV=test npm start
347 ```
348
349 * Register the instance via the CLI:
350
351 ```
352 $ node ./dist/server/tools/peertube.js auth add -u 'http://localhost:9000' -U 'root' --password 'test'
353 ```
354
355 Then, you can install or reinstall your local plugin/theme by running:
356
357 ```
358 $ node ./dist/server/tools/peertube.js plugins install --path /your/absolute/plugin-or-theme/path
359 ```
360
361 ### Publish
362
363 Go in your plugin/theme directory, and run:
364
365 ```
366 $ npm publish
367 ```
368
369 Every time you want to publish another version of your plugin/theme, just update the `version` key from the `package.json`
370 and republish it on NPM. Remember that the PeerTube index will take into account your new plugin/theme version after ~24 hours.
371
372
373 ## Plugin & Theme hooks/helpers API
374
375 See the dedicated documentation: https://docs.joinpeertube.org/#/api-plugins
376
377
378 ## Tips
379
380 ### Compatibility with PeerTube
381
382 Unfortunately, we don't have enough resources to provide hook compatibility between minor releases of PeerTube (for example between `1.2.x` and `1.3.x`).
383 So please:
384 * Don't make assumptions and check every parameter you want to use. For example:
385
386 ```js
387 registerHook({
388 target: 'filter:api.video.get.result',
389 handler: video => {
390 // We check the parameter exists and the name field exists too, to avoid exceptions
391 if (video && video.name) video.name += ' <3'
392
393 return video
394 }
395 })
396 ```
397 * Don't try to require parent PeerTube modules, only use `peertubeHelpers`. If you need another helper or a specific hook, please [create an issue](https://github.com/Chocobozzz/PeerTube/issues/new)
398 * Don't use PeerTube dependencies. Use your own :)
399
400 If your plugin is broken with a new PeerTube release, update your code and the `peertubeEngine` field of your `package.json` field.
401 This way, older PeerTube versions will still use your old plugin, and new PeerTube versions will use your updated plugin.
402
403 ### Spam/moderation plugin
404
405 If you want to create an antispam/moderation plugin, you could use the following hooks:
406 * `filter:api.video.upload.accept.result`: to accept or not local uploads
407 * `filter:api.video-thread.create.accept.result`: to accept or not local thread
408 * `filter:api.video-comment-reply.create.accept.result`: to accept or not local replies
409 * `filter:api.video-threads.list.result`: to change/hide the text of threads
410 * `filter:api.video-thread-comments.list.result`: to change/hide the text of replies
411 * `filter:video.auto-blacklist.result`: to automatically blacklist local or remote videos
412