diff options
author | Chocobozzz <me@florianbigard.com> | 2019-07-23 11:23:25 +0200 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2019-07-24 10:58:16 +0200 |
commit | d8e9a42c4b048b2669ab6a61704682ce23fbcf99 (patch) | |
tree | e54af7ea903ab04728832f1451141050f0986f54 /support/doc/plugins/guide.md | |
parent | 7c421bb19809c4b0223d9e082d52d125fbe95f2a (diff) | |
download | PeerTube-d8e9a42c4b048b2669ab6a61704682ce23fbcf99.tar.gz PeerTube-d8e9a42c4b048b2669ab6a61704682ce23fbcf99.tar.zst PeerTube-d8e9a42c4b048b2669ab6a61704682ce23fbcf99.zip |
Update plugin guide
Diffstat (limited to 'support/doc/plugins/guide.md')
-rw-r--r-- | support/doc/plugins/guide.md | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/support/doc/plugins/guide.md b/support/doc/plugins/guide.md new file mode 100644 index 000000000..85e5f1e7d --- /dev/null +++ b/support/doc/plugins/guide.md | |||
@@ -0,0 +1,301 @@ | |||
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 | - [Publishing](#publishing) | ||
15 | - [Write a plugin/theme](#write-a-plugintheme) | ||
16 | - [Clone the quickstart repository](#clone-the-quickstart-repository) | ||
17 | - [Configure your repository](#configure-your-repository) | ||
18 | - [Update README](#update-readme) | ||
19 | - [Update package.json](#update-packagejson) | ||
20 | - [Write code](#write-code) | ||
21 | - [Test your plugin/theme](#test-your-plugintheme) | ||
22 | - [Publish](#publish) | ||
23 | - [Tips](#tips) | ||
24 | - [Compatibility with PeerTube](#compatibility-with-peertube) | ||
25 | - [Spam/moderation plugin](#spammoderation-plugin) | ||
26 | |||
27 | <!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
28 | |||
29 | ## Concepts | ||
30 | |||
31 | Themes are exactly the same than plugins, except that: | ||
32 | * Their name starts with `peertube-theme-` instead of `peertube-plugin-` | ||
33 | * They cannot declare server code (so they cannot register server hooks or settings) | ||
34 | * CSS files are loaded by client only if the theme is chosen by the administrator or the user | ||
35 | |||
36 | ### Hooks | ||
37 | |||
38 | A plugin registers functions in JavaScript to execute when PeerTube (server and client) fires events. There are 3 types of hooks: | ||
39 | * `filter`: used to filter functions parameters or return values. | ||
40 | For example to replace words in video comments, or change the videos list behaviour | ||
41 | * `action`: used to do something after a certain trigger. For example to send a hook every time a video is published | ||
42 | * `static`: same than `action` but PeerTube waits their execution | ||
43 | |||
44 | Example: | ||
45 | |||
46 | ```js | ||
47 | // This register function is called by PeerTube, and **must** return a promise | ||
48 | async function register ({ registerHook, registerSetting, settingsManager, storageManager, peertubeHelpers }) { | ||
49 | registerHook({ | ||
50 | target: 'action:application.listening', | ||
51 | handler: () => displayHelloWorld() | ||
52 | }) | ||
53 | } | ||
54 | ``` | ||
55 | |||
56 | On server side, these hooks are registered by the `library` file defined in `package.json`. | ||
57 | |||
58 | ```json | ||
59 | { | ||
60 | ..., | ||
61 | "library": "./main.js", | ||
62 | ..., | ||
63 | } | ||
64 | ``` | ||
65 | |||
66 | |||
67 | On client side, these hooks are registered by the `clientScripts` files defined in `package.json`. | ||
68 | All client scripts have scopes so PeerTube client only loads scripts it needs: | ||
69 | |||
70 | ```json | ||
71 | { | ||
72 | ..., | ||
73 | "clientScripts": [ | ||
74 | { | ||
75 | "script": "client/common-client-plugin.js", | ||
76 | "scopes": [ "common" ] | ||
77 | }, | ||
78 | { | ||
79 | "script": "client/video-watch-client-plugin.js", | ||
80 | "scopes": [ "video-watch" ] | ||
81 | } | ||
82 | ], | ||
83 | ... | ||
84 | } | ||
85 | ``` | ||
86 | |||
87 | ### Static files | ||
88 | |||
89 | Plugins can declare static directories that PeerTube will serve (images for example) | ||
90 | from `/plugins/{plugin-name}/{plugin-version}/static/` | ||
91 | or `/themes/{theme-name}/{theme-version}/static/` routes. | ||
92 | |||
93 | ### CSS | ||
94 | |||
95 | Plugins can declare CSS files that PeerTube will automatically inject in the client. | ||
96 | |||
97 | ### Server helpers (only for plugins) | ||
98 | |||
99 | #### Settings | ||
100 | |||
101 | Plugins can register settings, that PeerTube will inject in the administration interface. | ||
102 | |||
103 | Example: | ||
104 | |||
105 | ```js | ||
106 | registerSetting({ | ||
107 | name: 'admin-name', | ||
108 | label: 'Admin name', | ||
109 | type: 'input', | ||
110 | default: 'my super name' | ||
111 | }) | ||
112 | |||
113 | const adminName = await settingsManager.getSetting('admin-name') | ||
114 | ``` | ||
115 | |||
116 | #### Storage | ||
117 | |||
118 | Plugins can store/load JSON data, that PeerTube will store in its database (so don't put files in there). | ||
119 | |||
120 | Example: | ||
121 | |||
122 | ```js | ||
123 | const value = await storageManager.getData('mykey') | ||
124 | await storageManager.storeData('mykey', { subkey: 'value' }) | ||
125 | ``` | ||
126 | |||
127 | ### Publishing | ||
128 | |||
129 | PeerTube plugins and themes should be published on [NPM](https://www.npmjs.com/) so that PeerTube indexes | ||
130 | 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). | ||
131 | |||
132 | ## Write a plugin/theme | ||
133 | |||
134 | Steps: | ||
135 | * Find a name for your plugin or your theme (must not have spaces, it can only contain lowercase letters and `-`) | ||
136 | * Add the appropriate prefix: | ||
137 | * If you develop a plugin, add `peertube-plugin-` prefix to your plugin name (for example: `peertube-plugin-mysupername`) | ||
138 | * If you develop a theme, add `peertube-theme-` prefix to your theme name (for example: `peertube-theme-mysupertheme`) | ||
139 | * Clone the quickstart repository | ||
140 | * Configure your repository | ||
141 | * Update `README.md` | ||
142 | * Update `package.json` | ||
143 | * Register hooks, add CSS and static files | ||
144 | * Test your plugin/theme with a local PeerTube installation | ||
145 | * Publish your plugin/theme on NPM | ||
146 | |||
147 | ### Clone the quickstart repository | ||
148 | |||
149 | If you develop a plugin, clone the `peertube-plugin-quickstart` repository: | ||
150 | |||
151 | ``` | ||
152 | $ git clone https://framagit.org/framasoft/peertube/peertube-plugin-quickstart.git peertube-plugin-mysupername | ||
153 | ``` | ||
154 | |||
155 | If you develop a theme, clone the `peertube-theme-quickstart` repository: | ||
156 | |||
157 | ``` | ||
158 | $ git clone https://framagit.org/framasoft/peertube/peertube-theme-quickstart.git peertube-theme-mysupername | ||
159 | ``` | ||
160 | |||
161 | ### Configure your repository | ||
162 | |||
163 | Set your repository URL: | ||
164 | |||
165 | ``` | ||
166 | $ cd peertube-plugin-mysupername # or cd peertube-theme-mysupername | ||
167 | $ git remote set-url origin https://your-git-repo | ||
168 | ``` | ||
169 | |||
170 | ### Update README | ||
171 | |||
172 | Update `README.md` file: | ||
173 | |||
174 | ``` | ||
175 | $ $EDITOR README.md | ||
176 | ``` | ||
177 | |||
178 | ### Update package.json | ||
179 | |||
180 | Update the `package.json` fields: | ||
181 | * `name` (should start with `peertube-plugin-` or `peertube-theme-`) | ||
182 | * `description` | ||
183 | * `homepage` | ||
184 | * `author` | ||
185 | * `bugs` | ||
186 | * `engine.peertube` (the PeerTube version compatibility, must be `>=x.y.z` and nothing else) | ||
187 | |||
188 | **Caution:** Don't update or remove other keys, or PeerTube will not be able to index/install your plugin. | ||
189 | If you don't need static directories, use an empty `object`: | ||
190 | |||
191 | ```json | ||
192 | { | ||
193 | ..., | ||
194 | "staticDirs": {}, | ||
195 | ... | ||
196 | } | ||
197 | ``` | ||
198 | |||
199 | And if you don't need CSS or client script files, use an empty `array`: | ||
200 | |||
201 | ```json | ||
202 | { | ||
203 | ..., | ||
204 | "css": [], | ||
205 | "clientScripts": [], | ||
206 | ... | ||
207 | } | ||
208 | ``` | ||
209 | |||
210 | ### Write code | ||
211 | |||
212 | Now you can register hooks or settings, write CSS and add static directories to your plugin or your theme :) | ||
213 | |||
214 | **Caution:** It's up to you to check the code you write will be compatible with the PeerTube NodeJS version, | ||
215 | and will be supported by web browsers. | ||
216 | If you want to write modern JavaScript, please use a transpiler like [Babel](https://babeljs.io/). | ||
217 | |||
218 | ### Test your plugin/theme | ||
219 | |||
220 | You'll need to have a local PeerTube instance: | ||
221 | * Follow the [dev prerequisites](https://github.com/Chocobozzz/PeerTube/blob/develop/.github/CONTRIBUTING.md#prerequisites) | ||
222 | (to clone the repository, install dependencies and prepare the database) | ||
223 | * Build PeerTube (`--light` to only build the english language): | ||
224 | |||
225 | ``` | ||
226 | $ npm run build -- --light | ||
227 | ``` | ||
228 | |||
229 | * Build the CLI: | ||
230 | |||
231 | ``` | ||
232 | $ npm run setup:cli | ||
233 | ``` | ||
234 | |||
235 | * Run PeerTube (you can access to your instance on http://localhost:9000): | ||
236 | |||
237 | ``` | ||
238 | $ NODE_ENV=test npm start | ||
239 | ``` | ||
240 | |||
241 | * Register the instance via the CLI: | ||
242 | |||
243 | ``` | ||
244 | $ node ./dist/server/tools/peertube.js auth add -u 'http://localhost:9000' -U 'root' --password 'test' | ||
245 | ``` | ||
246 | |||
247 | Then, you can install or reinstall your local plugin/theme by running: | ||
248 | |||
249 | ``` | ||
250 | $ node ./dist/server/tools/peertube.js plugins install --path /your/absolute/plugin-or-theme/path | ||
251 | ``` | ||
252 | |||
253 | ### Publish | ||
254 | |||
255 | Go in your plugin/theme directory, and run: | ||
256 | |||
257 | ``` | ||
258 | $ npm publish | ||
259 | ``` | ||
260 | |||
261 | Every time you want to publish another version of your plugin/theme, just update the `version` key from the `package.json` | ||
262 | and republish it on NPM. Remember that the PeerTube index will take into account your new plugin/theme version after ~24 hours. | ||
263 | |||
264 | |||
265 | ## Tips | ||
266 | |||
267 | ### Compatibility with PeerTube | ||
268 | |||
269 | 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`). | ||
270 | So please: | ||
271 | * Don't make assumptions and check every parameter you want to use. For example: | ||
272 | |||
273 | ```js | ||
274 | registerHook({ | ||
275 | target: 'filter:api.video.get.result', | ||
276 | handler: video => { | ||
277 | // We check the parameter exists and the name field exists too, to avoid exceptions | ||
278 | if (video && video.name) video.name += ' <3' | ||
279 | |||
280 | return video | ||
281 | } | ||
282 | }) | ||
283 | ``` | ||
284 | * Don't try to require parent PeerTube modules, only use `peertubeHelpers`. If you need another helper or a specific, please [create an issue](https://github.com/Chocobozzz/PeerTube/issues/new) | ||
285 | * Don't use PeerTube dependencies. Use your own :) | ||
286 | |||
287 | If your plugin is broken with a new PeerTube release, update your code and the `peertubeEngine` `package.json` field. | ||
288 | This way, older PeerTube versions will still use your old plugin, and new PeerTube versions will use your updated plugin. | ||
289 | |||
290 | ### Spam/moderation plugin | ||
291 | |||
292 | If you want to create an antispam/moderation plugin, you could use the following hooks: | ||
293 | * `filter:api.video.upload.accept.result`: to accept or not local uploads | ||
294 | * `filter:api.video-thread.create.accept.result`: to accept or not local thread | ||
295 | * `filter:api.video-comment-reply.create.accept.result`: to accept or not local replies | ||
296 | * `filter:api.video-threads.list.result`: to change/hide the text of threads | ||
297 | * `filter:api.video-thread-comments.list.result`: to change/hide the text of replies | ||
298 | * `filter:video.auto-blacklist.result`: to automatically blacklist local or remote videos | ||
299 | |||
300 | |||
301 | |||