aboutsummaryrefslogtreecommitdiffhomepage
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/TODO.md28
-rw-r--r--plugins/addlink_toolbar/addlink_toolbar.php13
-rw-r--r--plugins/archiveorg/archiveorg.html6
-rw-r--r--plugins/archiveorg/archiveorg.php11
-rw-r--r--plugins/demo_plugin/demo_plugin.php37
-rw-r--r--plugins/demo_plugin/languages/fr/LC_MESSAGES/demo.mobin0 -> 652 bytes
-rw-r--r--plugins/demo_plugin/languages/fr/LC_MESSAGES/demo.po21
-rw-r--r--plugins/isso/isso.php17
-rw-r--r--plugins/markdown/help.html6
-rw-r--r--plugins/markdown/markdown.php21
-rw-r--r--plugins/piwik/piwik.php15
-rw-r--r--plugins/playvideos/playvideos.php13
-rw-r--r--plugins/pubsubhubbub/pubsubhubbub.php16
-rw-r--r--plugins/qrcode/qrcode.meta2
-rw-r--r--plugins/qrcode/qrcode.php9
-rw-r--r--plugins/wallabag/wallabag.html6
-rw-r--r--plugins/wallabag/wallabag.php20
17 files changed, 188 insertions, 53 deletions
diff --git a/plugins/TODO.md b/plugins/TODO.md
deleted file mode 100644
index e3313d67..00000000
--- a/plugins/TODO.md
+++ /dev/null
@@ -1,28 +0,0 @@
1https://github.com/shaarli/Shaarli/issues/181 - Add Disqus or Isso comments box on a permalink page
2
3 * http://posativ.org/isso/
4 * install debian package https://packages.debian.org/sid/isso
5 * configure server http://posativ.org/isso/docs/configuration/server/
6 * configure client http://posativ.org/isso/docs/configuration/client/
7 * http://posativ.org/isso/docs/quickstart/ and add `<script data-isso="//comments.example.tld/" src="//comments.example.tld/js/embed.min.js"></script>` to includes.html template; then add `<section id="isso-thread"></section>` in the linklist template where you want the comments (in the linklist_plugins loop for example)
8
9
10Problem: by default, Isso thread ID is guessed from the current url (only one thread per page).
11if we want multiple threads on a single page (shaarli linklist), we must use : the `data-isso-id` client config,
12with data-isso-id being the permalink of an item.
13
14`<section data-isso-id="aH7klxW" id="isso-thread"></section>`
15`data-isso-id: Set a custom thread id, defaults to current URI.`
16
17Problem: feature is currently broken https://github.com/posativ/isso/issues/27
18
19Another option, only display isso threads when current URL is a permalink (`\?(A-Z|a-z|0-9|-){7}`) (only show thread
20when displaying only this link), and just display a "comments" button on each linklist item. Optionally show the comment
21count on each item using the API (http://posativ.org/isso/docs/extras/api/#get-comment-count). API requests can be done
22by raintpl `{function` or client-side with js. The former should be faster if isso and shaarli are on ther same server.
23
24Showing all full isso threads in the linklist would destroy layout
25
26-----------------------------------------------------------
27
28http://www.git-attitude.fr/2014/11/04/git-rerere/ for the merge
diff --git a/plugins/addlink_toolbar/addlink_toolbar.php b/plugins/addlink_toolbar/addlink_toolbar.php
index ddf50aaf..8c05a231 100644
--- a/plugins/addlink_toolbar/addlink_toolbar.php
+++ b/plugins/addlink_toolbar/addlink_toolbar.php
@@ -26,11 +26,11 @@ function hook_addlink_toolbar_render_header($data)
26 array( 26 array(
27 'type' => 'text', 27 'type' => 'text',
28 'name' => 'post', 28 'name' => 'post',
29 'placeholder' => 'URI', 29 'placeholder' => t('URI'),
30 ), 30 ),
31 array( 31 array(
32 'type' => 'submit', 32 'type' => 'submit',
33 'value' => 'Add link', 33 'value' => t('Add link'),
34 'class' => 'bigbutton', 34 'class' => 'bigbutton',
35 ), 35 ),
36 ), 36 ),
@@ -40,3 +40,12 @@ function hook_addlink_toolbar_render_header($data)
40 40
41 return $data; 41 return $data;
42} 42}
43
44/**
45 * This function is never called, but contains translation calls for GNU gettext extraction.
46 */
47function addlink_toolbar_dummy_translation()
48{
49 // meta
50 t('Adds the addlink input on the linklist page.');
51}
diff --git a/plugins/archiveorg/archiveorg.html b/plugins/archiveorg/archiveorg.html
index 0781fe35..ad501f47 100644
--- a/plugins/archiveorg/archiveorg.html
+++ b/plugins/archiveorg/archiveorg.html
@@ -1 +1,5 @@
1<span><a href="https://web.archive.org/web/%s"><img class="linklist-plugin-icon" src="plugins/archiveorg/internetarchive.png" title="View on archive.org" alt="archive.org" /></a></span> 1<span>
2 <a href="https://web.archive.org/web/%s">
3 <img class="linklist-plugin-icon" src="plugins/archiveorg/internetarchive.png" title="%s" alt="archive.org" />
4 </a>
5</span>
diff --git a/plugins/archiveorg/archiveorg.php b/plugins/archiveorg/archiveorg.php
index 03d13d0e..cda35751 100644
--- a/plugins/archiveorg/archiveorg.php
+++ b/plugins/archiveorg/archiveorg.php
@@ -20,9 +20,18 @@ function hook_archiveorg_render_linklist($data)
20 if($value['private'] && preg_match('/^\?[a-zA-Z0-9-_@]{6}($|&|#)/', $value['real_url'])) { 20 if($value['private'] && preg_match('/^\?[a-zA-Z0-9-_@]{6}($|&|#)/', $value['real_url'])) {
21 continue; 21 continue;
22 } 22 }
23 $archive = sprintf($archive_html, $value['url']); 23 $archive = sprintf($archive_html, $value['url'], t('View on archive.org'));
24 $value['link_plugin'][] = $archive; 24 $value['link_plugin'][] = $archive;
25 } 25 }
26 26
27 return $data; 27 return $data;
28} 28}
29
30/**
31 * This function is never called, but contains translation calls for GNU gettext extraction.
32 */
33function archiveorg_dummy_translation()
34{
35 // meta
36 t('For each link, add an Archive.org icon.');
37}
diff --git a/plugins/demo_plugin/demo_plugin.php b/plugins/demo_plugin/demo_plugin.php
index 8fdbf663..b80a2b6d 100644
--- a/plugins/demo_plugin/demo_plugin.php
+++ b/plugins/demo_plugin/demo_plugin.php
@@ -14,6 +14,26 @@
14 * and check user status with _LOGGEDIN_. 14 * and check user status with _LOGGEDIN_.
15 */ 15 */
16 16
17use Shaarli\Config\ConfigManager;
18
19/**
20 * In the footer hook, there is a working example of a translation extension for Shaarli.
21 *
22 * The extension must be attached to a new translation domain (i.e. NOT 'shaarli').
23 * Use case: any custom theme or non official plugin can use the translation system.
24 *
25 * See the documentation for more information.
26 */
27const EXT_TRANSLATION_DOMAIN = 'demo';
28
29/*
30 * This is not necessary, but it's easier if you don't want Poedit to mix up your translations.
31 */
32function demo_plugin_t($text, $nText = '', $nb = 1)
33{
34 return t($text, $nText, $nb, EXT_TRANSLATION_DOMAIN);
35}
36
17/** 37/**
18 * Initialization function. 38 * Initialization function.
19 * It will be called when the plugin is loaded. 39 * It will be called when the plugin is loaded.
@@ -27,6 +47,12 @@ function demo_plugin_init($conf)
27{ 47{
28 $conf->get('toto', 'nope'); 48 $conf->get('toto', 'nope');
29 49
50 if (! $conf->exists('translation.extensions.demo')) {
51 // Custom translation with the domain 'demo'
52 $conf->set('translation.extensions.demo', 'plugins/demo_plugin/languages/');
53 $conf->write(true);
54 }
55
30 $errors[] = 'This a demo init error.'; 56 $errors[] = 'This a demo init error.';
31 return $errors; 57 return $errors;
32} 58}
@@ -160,7 +186,7 @@ function hook_demo_plugin_render_includes($data)
160function hook_demo_plugin_render_footer($data) 186function hook_demo_plugin_render_footer($data)
161{ 187{
162 // footer text 188 // footer text
163 $data['text'][] = 'Shaarli is now enhanced by the awesome demo_plugin.'; 189 $data['text'][] = '<br>'. demo_plugin_t('Shaarli is now enhanced by the awesome demo_plugin.');
164 190
165 // Free elements at the end of the page. 191 // Free elements at the end of the page.
166 $data['endofpage'][] = '<marquee id="demo_marquee">' . 192 $data['endofpage'][] = '<marquee id="demo_marquee">' .
@@ -433,3 +459,12 @@ function hook_demo_plugin_render_feed($data)
433 } 459 }
434 return $data; 460 return $data;
435} 461}
462
463/**
464 * This function is never called, but contains translation calls for GNU gettext extraction.
465 */
466function demo_dummy_translation()
467{
468 // meta
469 t('A demo plugin covering all use cases for template designers and plugin developers.');
470}
diff --git a/plugins/demo_plugin/languages/fr/LC_MESSAGES/demo.mo b/plugins/demo_plugin/languages/fr/LC_MESSAGES/demo.mo
new file mode 100644
index 00000000..0f80f6ed
--- /dev/null
+++ b/plugins/demo_plugin/languages/fr/LC_MESSAGES/demo.mo
Binary files differ
diff --git a/plugins/demo_plugin/languages/fr/LC_MESSAGES/demo.po b/plugins/demo_plugin/languages/fr/LC_MESSAGES/demo.po
new file mode 100644
index 00000000..921379c0
--- /dev/null
+++ b/plugins/demo_plugin/languages/fr/LC_MESSAGES/demo.po
@@ -0,0 +1,21 @@
1msgid ""
2msgstr ""
3"Project-Id-Version: Demo plugin\n"
4"POT-Creation-Date: 2017-08-19 10:45+0200\n"
5"PO-Revision-Date: 2017-08-19 11:28+0200\n"
6"Last-Translator: \n"
7"Language-Team: demo\n"
8"Language: fr\n"
9"MIME-Version: 1.0\n"
10"Content-Type: text/plain; charset=UTF-8\n"
11"Content-Transfer-Encoding: 8bit\n"
12"X-Generator: Poedit 2.0.2\n"
13"X-Poedit-Basepath: ../../..\n"
14"Plural-Forms: nplurals=2; plural=(n > 1);\n"
15"X-Poedit-KeywordsList: ;demo_plugin_t:1,2;demo_plugin_t\n"
16"X-Poedit-SourceCharset: UTF-8\n"
17"X-Poedit-SearchPath-0: .\n"
18
19#: demo_plugin.php:173
20msgid "Shaarli is now enhanced by the awesome demo_plugin."
21msgstr "Shaarli est maintenant amélioré avec le fantastique demo_plugin."
diff --git a/plugins/isso/isso.php b/plugins/isso/isso.php
index ce16645f..5bc1cce2 100644
--- a/plugins/isso/isso.php
+++ b/plugins/isso/isso.php
@@ -4,10 +4,11 @@
4 * Plugin Isso. 4 * Plugin Isso.
5 */ 5 */
6 6
7use Shaarli\Config\ConfigManager;
8
7/** 9/**
8 * Display an error everywhere if the plugin is enabled without configuration. 10 * Display an error everywhere if the plugin is enabled without configuration.
9 * 11 *
10 * @param $data array List of links
11 * @param $conf ConfigManager instance 12 * @param $conf ConfigManager instance
12 * 13 *
13 * @return mixed - linklist data with Isso plugin. 14 * @return mixed - linklist data with Isso plugin.
@@ -16,8 +17,8 @@ function isso_init($conf)
16{ 17{
17 $issoUrl = $conf->get('plugins.ISSO_SERVER'); 18 $issoUrl = $conf->get('plugins.ISSO_SERVER');
18 if (empty($issoUrl)) { 19 if (empty($issoUrl)) {
19 $error = 'Isso plugin error: '. 20 $error = t('Isso plugin error: '.
20 'Please define the "ISSO_SERVER" setting in the plugin administration page.'; 21 'Please define the "ISSO_SERVER" setting in the plugin administration page.');
21 return array($error); 22 return array($error);
22 } 23 }
23} 24}
@@ -52,3 +53,13 @@ function hook_isso_render_linklist($data, $conf)
52 53
53 return $data; 54 return $data;
54} 55}
56
57/**
58 * This function is never called, but contains translation calls for GNU gettext extraction.
59 */
60function isso_dummy_translation()
61{
62 // meta
63 t('Let visitor comment your shaares on permalinks with Isso.');
64 t('Isso server URL (without \'http://\')');
65}
diff --git a/plugins/markdown/help.html b/plugins/markdown/help.html
index 9c4e5ae0..ded3d347 100644
--- a/plugins/markdown/help.html
+++ b/plugins/markdown/help.html
@@ -1,5 +1,5 @@
1<div class="md_help"> 1<div class="md_help">
2 Description will be rendered with 2 %s
3 <a href="http://daringfireball.net/projects/markdown/syntax" title="Markdown syntax documentation"> 3 <a href="http://daringfireball.net/projects/markdown/syntax" title="%s">
4 Markdown syntax</a>. 4 %s</a>.
5</div> 5</div>
diff --git a/plugins/markdown/markdown.php b/plugins/markdown/markdown.php
index 772c56e8..1531549d 100644
--- a/plugins/markdown/markdown.php
+++ b/plugins/markdown/markdown.php
@@ -154,8 +154,13 @@ function hook_markdown_render_includes($data)
154function hook_markdown_render_editlink($data) 154function hook_markdown_render_editlink($data)
155{ 155{
156 // Load help HTML into a string 156 // Load help HTML into a string
157 $data['edit_link_plugin'][] = file_get_contents(PluginManager::$PLUGINS_PATH .'/markdown/help.html'); 157 $txt = file_get_contents(PluginManager::$PLUGINS_PATH .'/markdown/help.html');
158 158 $translations = [
159 t('Description will be rendered with'),
160 t('Markdown syntax documentation'),
161 t('Markdown syntax'),
162 ];
163 $data['edit_link_plugin'][] = vsprintf($txt, $translations);
159 // Add no markdown 'meta-tag' in tag list if it was never used, for autocompletion. 164 // Add no markdown 'meta-tag' in tag list if it was never used, for autocompletion.
160 if (! in_array(NO_MD_TAG, $data['tags'])) { 165 if (! in_array(NO_MD_TAG, $data['tags'])) {
161 $data['tags'][NO_MD_TAG] = 0; 166 $data['tags'][NO_MD_TAG] = 0;
@@ -325,3 +330,15 @@ function process_markdown($description, $escape = true, $allowedProtocols = [])
325 330
326 return $processedDescription; 331 return $processedDescription;
327} 332}
333
334/**
335 * This function is never called, but contains translation calls for GNU gettext extraction.
336 */
337function markdown_dummy_translation()
338{
339 // meta
340 t('Render shaare description with Markdown syntax.<br><strong>Warning</strong>:
341If your shaared descriptions contained HTML tags before enabling the markdown plugin,
342enabling it might break your page.
343See the <a href="https://github.com/shaarli/Shaarli/tree/master/plugins/markdown#html-rendering">README</a>.');
344}
diff --git a/plugins/piwik/piwik.php b/plugins/piwik/piwik.php
index 4a2b48a1..ca00c2be 100644
--- a/plugins/piwik/piwik.php
+++ b/plugins/piwik/piwik.php
@@ -18,8 +18,8 @@ function piwik_init($conf)
18 $piwikUrl = $conf->get('plugins.PIWIK_URL'); 18 $piwikUrl = $conf->get('plugins.PIWIK_URL');
19 $piwikSiteid = $conf->get('plugins.PIWIK_SITEID'); 19 $piwikSiteid = $conf->get('plugins.PIWIK_SITEID');
20 if (empty($piwikUrl) || empty($piwikSiteid)) { 20 if (empty($piwikUrl) || empty($piwikSiteid)) {
21 $error = 'Piwik plugin error: ' . 21 $error = t('Piwik plugin error: ' .
22 'Please define PIWIK_URL and PIWIK_SITEID in the plugin administration page.'; 22 'Please define PIWIK_URL and PIWIK_SITEID in the plugin administration page.');
23 return array($error); 23 return array($error);
24 } 24 }
25} 25}
@@ -60,3 +60,14 @@ function hook_piwik_render_footer($data, $conf)
60 60
61 return $data; 61 return $data;
62} 62}
63
64/**
65 * This function is never called, but contains translation calls for GNU gettext extraction.
66 */
67function piwik_dummy_translation()
68{
69 // meta
70 t('A plugin that adds Piwik tracking code to Shaarli pages.');
71 t('Piwik URL');
72 t('Piwik site ID');
73}
diff --git a/plugins/playvideos/playvideos.php b/plugins/playvideos/playvideos.php
index 64484504..c6d6b0cc 100644
--- a/plugins/playvideos/playvideos.php
+++ b/plugins/playvideos/playvideos.php
@@ -19,10 +19,10 @@ function hook_playvideos_render_header($data)
19 $playvideo = array( 19 $playvideo = array(
20 'attr' => array( 20 'attr' => array(
21 'href' => '#', 21 'href' => '#',
22 'title' => 'Video player', 22 'title' => t('Video player'),
23 'id' => 'playvideos', 23 'id' => 'playvideos',
24 ), 24 ),
25 'html' => '► Play Videos' 25 'html' => '► '. t('Play Videos')
26 ); 26 );
27 $data['buttons_toolbar'][] = $playvideo; 27 $data['buttons_toolbar'][] = $playvideo;
28 } 28 }
@@ -46,3 +46,12 @@ function hook_playvideos_render_footer($data)
46 46
47 return $data; 47 return $data;
48} 48}
49
50/**
51 * This function is never called, but contains translation calls for GNU gettext extraction.
52 */
53function playvideos_dummy_translation()
54{
55 // meta
56 t('Add a button in the toolbar allowing to watch all videos.');
57}
diff --git a/plugins/pubsubhubbub/pubsubhubbub.php b/plugins/pubsubhubbub/pubsubhubbub.php
index 03b6757b..184b588b 100644
--- a/plugins/pubsubhubbub/pubsubhubbub.php
+++ b/plugins/pubsubhubbub/pubsubhubbub.php
@@ -10,6 +10,7 @@
10 */ 10 */
11 11
12use pubsubhubbub\publisher\Publisher; 12use pubsubhubbub\publisher\Publisher;
13use Shaarli\Config\ConfigManager;
13 14
14/** 15/**
15 * Plugin init function - set the hub to the default appspot one. 16 * Plugin init function - set the hub to the default appspot one.
@@ -65,7 +66,7 @@ function hook_pubsubhubbub_save_link($data, $conf)
65 $p = new Publisher($conf->get('plugins.PUBSUBHUB_URL')); 66 $p = new Publisher($conf->get('plugins.PUBSUBHUB_URL'));
66 $p->publish_update($feeds, $httpPost); 67 $p->publish_update($feeds, $httpPost);
67 } catch (Exception $e) { 68 } catch (Exception $e) {
68 error_log('Could not publish to PubSubHubbub: ' . $e->getMessage()); 69 error_log(sprintf(t('Could not publish to PubSubHubbub: %s'), $e->getMessage()));
69 } 70 }
70 71
71 return $data; 72 return $data;
@@ -91,11 +92,20 @@ function nocurl_http_post($url, $postString) {
91 $context = stream_context_create($params); 92 $context = stream_context_create($params);
92 $fp = @fopen($url, 'rb', false, $context); 93 $fp = @fopen($url, 'rb', false, $context);
93 if (!$fp) { 94 if (!$fp) {
94 throw new Exception('Could not post to '. $url); 95 throw new Exception(sprintf(t('Could not post to %s'), $url));
95 } 96 }
96 $response = @stream_get_contents($fp); 97 $response = @stream_get_contents($fp);
97 if ($response === false) { 98 if ($response === false) {
98 throw new Exception('Bad response from the hub '. $url); 99 throw new Exception(sprintf(t('Bad response from the hub %s'), $url));
99 } 100 }
100 return $response; 101 return $response;
101} 102}
103
104/**
105 * This function is never called, but contains translation calls for GNU gettext extraction.
106 */
107function pubsubhubbub_dummy_translation()
108{
109 // meta
110 t('Enable PubSubHubbub feed publishing.');
111}
diff --git a/plugins/qrcode/qrcode.meta b/plugins/qrcode/qrcode.meta
index cbf371ea..1812cd21 100644
--- a/plugins/qrcode/qrcode.meta
+++ b/plugins/qrcode/qrcode.meta
@@ -1 +1 @@
description="For each link, add a QRCode icon ." description="For each link, add a QRCode icon."
diff --git a/plugins/qrcode/qrcode.php b/plugins/qrcode/qrcode.php
index 8bc610d1..0f96a106 100644
--- a/plugins/qrcode/qrcode.php
+++ b/plugins/qrcode/qrcode.php
@@ -59,3 +59,12 @@ function hook_qrcode_render_includes($data)
59 59
60 return $data; 60 return $data;
61} 61}
62
63/**
64 * This function is never called, but contains translation calls for GNU gettext extraction.
65 */
66function qrcode_dummy_translation()
67{
68 // meta
69 t('For each link, add a QRCode icon.');
70}
diff --git a/plugins/wallabag/wallabag.html b/plugins/wallabag/wallabag.html
index e861536d..4c57691d 100644
--- a/plugins/wallabag/wallabag.html
+++ b/plugins/wallabag/wallabag.html
@@ -1 +1,5 @@
1<span><a href="%s%s" target="_blank"><img class="linklist-plugin-icon" src="%s/wallabag/wallabag.png" title="Save to wallabag" alt="wallabag" /></a></span> 1<span>
2 <a href="%s%s" target="_blank">
3 <img class="linklist-plugin-icon" src="%s/wallabag/wallabag.png" title="%s" alt="wallabag" />
4 </a>
5</span>
diff --git a/plugins/wallabag/wallabag.php b/plugins/wallabag/wallabag.php
index 641e4cc2..9dfd079e 100644
--- a/plugins/wallabag/wallabag.php
+++ b/plugins/wallabag/wallabag.php
@@ -5,6 +5,7 @@
5 */ 5 */
6 6
7require_once 'WallabagInstance.php'; 7require_once 'WallabagInstance.php';
8use Shaarli\Config\ConfigManager;
8 9
9/** 10/**
10 * Init function, return an error if the server is not set. 11 * Init function, return an error if the server is not set.
@@ -17,8 +18,8 @@ function wallabag_init($conf)
17{ 18{
18 $wallabagUrl = $conf->get('plugins.WALLABAG_URL'); 19 $wallabagUrl = $conf->get('plugins.WALLABAG_URL');
19 if (empty($wallabagUrl)) { 20 if (empty($wallabagUrl)) {
20 $error = 'Wallabag plugin error: '. 21 $error = t('Wallabag plugin error: '.
21 'Please define the "WALLABAG_URL" setting in the plugin administration page.'; 22 'Please define the "WALLABAG_URL" setting in the plugin administration page.');
22 return array($error); 23 return array($error);
23 } 24 }
24} 25}
@@ -43,12 +44,14 @@ function hook_wallabag_render_linklist($data, $conf)
43 44
44 $wallabagHtml = file_get_contents(PluginManager::$PLUGINS_PATH . '/wallabag/wallabag.html'); 45 $wallabagHtml = file_get_contents(PluginManager::$PLUGINS_PATH . '/wallabag/wallabag.html');
45 46
47 $linkTitle = t('Save to wallabag');
46 foreach ($data['links'] as &$value) { 48 foreach ($data['links'] as &$value) {
47 $wallabag = sprintf( 49 $wallabag = sprintf(
48 $wallabagHtml, 50 $wallabagHtml,
49 $wallabagInstance->getWallabagUrl(), 51 $wallabagInstance->getWallabagUrl(),
50 urlencode($value['url']), 52 urlencode($value['url']),
51 PluginManager::$PLUGINS_PATH 53 PluginManager::$PLUGINS_PATH,
54 $linkTitle
52 ); 55 );
53 $value['link_plugin'][] = $wallabag; 56 $value['link_plugin'][] = $wallabag;
54 } 57 }
@@ -56,3 +59,14 @@ function hook_wallabag_render_linklist($data, $conf)
56 return $data; 59 return $data;
57} 60}
58 61
62/**
63 * This function is never called, but contains translation calls for GNU gettext extraction.
64 */
65function wallabag_dummy_translation()
66{
67 // meta
68 t('For each link, add a QRCode icon.');
69 t('Wallabag API URL');
70 t('Wallabag API version (1 or 2)');
71}
72