Skip to content

Commit bef866a

Browse files
committed
Pleroma support.
- Added support for Pleroma posts. - Fixed some toots URLs badly parsed (the ones with more than two “folders” in their paths).
1 parent 84c88fa commit bef866a

File tree

6 files changed

+93
-16
lines changed

6 files changed

+93
-16
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
#v1.1.0
2+
## 11-07-2018
3+
4+
1. [](#new)
5+
* Added [Pleroma](https://pleroma.social) support (using the `toot` shortcode).
6+
7+
1. [](#bugfix)
8+
* Fixed some Mastodon URLs badly parsed.
9+
110
# v1.0.1
211
## 07-07-2018
312

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
The **Static Social Embeds** Plugin is for [Grav CMS](http://github.com/getgrav/grav). It embeds social status (like tweets, instagram posts, toots, etc.) in articles without using their embed iframe, but rather statically without any dependency to the service.
44

5+
The following networks are supported ([see below](#usage) for details):
6+
7+
- [Twitter](https://twitter.com);
8+
- [Mastodon](https://joinmastodon.org) and [Pleroma](https://pleroma.social);
9+
- [Instagram](https://www.instagram.com).
10+
511
## Installation
612

713
Installing the Static Social Embeds plugin can be done in one of two ways. The GPM (Grav Package Manager) installation method enables you to quickly and easily install the plugin with a simple terminal command, while the manual method enables you to do so via a zip file.
@@ -32,6 +38,8 @@ If you use the admin plugin, you can install directly through the admin plugin b
3238

3339
Before configuring this plugin, you should copy the `user/plugins/static-social-embeds/static-social-embeds.yaml` to `user/config/plugins/static-social-embeds.yaml` and only edit that copy.
3440

41+
Note that if you use the admin plugin, a file with your configuration, and named static-social-embeds.yaml will be saved in the `user/config/plugins/` folder once the configuration is saved in the admin.
42+
3543
Here is the default configuration and a short explanation of available options. Extensive explanations are available in the admin page of the plugin.
3644

3745
```yaml
@@ -86,17 +94,15 @@ To use Twitter embeds, you'll need to register an application. This is done in a
8694
2. Then, click the **Keys and access tokens** tab and at the bottom of the page, click **Create my Access Token**.
8795
3. Finally, copy the credentials in the configuration file (or in the admin).
8896

89-
Note that if you use the admin plugin, a file with your configuration, and named static-social-embeds.yaml will be saved in the `user/config/plugins/` folder once the configuration is saved in the admin.
90-
9197
### Customization
9298

9399
If you want to customize the embeds' HTML code, you can override the `partials/static-social-embeds` templates. The template name is the same as the shortcode name (see below), e.g. `toot.html.twig` for Mastodon embeds template. Templates context vary for different social networks; checkout built-in templates or shortcode classes to know which variables you can use.
94100

95101
## Usage
96102

97-
The plugin supports static embeds for Twitter, Mastodon and Instagram posts. It tries to match original embeds styles, so it's close to the real embeds, wut without any request to the social networks: independence!
103+
The plugin supports static embeds for Twitter, Mastodon (including Pleroma) and Instagram posts. It tries to match original embeds styles, so it's close to the real embeds, but without any request to the social networks: independence!
98104

99-
Three shortcodes are declared to embed status: `tweet`, `toot` and `instagram`, for respectively Twitter, Mastodon and Instagram. They accept one parameter: the status URL to embed. Use them in your articles like this:
105+
Three shortcodes are declared to embed status: `tweet`, `toot` and `instagram`, for respectively Twitter, Mastodon/Pleroma, and Instagram. They accept one parameter: the status URL to embed. Use them in your articles like this:
100106

101107
```markdown
102108
[tweet="https://twitter.com/INSVideos/status/1013375197984980992"]
@@ -110,7 +116,7 @@ The following shortcodes will be rendered as below (for light and dark themes, w
110116

111117
![](assets/docs/embeds-preview.png)
112118

113-
Texts, images (single or multiples), videos (single or multiples), GIFs, are supported for all networks above. Mastodon toots supports CW and sensitive images.
119+
Texts, images (single or multiples), videos (single or multiples), GIFs, are supported for all networks above. Mastodon/Pleroma toots supports CW and sensitive images, account privacy badges, and instances' custom emojis. Twitter and Instagram supports verified and protected accounts badges.
114120

115121
Extensive caching is used to retrieve data and medias only once per embed. The first page load may be slow (especially if there are a lot of embeds in the page), but subsequent calls will be lightning-fast, as all data will be read from the cache, without any request to the social networks (no tracking, yay!). This also means that if an embed status is deleted, it will be kept on your site if the cache is not deleted. Custom locations are used for the cache files.
116122

@@ -121,7 +127,7 @@ The plugin is translated in English and French.
121127

122128
## Technical considerations regarding Instagram
123129

124-
While Twitter and Mastodon data are retrieved using their respective API, there is no way to do that with Instagram (or there is, but deprecated and soon-to-be-removed in december 2018). We scrap an internal JSON embed in the post pages to retrieve data (thanks to [RSSBridge](https://github.com/RSS-Bridge/rss-bridge/blob/master/bridges/InstagramBridge.php) for the tip). As it isn't official, it may break anytime.
130+
While Twitter and Mastodon/Pleroma data are retrieved using their respective API, there is no way to do that with Instagram (or there is, but deprecated and soon-to-be-removed in december 2018). We scrap an internal JSON embed in the post pages to retrieve data (thanks to [RSSBridge](https://github.com/RSS-Bridge/rss-bridge/blob/master/bridges/InstagramBridge.php) for the tip). As it isn't official, it may break anytime.
125131

126132
Data is cached without expiration, so as long as you don't delete the cache, existing embeds will never break. New ones will. Feel free to open an issue if such problem occurs (but this is pretty stable for a few years now and I hope it will remains as such).
127133

@@ -132,5 +138,5 @@ Data is cached without expiration, so as long as you don't delete the cache, exi
132138
## To Do
133139

134140
- [ ] Support for Twitter pools.
135-
- [ ] Support for Pleroma (should be simple as it's compatible with the Mastodon API) and maybe other networks (by request).
141+
- [ ] Support for other networks (by request).
136142
- [ ] Maybe option to proxy medias, allowing not to store them but still serve them from the website's domain.

languages/en.yaml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ PLUGIN_SSE:
3535
DIRECT: Direct message
3636
REBLOGS: $rbls reblogs
3737
FAVOURITES: $favs favourites
38+
PLEROMA:
39+
CANNOT_RENDER: Unable to render post.
40+
VIEW_ON_MASTODON: (Click to view on Pleroma.)
41+
REBLOGS: $rbls repeats
42+
FAVOURITES: $favs likes
43+
VISIBILITIES:
44+
PUBLIC: Public post
45+
UNLISTED: Unlisted post
46+
PRIVATE: Private post
47+
DIRECT: Direct message
3848
INSTAGRAM:
3949
CANNOT_RENDER: Unable to render post
4050
VIEW_ON_INSTAGRAM: (Click to view on Instagram.)
@@ -119,12 +129,13 @@ PLUGIN_SSE:
119129
MASTODON:
120130
TITLE: Mastodon
121131
HELP: |
122-
Embed toots from <a href="https://joinmastodon.org">Mastodon</a> in articles using
123-
<code>[toot="tootURL"]</code> with blanks lines before and after.<br />
132+
Embed toots from <a href="https://joinmastodon.org">Mastodon</a> or posts from
133+
<a href="https://pleroma.social/">Pleroma</a> in articles using <code>[toot="tootURL"]</code> with blanks lines
134+
before and after.<br />
124135
As toots are retrieved using non-authenticated requests, you cannot embed private or direct toots (but
125136
unlisted and public ones are fine).
126137
THEME:
127-
LABEL: Mastodon theme
138+
LABEL: Mastodon/Pleroma theme
128139
HELP: The embeds theme. This option is only guaranteed to be followed with the built-in CSS.
129140
INSTAGRAM:
130141
TITLE: Instagram

languages/fr.yaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,20 @@ PLUGIN_SSE:
3131
VISIBILITIES:
3232
PUBLIC: Toot public
3333
UNLISTED: Toot non listé
34-
PRIVATE: Toot privé
34+
PRIVATE: Toot privé, à destination de vos abonné⋅e⋅s uniquement
3535
DIRECT: Message direct
3636
REBLOGS: $rbls boosts
3737
FAVOURITES: $favs favoris
38+
PLEROMA:
39+
CANNOT_RENDER: Impossible d'afficher le statut.
40+
VIEW_ON_MASTODON: (Cliquez pour le voir sur Pleroma.)
41+
REBLOGS: $rbls partages
42+
FAVOURITES: $favs mentions j'aime
43+
VISIBILITIES:
44+
PUBLIC: Statut public
45+
UNLISTED: Statut non listé
46+
PRIVATE: Statut à destination de vos abonné⋅e⋅s uniquement
47+
DIRECT: Message direct
3848
INSTAGRAM:
3949
CANNOT_RENDER: Impossible d'afficher la publication.
4050
VIEW_ON_INSTAGRAM: (Cliquez pour le voir sur Instagram.)

shortcodes/MastodonShortcode.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,30 @@ protected function getShortcodeName()
3636
*/
3737
protected function getData($url)
3838
{
39+
// First, we fetch the final URL after redirections.
40+
// Typically, Pleroma features objects links that will redirect to URLs with the status ID we need to
41+
// call the API.
42+
43+
$ch = curl_init();
44+
45+
curl_setopt_array($ch, [
46+
CURLOPT_URL => $url,
47+
CURLOPT_HEADER => true,
48+
CURLOPT_RETURNTRANSFER => true,
49+
CURLOPT_SSL_VERIFYPEER => false,
50+
CURLOPT_FOLLOWLOCATION => true,
51+
CURLOPT_MAXREDIRS => 256,
52+
CURLOPT_TIMEOUT => 3600,
53+
54+
// Required because Pleroma only redirects if we accept HTML content (else, we get an ActivityPub XML).
55+
CURLOPT_HTTPHEADER => [
56+
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
57+
]
58+
]);
59+
60+
curl_exec($ch);
61+
62+
$url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
3963
$purl = parse_url($url);
4064

4165
if ($purl === false)
@@ -47,8 +71,14 @@ protected function getData($url)
4771

4872
// From: https://mamot.fr/@ploum/100244825435451499
4973
// To: https://mamot.fr/api/v1/statuses/100244825435451499
74+
// - or -
75+
// From: https://weeaboo.space/notice/908080
76+
// To: https://weeaboo.space/api/v1/statuses/908080
77+
// - or -
78+
// From: https://mstdn.jp/users/Alumi/statuses/100355954289843928
79+
// To: https://mstdn.jp/api/v1/statuses/100355954289843928
5080
$api_endpoint = $purl['scheme'] . '://' . $purl['host'] . (isset($purl['port']) && $purl['port'] != 80 ? ':' . $purl['port'] : '');
51-
$api_endpoint .= '/api/v1/statuses/' . $path_parts[2];
81+
$api_endpoint .= '/api/v1/statuses/' . end($path_parts);
5282

5383
$ch = curl_init();
5484

@@ -76,6 +106,17 @@ protected function getData($url)
76106
$toot['account']['avatar'] = $this->fetchImage($toot['account']['avatar']);
77107
$toot['account']['fully_qualified_name'] = $toot['account']['username'] . '@' . $purl['host'] . (isset($purl['port']) && $purl['port'] != 80 ? ':' . $purl['port'] : '');
78108

109+
// Oh and Pleroma does not add <p> tags.
110+
111+
if (strpos($toot['content'], '<p>') !== 0)
112+
{
113+
$toot['content'] = '<p>' . $toot['content'] . '</p>';
114+
}
115+
116+
// While we're at it, let's store which federation this is from
117+
118+
$toot['federation_software'] = strpos($toot['uri'], 'objects') !== false ? 'pleroma' : 'mastodon';
119+
79120
// Process & store medias
80121

81122
if (isset($toot['media_attachments']))

templates/partials/static-social-embeds/toot.html.twig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<article class="static-social-embed sse-theme-{{ config.mastodon.theme }} sse-status sse-toot">
22
{% if errors %}
33
<div class="sse-status-error">
4-
<p>{{ 'PLUGIN_SSE.MASTODON.CANNOT_RENDER'|t }} <a href="{{ url }}">{{ 'PLUGIN_SSE.MASTODON.VIEW_ON_MASTODON'|t }}</a></p>
4+
<p>{{ ('PLUGIN_SSE.' ~ federation_software|upper ~ '.CANNOT_RENDER')|t }} <a href="{{ url }}">{{ ('PLUGIN_SSE.' ~ federation_software|upper ~ '.VIEW_ON_MASTODON')|t }}</a></p>
55
<ul>
66
{% for error in errors %}
77
<li>{{ error.code }}: {{ error.message }}</li>
@@ -105,7 +105,7 @@
105105
<li class="sse-mastodon-stats-date">
106106
<time datetime="{{ created_at|date('c') }}"><a href="{{ url }}">{{ created_at|date('PLUGIN_SSE.EMBEDS.DATE_FORMAT'|t) }}</a></time>
107107
</li>
108-
<li title="{{ ('PLUGIN_SSE.MASTODON.VISIBILITIES.' ~ visibility|upper)|t }}" class="sse-mastodon-stats-visibility">
108+
<li title="{{ ('PLUGIN_SSE.' ~ federation_software|upper ~ '.VISIBILITIES.' ~ visibility|upper)|t }}" class="sse-mastodon-stats-visibility">
109109
{%- set visibility_icons = {
110110
'public': 'fas fa-globe-africa',
111111
'unlisted': 'fas fa-unlock',
@@ -121,10 +121,10 @@
121121
{{- application.name -}}
122122
{%- endif -%}
123123
</li>
124-
<li aria-label="{{ 'PLUGIN_SSE.MASTODON.REBLOGS'|t|replace({'$rbls': reblogs_count}) }}" class="sse-mastodon-stats-reblogs">
124+
<li title="{{ ('PLUGIN_SSE.' ~ federation_software|upper ~ '.REBLOGS')|t|replace({'$rbls': reblogs_count}) }}" class="sse-mastodon-stats-reblogs">
125125
<span class="fas fa-retweet" aria-hidden="true"></span> {{ reblogs_count -}}
126126
</li>
127-
<li aria-label="{{ 'PLUGIN_SSE.MASTODON.FAVOURITES'|t|replace({'$favs': favourites_count}) }}" class="sse-mastodon-stats-favourites">
127+
<li title="{{ ('PLUGIN_SSE.' ~ federation_software|upper ~ '.FAVOURITES')|t|replace({'$favs': favourites_count}) }}" class="sse-mastodon-stats-favourites">
128128
<span class="fas fa-heart" aria-hidden="true"></span> {{ favourites_count -}}
129129
</li>
130130
</ul>

0 commit comments

Comments
 (0)