diff --git a/wp-content/plugins/activitypub/activitypub.php b/wp-content/plugins/activitypub/activitypub.php
index 6c170a0c..851d554c 100644
--- a/wp-content/plugins/activitypub/activitypub.php
+++ b/wp-content/plugins/activitypub/activitypub.php
@@ -3,7 +3,7 @@
* Plugin Name: ActivityPub
* Plugin URI: https://github.com/pfefferle/wordpress-activitypub/
* Description: The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format.
- * Version: 2.0.1
+ * Version: 2.2.0
* Author: Matthias Pfefferle & Automattic
* Author URI: https://automattic.com/
* License: MIT
@@ -33,7 +33,10 @@ require_once __DIR__ . '/includes/functions.php';
\defined( 'ACTIVITYPUB_CUSTOM_POST_CONTENT' ) || \define( 'ACTIVITYPUB_CUSTOM_POST_CONTENT', "[ap_title]\n\n[ap_content]\n\n[ap_hashtags]\n\n[ap_shortlink]" );
\defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) || \define( 'ACTIVITYPUB_AUTHORIZED_FETCH', false );
\defined( 'ACTIVITYPUB_DISABLE_REWRITES' ) || \define( 'ACTIVITYPUB_DISABLE_REWRITES', false );
+\defined( 'ACTIVITYPUB_DISABLE_INCOMING_INTERACTIONS' ) || \define( 'ACTIVITYPUB_DISABLE_INCOMING_INTERACTIONS', false );
+\defined( 'ACTIVITYPUB_DISABLE_OUTGOING_INTERACTIONS' ) || \define( 'ACTIVITYPUB_DISABLE_OUTGOING_INTERACTIONS', false );
\defined( 'ACTIVITYPUB_SHARED_INBOX_FEATURE' ) || \define( 'ACTIVITYPUB_SHARED_INBOX_FEATURE', false );
+\defined( 'ACTIVITYPUB_SEND_VARY_HEADER' ) || \define( 'ACTIVITYPUB_SEND_VARY_HEADER', false );
\define( 'ACTIVITYPUB_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
\define( 'ACTIVITYPUB_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
@@ -50,6 +53,7 @@ function rest_init() {
Rest\Followers::init();
Rest\Following::init();
Rest\Webfinger::init();
+ Rest\Comment::init();
Rest\Server::init();
Rest\Collection::init();
@@ -73,6 +77,7 @@ function plugin_init() {
\add_action( 'init', array( __NAMESPACE__ . '\Mention', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Health_Check', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Scheduler', 'init' ) );
+ \add_action( 'init', array( __NAMESPACE__ . '\Comment', 'init' ) );
if ( site_supports_blocks() ) {
\add_action( 'init', array( __NAMESPACE__ . '\Blocks', 'init' ) );
@@ -89,6 +94,9 @@ function plugin_init() {
require_once __DIR__ . '/integration/class-nodeinfo.php';
Integration\Nodeinfo::init();
+
+ require_once __DIR__ . '/integration/class-enable-mastodon-apps.php';
+ Integration\Enable_Mastodon_Apps::init();
}
\add_action( 'plugins_loaded', __NAMESPACE__ . '\plugin_init' );
@@ -111,7 +119,7 @@ function plugin_init() {
if ( false !== strpos( $class, '\\' ) ) {
$parts = explode( '\\', $class );
$class = array_pop( $parts );
- $sub_dir = implode( '/', $parts );
+ $sub_dir = strtr( implode( '/', $parts ), '_', '-' );
$base_dir = $base_dir . $sub_dir . '/';
}
diff --git a/wp-content/plugins/activitypub/build/follow-me/index.asset.php b/wp-content/plugins/activitypub/build/follow-me/index.asset.php
index eb992eab..ac15b343 100644
--- a/wp-content/plugins/activitypub/build/follow-me/index.asset.php
+++ b/wp-content/plugins/activitypub/build/follow-me/index.asset.php
@@ -1 +1 @@
- array( 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives' ), 'version' => '3ffce3edc6fed284bfbc' );
+ array('wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'c7c2319cdfac52a18445');
diff --git a/wp-content/plugins/activitypub/build/follow-me/index.js b/wp-content/plugins/activitypub/build/follow-me/index.js
index 96605cdb..d95484d4 100644
--- a/wp-content/plugins/activitypub/build/follow-me/index.js
+++ b/wp-content/plugins/activitypub/build/follow-me/index.js
@@ -1 +1 @@
-(()=>{"use strict";var e,t={454:(e,t,n)=>{const r=window.wp.blocks,o=window.wp.element,l=window.wp.primitives,a=(0,o.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,o.createElement)(l.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})),c=window.wp.blockEditor,i=window.wp.i18n,s=window.wp.components,u=window.wp.data,p=window._activityPubOptions?.enabled,m=window.wp.apiFetch;var d=n.n(m);const v=(0,o.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,o.createElement)(l.Path,{d:"M20.2 8v11c0 .7-.6 1.2-1.2 1.2H6v1.5h13c1.5 0 2.7-1.2 2.7-2.8V8zM18 16.4V4.6c0-.9-.7-1.6-1.6-1.6H4.6C3.7 3 3 3.7 3 4.6v11.8c0 .9.7 1.6 1.6 1.6h11.8c.9 0 1.6-.7 1.6-1.6zm-13.5 0V4.6c0-.1.1-.1.1-.1h11.8c.1 0 .1.1.1.1v11.8c0 .1-.1.1-.1.1H4.6l-.1-.1z"})),f=(0,o.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,o.createElement)(l.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})),w=function({icon:e,size:t=24,...n}){return(0,o.cloneElement)(e,{width:t,height:t,...n})},b=window.wp.compose;function y(e){return`var(--wp--preset--color--${e})`}function _(e){if("string"!=typeof e)return null;if(e.match(/^#/))return e.substring(0,7);const[,,t]=e.split("|");return y(t)}function h(e,t,n=null,r=""){return n?`${e}${r} { ${t}: ${n}; }\n`:""}function E(e,t,n,r){return h(e,"background-color",t)+h(e,"color",n)+h(e,"background-color",r,":hover")+h(e,"background-color",r,":focus")}function g({selector:e,style:t,backgroundColor:n}){const r=function(e,t,n){const r=`${e} .components-button`,o=("string"==typeof(l=n)?y(l):l?.color?.background||null)||t?.color?.background;var l;return E(r,_(t?.elements?.link?.color?.text),o,_(t?.elements?.link?.[":hover"]?.color?.text))}(e,t,n);return(0,o.createElement)("style",null,r)}const{namespace:k}=window._activityPubOptions,x={avatar:"",webfinger:"@well@hello.dolly",name:(0,i.__)("Hello Dolly Fan Account","activitypub"),url:"#"};function C(e){if(!e)return x;const t={...x,...e};return t.avatar=t?.icon?.url,t}function O({profile:e,popupStyles:t,userId:n}){const{avatar:r,name:l,webfinger:a}=e;return(0,o.createElement)("div",{className:"activitypub-profile"},(0,o.createElement)("img",{className:"activitypub-profile__avatar",src:r,alt:l}),(0,o.createElement)("div",{className:"activitypub-profile__content"},(0,o.createElement)("div",{className:"activitypub-profile__name"},l),(0,o.createElement)("div",{className:"activitypub-profile__handle",title:a},a)),(0,o.createElement)(S,{profile:e,popupStyles:t,userId:n}))}function S({profile:e,popupStyles:t,userId:n}){const[r,l]=(0,o.useState)(!1),a=(0,i.sprintf)((0,i.__)("Follow %s","activitypub"),e?.name);return(0,o.createElement)(o.Fragment,null,(0,o.createElement)(s.Button,{className:"activitypub-profile__follow",onClick:()=>l(!0)},(0,i.__)("Follow","activitypub")),r&&(0,o.createElement)(s.Modal,{className:"activitypub-profile__confirm",onRequestClose:()=>l(!1),title:a},(0,o.createElement)($,{profile:e,userId:n}),(0,o.createElement)("style",null,t)))}function N(e){try{return new URL(e),!0}catch(e){return!1}}function $({profile:e,userId:t}){const{webfinger:n}=e,r=(0,i.__)("Follow","activitypub"),l=(0,i.__)("Loading...","activitypub"),a=(0,i.__)("Opening...","activitypub"),c=(0,i.__)("Error","activitypub"),u=(0,i.__)("Invalid","activitypub"),[p,m]=(0,o.useState)(r),[y,_]=(0,o.useState)(v),h=(0,b.useCopyToClipboard)(n,(()=>{_(f),setTimeout((()=>_(v)),1e3)})),[E,g]=(0,o.useState)(""),x=(0,o.useCallback)((()=>{let e;if(!N(E)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&N(`https://${t[1]}`)}(E))return m(u),e=setTimeout((()=>m(r)),2e3),()=>clearTimeout(e);const n=`/${k}/users/${t}/remote-follow?resource=${E}`;m(l),d()({path:n}).then((({url:e})=>{m(a),setTimeout((()=>{window.open(e,"_blank"),m(r)}),200)})).catch((()=>{m(c),setTimeout((()=>m(r)),2e3)}))}),[E]);return(0,o.createElement)("div",{className:"activitypub-follow-me__dialog"},(0,o.createElement)("div",{className:"apmfd__section"},(0,o.createElement)("h4",null,(0,i.__)("My Profile","activitypub")),(0,o.createElement)("div",{className:"apfmd-description"},(0,i.__)("Copy and paste my profile into the search field of your favorite fediverse app or server.","activitypub")),(0,o.createElement)("div",{className:"apfmd__button-group"},(0,o.createElement)("input",{type:"text",value:n,readOnly:!0}),(0,o.createElement)(s.Button,{ref:h},(0,o.createElement)(w,{icon:y}),(0,i.__)("Copy","activitypub")))),(0,o.createElement)("div",{className:"apmfd__section"},(0,o.createElement)("h4",null,(0,i.__)("Your Profile","activitypub")),(0,o.createElement)("div",{className:"apfmd-description"},(0,o.createInterpolateElement)((0,i.__)("Or, if you know your own profile, we can start things that way! (eg https://example.com/yourusername or yourusername@example.com)","activitypub"),{code:(0,o.createElement)("code",null)})),(0,o.createElement)("div",{className:"apfmd__button-group"},(0,o.createElement)("input",{type:"text",value:E,onKeyDown:e=>{"Enter"===e?.code&&x()},onChange:e=>g(e.target.value)}),(0,o.createElement)(s.Button,{onClick:x},p))))}function z({selectedUser:e,style:t,backgroundColor:n,id:r,useId:l=!1,profileData:a=!1}){const[c,i]=(0,o.useState)(C()),s="site"===e?0:e,u=function(e){return E(".apfmd__button-group .components-button",_(e?.elements?.link?.color?.text)||"#111","#fff",_(e?.elements?.link?.[":hover"]?.color?.text)||"#333")}(t),p=l?{id:r}:{};function m(e){i(C(e))}return(0,o.useEffect)((()=>{if(a)return m(a);(function(e){const t={headers:{Accept:"application/activity+json"},path:`/${k}/users/${e}`};return d()(t)})(s).then(m)}),[s,a]),(0,o.createElement)("div",{...p},(0,o.createElement)(g,{selector:`#${r}`,style:t,backgroundColor:n}),(0,o.createElement)(O,{profile:c,userId:s,popupStyles:u}))}(0,r.registerBlockType)("activitypub/follow-me",{edit:function({attributes:e,setAttributes:t}){const n=(0,c.useBlockProps)({className:"activitypub-follow-me-block-wrapper"}),r=function(){const e=p?.users?(0,u.useSelect)((e=>e("core").getUsers({who:"authors"}))):[];return(0,o.useMemo)((()=>{if(!e)return[];const t=p?.site?[{label:(0,i.__)("Whole Site","activitypub"),value:"site"}]:[];return e.reduce(((e,t)=>(e.push({label:t.name,value:`${t.id}`}),e)),t)}),[e])}(),{selectedUser:l}=e;return(0,o.useEffect)((()=>{r.length&&(r.find((({value:e})=>e===l))||t({selectedUser:r[0].value}))}),[l,r]),(0,o.createElement)("div",{...n},r.length>1&&(0,o.createElement)(c.InspectorControls,{key:"setting"},(0,o.createElement)(s.PanelBody,{title:(0,i.__)("Followers Options","activitypub")},(0,o.createElement)(s.SelectControl,{label:(0,i.__)("Select User","activitypub"),value:e.selectedUser,options:r,onChange:e=>t({selectedUser:e})}))),(0,o.createElement)(z,{...e,id:n.id}))},save:()=>null,icon:a})}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var l=n[e]={exports:{}};return t[e](l,l.exports,r),l.exports}r.m=t,e=[],r.O=(t,n,o,l)=>{if(!n){var a=1/0;for(u=0;u=l)&&Object.keys(r.O).every((e=>r.O[e](n[i])))?n.splice(i--,1):(c=!1,l0&&e[u-1][2]>l;u--)e[u]=e[u-1];e[u]=[n,o,l]},r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={127:0,740:0};r.O.j=t=>0===e[t];var t=(t,n)=>{var o,l,a=n[0],c=n[1],i=n[2],s=0;if(a.some((t=>0!==e[t]))){for(o in c)r.o(c,o)&&(r.m[o]=c[o]);if(i)var u=i(r)}for(t&&t(n);sr(454)));o=r.O(o)})();
\ No newline at end of file
+(()=>{"use strict";var e,t={454:(e,t,n)=>{const o=window.wp.blocks,r=window.wp.element,l=window.wp.primitives,i=(0,r.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,r.createElement)(l.Path,{d:"M15.5 9.5a1 1 0 100-2 1 1 0 000 2zm0 1.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5zm-2.25 6v-2a2.75 2.75 0 00-2.75-2.75h-4A2.75 2.75 0 003.75 15v2h1.5v-2c0-.69.56-1.25 1.25-1.25h4c.69 0 1.25.56 1.25 1.25v2h1.5zm7-2v2h-1.5v-2c0-.69-.56-1.25-1.25-1.25H15v-1.5h2.5A2.75 2.75 0 0120.25 15zM9.5 8.5a1 1 0 11-2 0 1 1 0 012 0zm1.5 0a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z",fillRule:"evenodd"})),a=window.wp.blockEditor,c=window.wp.i18n,u=window.wp.components,s=window.wp.data,p=window._activityPubOptions?.enabled,v=window.wp.apiFetch;var m=n.n(v);const d=(0,r.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,r.createElement)(l.Path,{d:"M20.2 8v11c0 .7-.6 1.2-1.2 1.2H6v1.5h13c1.5 0 2.7-1.2 2.7-2.8V8zM18 16.4V4.6c0-.9-.7-1.6-1.6-1.6H4.6C3.7 3 3 3.7 3 4.6v11.8c0 .9.7 1.6 1.6 1.6h11.8c.9 0 1.6-.7 1.6-1.6zm-13.5 0V4.6c0-.1.1-.1.1-.1h11.8c.1 0 .1.1.1.1v11.8c0 .1-.1.1-.1.1H4.6l-.1-.1z"})),f=(0,r.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,r.createElement)(l.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})),b=function({icon:e,size:t=24,...n}){return(0,r.cloneElement)(e,{width:t,height:t,...n})},w=window.wp.compose;function y(e){return`var(--wp--preset--color--${e})`}function _(e){if("string"!=typeof e)return null;if(e.match(/^#/))return e.substring(0,7);const[,,t]=e.split("|");return y(t)}function h(e,t,n=null,o=""){return n?`${e}${o} { ${t}: ${n}; }\n`:""}function g(e,t,n,o){return h(e,"background-color",t)+h(e,"color",n)+h(e,"background-color",o,":hover")+h(e,"background-color",o,":focus")}function E({selector:e,style:t,backgroundColor:n}){const o=function(e,t,n){const o=`${e} .components-button`,r=("string"==typeof(l=n)?y(l):l?.color?.background||null)||t?.color?.background;var l;return g(o,_(t?.elements?.link?.color?.text),r,_(t?.elements?.link?.[":hover"]?.color?.text))}(e,t,n);return(0,r.createElement)("style",null,o)}const{namespace:k}=window._activityPubOptions,x={avatar:"",webfinger:"@well@hello.dolly",name:(0,c.__)("Hello Dolly Fan Account","activitypub"),url:"#"};function C(e){if(!e)return x;const t={...x,...e};return t.avatar=t?.icon?.url,t}function O({profile:e,popupStyles:t,userId:n}){const{avatar:o,name:l,webfinger:i}=e;return(0,r.createElement)("div",{className:"activitypub-profile"},(0,r.createElement)("img",{className:"activitypub-profile__avatar",src:o,alt:l}),(0,r.createElement)("div",{className:"activitypub-profile__content"},(0,r.createElement)("div",{className:"activitypub-profile__name"},l),(0,r.createElement)("div",{className:"activitypub-profile__handle",title:i},i)),(0,r.createElement)(S,{profile:e,popupStyles:t,userId:n}))}function S({profile:e,popupStyles:t,userId:n}){const[o,l]=(0,r.useState)(!1),i=(0,c.sprintf)((0,c.__)("Follow %s","activitypub"),e?.name);return(0,r.createElement)(r.Fragment,null,(0,r.createElement)(u.Button,{className:"activitypub-profile__follow",onClick:()=>l(!0)},(0,c.__)("Follow","activitypub")),o&&(0,r.createElement)(u.Modal,{className:"activitypub-profile__confirm activitypub__modal",onRequestClose:()=>l(!1),title:i},(0,r.createElement)($,{profile:e,userId:n}),(0,r.createElement)("style",null,t)))}function N(e){try{return new URL(e),!0}catch(e){return!1}}function $({profile:e,userId:t}){const{webfinger:n}=e,o=(0,c.__)("Follow","activitypub"),l=(0,c.__)("Loading...","activitypub"),i=(0,c.__)("Opening...","activitypub"),a=(0,c.__)("Error","activitypub"),s=(0,c.__)("Invalid","activitypub"),[p,v]=(0,r.useState)(o),[y,_]=(0,r.useState)(d),h=(0,w.useCopyToClipboard)(n,(()=>{_(f),setTimeout((()=>_(d)),1e3)})),[g,E]=(0,r.useState)(""),x=(0,r.useCallback)((()=>{let e;if(!N(g)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&N(`https://${t[1]}`)}(g))return v(s),e=setTimeout((()=>v(o)),2e3),()=>clearTimeout(e);const n=`/${k}/users/${t}/remote-follow?resource=${g}`;v(l),m()({path:n}).then((({url:e})=>{v(i),setTimeout((()=>{window.open(e,"_blank"),v(o)}),200)})).catch((()=>{v(a),setTimeout((()=>v(o)),2e3)}))}),[g]);return(0,r.createElement)("div",{className:"activitypub__dialog"},(0,r.createElement)("div",{className:"activitypub-dialog__section"},(0,r.createElement)("h4",null,(0,c.__)("My Profile","activitypub")),(0,r.createElement)("div",{className:"activitypub-dialog-description"},(0,c.__)("Copy and paste my profile into the search field of your favorite fediverse app or server.","activitypub")),(0,r.createElement)("div",{className:"activitypub-dialog__button-group"},(0,r.createElement)("input",{type:"text",value:n,readOnly:!0}),(0,r.createElement)(u.Button,{ref:h},(0,r.createElement)(b,{icon:y}),(0,c.__)("Copy","activitypub")))),(0,r.createElement)("div",{className:"activitypub-dialog__section"},(0,r.createElement)("h4",null,(0,c.__)("Your Profile","activitypub")),(0,r.createElement)("div",{className:"activitypub-dialog__description"},(0,r.createInterpolateElement)((0,c.__)("Or, if you know your own profile, we can start things that way! (eg https://example.com/yourusername or yourusername@example.com)","activitypub"),{code:(0,r.createElement)("code",null)})),(0,r.createElement)("div",{className:"activitypub-dialog__button-group"},(0,r.createElement)("input",{type:"text",value:g,onKeyDown:e=>{"Enter"===e?.code&&x()},onChange:e=>E(e.target.value)}),(0,r.createElement)(u.Button,{onClick:x},p))))}function z({selectedUser:e,style:t,backgroundColor:n,id:o,useId:l=!1,profileData:i=!1}){const[a,c]=(0,r.useState)(C()),u="site"===e?0:e,s=function(e){return g(".apfmd__button-group .components-button",_(e?.elements?.link?.color?.text)||"#111","#fff",_(e?.elements?.link?.[":hover"]?.color?.text)||"#333")}(t),p=l?{id:o}:{};function v(e){c(C(e))}return(0,r.useEffect)((()=>{if(i)return v(i);(function(e){const t={headers:{Accept:"application/activity+json"},path:`/${k}/users/${e}`};return m()(t)})(u).then(v)}),[u,i]),(0,r.createElement)("div",{...p},(0,r.createElement)(E,{selector:`#${o}`,style:t,backgroundColor:n}),(0,r.createElement)(O,{profile:a,userId:u,popupStyles:s}))}(0,o.registerBlockType)("activitypub/follow-me",{edit:function({attributes:e,setAttributes:t}){const n=(0,a.useBlockProps)({className:"activitypub-follow-me-block-wrapper"}),o=function(){const e=p?.users?(0,s.useSelect)((e=>e("core").getUsers({who:"authors"}))):[];return(0,r.useMemo)((()=>{if(!e)return[];const t=p?.site?[{label:(0,c.__)("Whole Site","activitypub"),value:"site"}]:[];return e.reduce(((e,t)=>(e.push({label:t.name,value:`${t.id}`}),e)),t)}),[e])}(),{selectedUser:l}=e;return(0,r.useEffect)((()=>{o.length&&(o.find((({value:e})=>e===l))||t({selectedUser:o[0].value}))}),[l,o]),(0,r.createElement)("div",{...n},o.length>1&&(0,r.createElement)(a.InspectorControls,{key:"setting"},(0,r.createElement)(u.PanelBody,{title:(0,c.__)("Followers Options","activitypub")},(0,r.createElement)(u.SelectControl,{label:(0,c.__)("Select User","activitypub"),value:e.selectedUser,options:o,onChange:e=>t({selectedUser:e})}))),(0,r.createElement)(z,{...e,id:n.id}))},save:()=>null,icon:i})}},n={};function o(e){var r=n[e];if(void 0!==r)return r.exports;var l=n[e]={exports:{}};return t[e](l,l.exports,o),l.exports}o.m=t,e=[],o.O=(t,n,r,l)=>{if(!n){var i=1/0;for(s=0;s=l)&&Object.keys(o.O).every((e=>o.O[e](n[c])))?n.splice(c--,1):(a=!1,l0&&e[s-1][2]>l;s--)e[s]=e[s-1];e[s]=[n,r,l]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={127:0,740:0};o.O.j=t=>0===e[t];var t=(t,n)=>{var r,l,i=n[0],a=n[1],c=n[2],u=0;if(i.some((t=>0!==e[t]))){for(r in a)o.o(a,r)&&(o.m[r]=a[r]);if(c)var s=c(o)}for(t&&t(n);uo(454)));r=o.O(r)})();
\ No newline at end of file
diff --git a/wp-content/plugins/activitypub/build/follow-me/style-index.css b/wp-content/plugins/activitypub/build/follow-me/style-index.css
index 7c6db77c..859950ec 100644
--- a/wp-content/plugins/activitypub/build/follow-me/style-index.css
+++ b/wp-content/plugins/activitypub/build/follow-me/style-index.css
@@ -1 +1 @@
-.activitypub-follow-me-block-wrapper{width:100%}.activitypub-follow-me-block-wrapper.has-background .activitypub-profile,.activitypub-follow-me-block-wrapper.has-border-color .activitypub-profile{padding-left:1rem;padding-right:1rem}.activitypub-follow-me-block-wrapper .activitypub-profile{align-items:center;display:flex;padding:1rem 0}.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__avatar{border-radius:50%;height:75px;margin-right:1rem;width:75px}.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__content{flex:1;min-width:0}.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__handle,.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__name{line-height:1.2;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__name{font-size:1.25em}.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__follow{align-self:center;background-color:var(--wp--preset--color--black);color:var(--wp--preset--color--white);margin-left:1rem}.activitypub-profile__confirm.components-modal__frame{background-color:#f7f7f7;color:#333}.activitypub-profile__confirm.components-modal__frame .components-modal__header-heading,.activitypub-profile__confirm.components-modal__frame h4{color:#333;letter-spacing:inherit;word-spacing:inherit}.activitypub-follow-me__dialog{max-width:30em}.activitypub-follow-me__dialog h4{line-height:1;margin:0}.activitypub-follow-me__dialog .apmfd__section{margin-bottom:2em}.activitypub-follow-me__dialog .apfmd-description{font-size:var(--wp--preset--font-size--normal,.75rem);margin:.33em 0 1em}.activitypub-follow-me__dialog .apfmd__button-group{align-items:flex-end;display:flex;justify-content:flex-end}.activitypub-follow-me__dialog .apfmd__button-group svg{height:21px;margin-right:.5em;width:21px}.activitypub-follow-me__dialog .apfmd__button-group input{background-color:var(--wp--preset--color--white);border:1px solid var(--wp--preset--color--black);color:var(--wp--preset--color--black);flex:1;padding:6px 12px}
+.activitypub-follow-me-block-wrapper{width:100%}.activitypub-follow-me-block-wrapper.has-background .activitypub-profile,.activitypub-follow-me-block-wrapper.has-border-color .activitypub-profile{padding-left:1rem;padding-right:1rem}.activitypub-follow-me-block-wrapper .activitypub-profile{align-items:center;display:flex;padding:1rem 0}.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__avatar{border-radius:50%;height:75px;margin-right:1rem;width:75px}.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__content{flex:1;min-width:0}.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__handle,.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__name{line-height:1.2;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__name{font-size:1.25em}.activitypub-follow-me-block-wrapper .activitypub-profile .activitypub-profile__follow{align-self:center;background-color:var(--wp--preset--color--black);color:var(--wp--preset--color--white);margin-left:1rem}.activitypub__modal.components-modal__frame{background-color:#f7f7f7;color:#333}.activitypub__modal.components-modal__frame .components-modal__header-heading,.activitypub__modal.components-modal__frame h4{color:#333;letter-spacing:inherit;word-spacing:inherit}.activitypub__modal.components-modal__frame .components-modal__header .components-button:hover{color:var(--wp--preset--color--white)}.activitypub__dialog{max-width:40em}.activitypub__dialog h4{line-height:1;margin:0}.activitypub__dialog .activitypub-dialog__section{margin-bottom:2em}.activitypub__dialog .activitypub-dialog__description{font-size:var(--wp--preset--font-size--normal,.75rem);margin:.33em 0 1em}.activitypub__dialog .activitypub-dialog__button-group{align-items:flex-end;display:flex;justify-content:flex-end}.activitypub__dialog .activitypub-dialog__button-group svg{height:21px;margin-right:.5em;width:21px}.activitypub__dialog .activitypub-dialog__button-group input{background-color:var(--wp--preset--color--white);border:1px solid var(--wp--preset--color--black);border-radius:inherit 0;color:var(--wp--preset--color--black);flex:1;padding:6px 12px}.activitypub__dialog .activitypub-dialog__button-group button{align-self:center;background-color:var(--wp--preset--color--black);color:var(--wp--preset--color--white);margin-left:0;text-decoration:none}
diff --git a/wp-content/plugins/activitypub/build/follow-me/view.asset.php b/wp-content/plugins/activitypub/build/follow-me/view.asset.php
index adf0ea1b..15d9b4ca 100644
--- a/wp-content/plugins/activitypub/build/follow-me/view.asset.php
+++ b/wp-content/plugins/activitypub/build/follow-me/view.asset.php
@@ -1 +1 @@
- array( 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives' ), 'version' => '40f3434fe6f953826373' );
+ array('wp-api-fetch', 'wp-components', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '1349fc90a3f33dde3595');
diff --git a/wp-content/plugins/activitypub/build/follow-me/view.js b/wp-content/plugins/activitypub/build/follow-me/view.js
index fd4e421c..a59d6bc4 100644
--- a/wp-content/plugins/activitypub/build/follow-me/view.js
+++ b/wp-content/plugins/activitypub/build/follow-me/view.js
@@ -1 +1 @@
-(()=>{"use strict";var e,t={703:(e,t,r)=>{const n=window.wp.element,o=window.wp.domReady;var a=r.n(o);const l=window.wp.apiFetch;var c=r.n(l);const i=window.wp.components,u=window.wp.i18n,s=window.wp.primitives,p=(0,n.createElement)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,n.createElement)(s.Path,{d:"M20.2 8v11c0 .7-.6 1.2-1.2 1.2H6v1.5h13c1.5 0 2.7-1.2 2.7-2.8V8zM18 16.4V4.6c0-.9-.7-1.6-1.6-1.6H4.6C3.7 3 3 3.7 3 4.6v11.8c0 .9.7 1.6 1.6 1.6h11.8c.9 0 1.6-.7 1.6-1.6zm-13.5 0V4.6c0-.1.1-.1.1-.1h11.8c.1 0 .1.1.1.1v11.8c0 .1-.1.1-.1.1H4.6l-.1-.1z"})),m=(0,n.createElement)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,n.createElement)(s.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})),d=function({icon:e,size:t=24,...r}){return(0,n.cloneElement)(e,{width:t,height:t,...r})},f=window.wp.compose;function v(e){return`var(--wp--preset--color--${e})`}function y(e){if("string"!=typeof e)return null;if(e.match(/^#/))return e.substring(0,7);const[,,t]=e.split("|");return v(t)}function w(e,t,r=null,n=""){return r?`${e}${n} { ${t}: ${r}; }\n`:""}function b(e,t,r,n){return w(e,"background-color",t)+w(e,"color",r)+w(e,"background-color",n,":hover")+w(e,"background-color",n,":focus")}function _({selector:e,style:t,backgroundColor:r}){const o=function(e,t,r){const n=`${e} .components-button`,o=("string"==typeof(a=r)?v(a):a?.color?.background||null)||t?.color?.background;var a;return b(n,y(t?.elements?.link?.color?.text),o,y(t?.elements?.link?.[":hover"]?.color?.text))}(e,t,r);return(0,n.createElement)("style",null,o)}const{namespace:h}=window._activityPubOptions,E={avatar:"",webfinger:"@well@hello.dolly",name:(0,u.__)("Hello Dolly Fan Account","activitypub"),url:"#"};function g(e){if(!e)return E;const t={...E,...e};return t.avatar=t?.icon?.url,t}function k({profile:e,popupStyles:t,userId:r}){const{avatar:o,name:a,webfinger:l}=e;return(0,n.createElement)("div",{className:"activitypub-profile"},(0,n.createElement)("img",{className:"activitypub-profile__avatar",src:o,alt:a}),(0,n.createElement)("div",{className:"activitypub-profile__content"},(0,n.createElement)("div",{className:"activitypub-profile__name"},a),(0,n.createElement)("div",{className:"activitypub-profile__handle",title:l},l)),(0,n.createElement)(x,{profile:e,popupStyles:t,userId:r}))}function x({profile:e,popupStyles:t,userId:r}){const[o,a]=(0,n.useState)(!1),l=(0,u.sprintf)((0,u.__)("Follow %s","activitypub"),e?.name);return(0,n.createElement)(n.Fragment,null,(0,n.createElement)(i.Button,{className:"activitypub-profile__follow",onClick:()=>a(!0)},(0,u.__)("Follow","activitypub")),o&&(0,n.createElement)(i.Modal,{className:"activitypub-profile__confirm",onRequestClose:()=>a(!1),title:l},(0,n.createElement)(C,{profile:e,userId:r}),(0,n.createElement)("style",null,t)))}function O(e){try{return new URL(e),!0}catch(e){return!1}}function C({profile:e,userId:t}){const{webfinger:r}=e,o=(0,u.__)("Follow","activitypub"),a=(0,u.__)("Loading...","activitypub"),l=(0,u.__)("Opening...","activitypub"),s=(0,u.__)("Error","activitypub"),v=(0,u.__)("Invalid","activitypub"),[y,w]=(0,n.useState)(o),[b,_]=(0,n.useState)(p),E=(0,f.useCopyToClipboard)(r,(()=>{_(m),setTimeout((()=>_(p)),1e3)})),[g,k]=(0,n.useState)(""),x=(0,n.useCallback)((()=>{let e;if(!O(g)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&O(`https://${t[1]}`)}(g))return w(v),e=setTimeout((()=>w(o)),2e3),()=>clearTimeout(e);const r=`/${h}/users/${t}/remote-follow?resource=${g}`;w(a),c()({path:r}).then((({url:e})=>{w(l),setTimeout((()=>{window.open(e,"_blank"),w(o)}),200)})).catch((()=>{w(s),setTimeout((()=>w(o)),2e3)}))}),[g]);return(0,n.createElement)("div",{className:"activitypub-follow-me__dialog"},(0,n.createElement)("div",{className:"apmfd__section"},(0,n.createElement)("h4",null,(0,u.__)("My Profile","activitypub")),(0,n.createElement)("div",{className:"apfmd-description"},(0,u.__)("Copy and paste my profile into the search field of your favorite fediverse app or server.","activitypub")),(0,n.createElement)("div",{className:"apfmd__button-group"},(0,n.createElement)("input",{type:"text",value:r,readOnly:!0}),(0,n.createElement)(i.Button,{ref:E},(0,n.createElement)(d,{icon:b}),(0,u.__)("Copy","activitypub")))),(0,n.createElement)("div",{className:"apmfd__section"},(0,n.createElement)("h4",null,(0,u.__)("Your Profile","activitypub")),(0,n.createElement)("div",{className:"apfmd-description"},(0,n.createInterpolateElement)((0,u.__)("Or, if you know your own profile, we can start things that way! (eg https://example.com/yourusername or yourusername@example.com)","activitypub"),{code:(0,n.createElement)("code",null)})),(0,n.createElement)("div",{className:"apfmd__button-group"},(0,n.createElement)("input",{type:"text",value:g,onKeyDown:e=>{"Enter"===e?.code&&x()},onChange:e=>k(e.target.value)}),(0,n.createElement)(i.Button,{onClick:x},y))))}function N({selectedUser:e,style:t,backgroundColor:r,id:o,useId:a=!1,profileData:l=!1}){const[i,u]=(0,n.useState)(g()),s="site"===e?0:e,p=function(e){return b(".apfmd__button-group .components-button",y(e?.elements?.link?.color?.text)||"#111","#fff",y(e?.elements?.link?.[":hover"]?.color?.text)||"#333")}(t),m=a?{id:o}:{};function d(e){u(g(e))}return(0,n.useEffect)((()=>{if(l)return d(l);(function(e){const t={headers:{Accept:"application/activity+json"},path:`/${h}/users/${e}`};return c()(t)})(s).then(d)}),[s,l]),(0,n.createElement)("div",{...m},(0,n.createElement)(_,{selector:`#${o}`,style:t,backgroundColor:r}),(0,n.createElement)(k,{profile:i,userId:s,popupStyles:p}))}let S=1;a()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-follow-me-block-wrapper"),(e=>{const t=JSON.parse(e.dataset.attrs);(0,n.render)((0,n.createElement)(N,{...t,id:"activitypub-follow-me-block-"+S++,useId:!0}),e)}))}))}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,n),a.exports}n.m=t,e=[],n.O=(t,r,o,a)=>{if(!r){var l=1/0;for(s=0;s=a)&&Object.keys(n.O).every((e=>n.O[e](r[i])))?r.splice(i--,1):(c=!1,a0&&e[s-1][2]>a;s--)e[s]=e[s-1];e[s]=[r,o,a]},n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={529:0,740:0};n.O.j=t=>0===e[t];var t=(t,r)=>{var o,a,l=r[0],c=r[1],i=r[2],u=0;if(l.some((t=>0!==e[t]))){for(o in c)n.o(c,o)&&(n.m[o]=c[o]);if(i)var s=i(n)}for(t&&t(r);un(703)));o=n.O(o)})();
\ No newline at end of file
+(()=>{"use strict";var e,t={703:(e,t,r)=>{const o=window.wp.element,n=window.wp.domReady;var a=r.n(n);const i=window.wp.apiFetch;var l=r.n(i);const c=window.wp.components,u=window.wp.i18n,s=window.wp.primitives,p=(0,o.createElement)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,o.createElement)(s.Path,{d:"M20.2 8v11c0 .7-.6 1.2-1.2 1.2H6v1.5h13c1.5 0 2.7-1.2 2.7-2.8V8zM18 16.4V4.6c0-.9-.7-1.6-1.6-1.6H4.6C3.7 3 3 3.7 3 4.6v11.8c0 .9.7 1.6 1.6 1.6h11.8c.9 0 1.6-.7 1.6-1.6zm-13.5 0V4.6c0-.1.1-.1.1-.1h11.8c.1 0 .1.1.1.1v11.8c0 .1-.1.1-.1.1H4.6l-.1-.1z"})),m=(0,o.createElement)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,o.createElement)(s.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})),d=function({icon:e,size:t=24,...r}){return(0,o.cloneElement)(e,{width:t,height:t,...r})},v=window.wp.compose;function f(e){return`var(--wp--preset--color--${e})`}function y(e){if("string"!=typeof e)return null;if(e.match(/^#/))return e.substring(0,7);const[,,t]=e.split("|");return f(t)}function b(e,t,r=null,o=""){return r?`${e}${o} { ${t}: ${r}; }\n`:""}function w(e,t,r,o){return b(e,"background-color",t)+b(e,"color",r)+b(e,"background-color",o,":hover")+b(e,"background-color",o,":focus")}function _({selector:e,style:t,backgroundColor:r}){const n=function(e,t,r){const o=`${e} .components-button`,n=("string"==typeof(a=r)?f(a):a?.color?.background||null)||t?.color?.background;var a;return w(o,y(t?.elements?.link?.color?.text),n,y(t?.elements?.link?.[":hover"]?.color?.text))}(e,t,r);return(0,o.createElement)("style",null,n)}const{namespace:h}=window._activityPubOptions,g={avatar:"",webfinger:"@well@hello.dolly",name:(0,u.__)("Hello Dolly Fan Account","activitypub"),url:"#"};function E(e){if(!e)return g;const t={...g,...e};return t.avatar=t?.icon?.url,t}function k({profile:e,popupStyles:t,userId:r}){const{avatar:n,name:a,webfinger:i}=e;return(0,o.createElement)("div",{className:"activitypub-profile"},(0,o.createElement)("img",{className:"activitypub-profile__avatar",src:n,alt:a}),(0,o.createElement)("div",{className:"activitypub-profile__content"},(0,o.createElement)("div",{className:"activitypub-profile__name"},a),(0,o.createElement)("div",{className:"activitypub-profile__handle",title:i},i)),(0,o.createElement)(x,{profile:e,popupStyles:t,userId:r}))}function x({profile:e,popupStyles:t,userId:r}){const[n,a]=(0,o.useState)(!1),i=(0,u.sprintf)((0,u.__)("Follow %s","activitypub"),e?.name);return(0,o.createElement)(o.Fragment,null,(0,o.createElement)(c.Button,{className:"activitypub-profile__follow",onClick:()=>a(!0)},(0,u.__)("Follow","activitypub")),n&&(0,o.createElement)(c.Modal,{className:"activitypub-profile__confirm activitypub__modal",onRequestClose:()=>a(!1),title:i},(0,o.createElement)(C,{profile:e,userId:r}),(0,o.createElement)("style",null,t)))}function O(e){try{return new URL(e),!0}catch(e){return!1}}function C({profile:e,userId:t}){const{webfinger:r}=e,n=(0,u.__)("Follow","activitypub"),a=(0,u.__)("Loading...","activitypub"),i=(0,u.__)("Opening...","activitypub"),s=(0,u.__)("Error","activitypub"),f=(0,u.__)("Invalid","activitypub"),[y,b]=(0,o.useState)(n),[w,_]=(0,o.useState)(p),g=(0,v.useCopyToClipboard)(r,(()=>{_(m),setTimeout((()=>_(p)),1e3)})),[E,k]=(0,o.useState)(""),x=(0,o.useCallback)((()=>{let e;if(!O(E)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&O(`https://${t[1]}`)}(E))return b(f),e=setTimeout((()=>b(n)),2e3),()=>clearTimeout(e);const r=`/${h}/users/${t}/remote-follow?resource=${E}`;b(a),l()({path:r}).then((({url:e})=>{b(i),setTimeout((()=>{window.open(e,"_blank"),b(n)}),200)})).catch((()=>{b(s),setTimeout((()=>b(n)),2e3)}))}),[E]);return(0,o.createElement)("div",{className:"activitypub__dialog"},(0,o.createElement)("div",{className:"activitypub-dialog__section"},(0,o.createElement)("h4",null,(0,u.__)("My Profile","activitypub")),(0,o.createElement)("div",{className:"activitypub-dialog-description"},(0,u.__)("Copy and paste my profile into the search field of your favorite fediverse app or server.","activitypub")),(0,o.createElement)("div",{className:"activitypub-dialog__button-group"},(0,o.createElement)("input",{type:"text",value:r,readOnly:!0}),(0,o.createElement)(c.Button,{ref:g},(0,o.createElement)(d,{icon:w}),(0,u.__)("Copy","activitypub")))),(0,o.createElement)("div",{className:"activitypub-dialog__section"},(0,o.createElement)("h4",null,(0,u.__)("Your Profile","activitypub")),(0,o.createElement)("div",{className:"activitypub-dialog__description"},(0,o.createInterpolateElement)((0,u.__)("Or, if you know your own profile, we can start things that way! (eg https://example.com/yourusername or yourusername@example.com)","activitypub"),{code:(0,o.createElement)("code",null)})),(0,o.createElement)("div",{className:"activitypub-dialog__button-group"},(0,o.createElement)("input",{type:"text",value:E,onKeyDown:e=>{"Enter"===e?.code&&x()},onChange:e=>k(e.target.value)}),(0,o.createElement)(c.Button,{onClick:x},y))))}function N({selectedUser:e,style:t,backgroundColor:r,id:n,useId:a=!1,profileData:i=!1}){const[c,u]=(0,o.useState)(E()),s="site"===e?0:e,p=function(e){return w(".apfmd__button-group .components-button",y(e?.elements?.link?.color?.text)||"#111","#fff",y(e?.elements?.link?.[":hover"]?.color?.text)||"#333")}(t),m=a?{id:n}:{};function d(e){u(E(e))}return(0,o.useEffect)((()=>{if(i)return d(i);(function(e){const t={headers:{Accept:"application/activity+json"},path:`/${h}/users/${e}`};return l()(t)})(s).then(d)}),[s,i]),(0,o.createElement)("div",{...m},(0,o.createElement)(_,{selector:`#${n}`,style:t,backgroundColor:r}),(0,o.createElement)(k,{profile:c,userId:s,popupStyles:p}))}let S=1;a()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-follow-me-block-wrapper"),(e=>{const t=JSON.parse(e.dataset.attrs);(0,o.render)((0,o.createElement)(N,{...t,id:"activitypub-follow-me-block-"+S++,useId:!0}),e)}))}))}},r={};function o(e){var n=r[e];if(void 0!==n)return n.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,o),a.exports}o.m=t,e=[],o.O=(t,r,n,a)=>{if(!r){var i=1/0;for(s=0;s=a)&&Object.keys(o.O).every((e=>o.O[e](r[c])))?r.splice(c--,1):(l=!1,a0&&e[s-1][2]>a;s--)e[s]=e[s-1];e[s]=[r,n,a]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={529:0,740:0};o.O.j=t=>0===e[t];var t=(t,r)=>{var n,a,i=r[0],l=r[1],c=r[2],u=0;if(i.some((t=>0!==e[t]))){for(n in l)o.o(l,n)&&(o.m[n]=l[n]);if(c)var s=c(o)}for(t&&t(r);uo(703)));n=o.O(n)})();
\ No newline at end of file
diff --git a/wp-content/plugins/activitypub/build/followers/index.asset.php b/wp-content/plugins/activitypub/build/followers/index.asset.php
index b4dda834..a6b5db01 100644
--- a/wp-content/plugins/activitypub/build/followers/index.asset.php
+++ b/wp-content/plugins/activitypub/build/followers/index.asset.php
@@ -1 +1 @@
- array( 'react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url' ), 'version' => 'c338a0364a63e21934ae' );
+ array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url'), 'version' => 'c338a0364a63e21934ae');
diff --git a/wp-content/plugins/activitypub/build/followers/view.asset.php b/wp-content/plugins/activitypub/build/followers/view.asset.php
index 50def18a..47972bbf 100644
--- a/wp-content/plugins/activitypub/build/followers/view.asset.php
+++ b/wp-content/plugins/activitypub/build/followers/view.asset.php
@@ -1 +1 @@
- array( 'react', 'wp-api-fetch', 'wp-components', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url' ), 'version' => 'ed5a13e66f8b10323435' );
+ array('react', 'wp-api-fetch', 'wp-components', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => 'ed5a13e66f8b10323435');
diff --git a/wp-content/plugins/activitypub/build/remote-reply/block.json b/wp-content/plugins/activitypub/build/remote-reply/block.json
new file mode 100644
index 00000000..b7d0b495
--- /dev/null
+++ b/wp-content/plugins/activitypub/build/remote-reply/block.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://schemas.wp.org/trunk/block.json",
+ "name": "activitypub/remote-reply",
+ "apiVersion": 3,
+ "version": "1.0.0",
+ "title": "Reply on the Fediverse",
+ "category": "widgets",
+ "description": "",
+ "textdomain": "activitypub",
+ "viewScript": "file:./index.js"
+}
\ No newline at end of file
diff --git a/wp-content/plugins/activitypub/build/remote-reply/index.asset.php b/wp-content/plugins/activitypub/build/remote-reply/index.asset.php
new file mode 100644
index 00000000..0e5d8d1a
--- /dev/null
+++ b/wp-content/plugins/activitypub/build/remote-reply/index.asset.php
@@ -0,0 +1 @@
+ array('wp-api-fetch', 'wp-components', 'wp-compose', 'wp-dom-ready', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => '0235743f089d22122d70');
diff --git a/wp-content/plugins/activitypub/build/remote-reply/index.js b/wp-content/plugins/activitypub/build/remote-reply/index.js
new file mode 100644
index 00000000..fa6d0e65
--- /dev/null
+++ b/wp-content/plugins/activitypub/build/remote-reply/index.js
@@ -0,0 +1 @@
+(()=>{"use strict";var e,t={664:(e,t,n)=>{const o=window.wp.element,a=window.wp.domReady;var i=n.n(a);const r=window.wp.apiFetch;var c=n.n(r);const l=window.wp.components,u=window.wp.i18n,s=window.wp.primitives,p=(0,o.createElement)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,o.createElement)(s.Path,{d:"M20.2 8v11c0 .7-.6 1.2-1.2 1.2H6v1.5h13c1.5 0 2.7-1.2 2.7-2.8V8zM18 16.4V4.6c0-.9-.7-1.6-1.6-1.6H4.6C3.7 3 3 3.7 3 4.6v11.8c0 .9.7 1.6 1.6 1.6h11.8c.9 0 1.6-.7 1.6-1.6zm-13.5 0V4.6c0-.1.1-.1.1-.1h11.8c.1 0 .1.1.1.1v11.8c0 .1-.1.1-.1.1H4.6l-.1-.1z"})),m=(0,o.createElement)(s.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},(0,o.createElement)(s.Path,{d:"M16.7 7.1l-6.3 8.5-3.3-2.5-.9 1.2 4.5 3.4L17.9 8z"})),d=function({icon:e,size:t=24,...n}){return(0,o.cloneElement)(e,{width:t,height:t,...n})},v=window.wp.compose,{namespace:y}=window._activityPubOptions;function _(e){try{return new URL(e),!0}catch(e){return!1}}function w({selectedComment:e,commentId:t}){const n=(0,u.__)("Reply","activitypub"),a=(0,u.__)("Loading...","activitypub"),i=(0,u.__)("Opening...","activitypub"),r=(0,u.__)("Error","activitypub"),s=(0,u.__)("Invalid","activitypub"),[w,b]=(0,o.useState)(n),[h,f]=(0,o.useState)(p),E=(0,v.useCopyToClipboard)(e,(()=>{f(m),setTimeout((()=>f(p)),1e3)})),[g,C]=(0,o.useState)(""),O=(0,o.useCallback)((()=>{let e;if(!_(g)&&!function(e){const t=e.replace(/^@/,"").split("@");return 2===t.length&&_(`https://${t[1]}`)}(g))return b(s),e=setTimeout((()=>b(n)),2e3),()=>clearTimeout(e);const o=`/${y}/comments/${t}/remote-reply?resource=${g}`;b(a),c()({path:o}).then((({url:e})=>{b(i),setTimeout((()=>{window.open(e,"_blank"),b(n)}),200)})).catch((()=>{b(r),setTimeout((()=>b(n)),2e3)}))}),[g]);return(0,o.createElement)("div",{className:"activitypub__dialog"},(0,o.createElement)("div",{className:"activitypub-dialog__section"},(0,o.createElement)("h4",null,(0,u.__)("The Comment-URL","activitypub")),(0,o.createElement)("div",{className:"activitypub-dialog__description"},(0,u.__)("Copy and paste the Comment-URL into the search field of your favorite fediverse app or server to reply to this Comment.","activitypub")),(0,o.createElement)("div",{className:"activitypub-dialog__button-group"},(0,o.createElement)("input",{type:"text",value:e,readOnly:!0}),(0,o.createElement)(l.Button,{ref:E},(0,o.createElement)(d,{icon:h}),(0,u.__)("Copy","activitypub")))),(0,o.createElement)("div",{className:"activitypub-dialog__section"},(0,o.createElement)("h4",null,(0,u.__)("Your Profile","activitypub")),(0,o.createElement)("div",{className:"activitypub-dialog__description"},(0,o.createInterpolateElement)((0,u.__)("Or, if you know your own profile, we can start things that way! (eg https://example.com/yourusername or yourusername@example.com)","activitypub"),{code:(0,o.createElement)("code",null)})),(0,o.createElement)("div",{className:"activitypub-dialog__button-group"},(0,o.createElement)("input",{type:"text",value:g,onKeyDown:e=>{"Enter"===e?.code&&O()},onChange:e=>C(e.target.value)}),(0,o.createElement)(l.Button,{onClick:O},w))))}function b({selectedComment:e,commentId:t}){const[n,a]=(0,o.useState)(!1),i=(0,u.__)("Remote Reply","activitypub");return(0,o.createElement)(o.Fragment,null,(0,o.createElement)(l.Button,{isLink:!0,className:"comment-reply-link activitypub-remote-reply__button",onClick:()=>a(!0)},(0,u.__)("Reply on the Fediverse","activitypub")),n&&(0,o.createElement)(l.Modal,{className:"activitypub-remote-reply__modal activitypub__modal",onRequestClose:()=>a(!1),title:i},(0,o.createElement)(w,{selectedComment:e,commentId:t})))}let h=1;i()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-remote-reply"),(e=>{const t=JSON.parse(e.dataset.attrs);(0,o.createRoot)(e).render((0,o.createElement)(b,{...t,id:"activitypub-remote-reply-link-"+h++,useId:!0}))}))}))}},n={};function o(e){var a=n[e];if(void 0!==a)return a.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,o),i.exports}o.m=t,e=[],o.O=(t,n,a,i)=>{if(!n){var r=1/0;for(s=0;s=i)&&Object.keys(o.O).every((e=>o.O[e](n[l])))?n.splice(l--,1):(c=!1,i0&&e[s-1][2]>i;s--)e[s]=e[s-1];e[s]=[n,a,i]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={805:0,881:0};o.O.j=t=>0===e[t];var t=(t,n)=>{var a,i,r=n[0],c=n[1],l=n[2],u=0;if(r.some((t=>0!==e[t]))){for(a in c)o.o(c,a)&&(o.m[a]=c[a]);if(l)var s=l(o)}for(t&&t(n);uo(664)));a=o.O(a)})();
\ No newline at end of file
diff --git a/wp-content/plugins/activitypub/build/remote-reply/style-index.css b/wp-content/plugins/activitypub/build/remote-reply/style-index.css
new file mode 100644
index 00000000..6f32a026
--- /dev/null
+++ b/wp-content/plugins/activitypub/build/remote-reply/style-index.css
@@ -0,0 +1 @@
+.activitypub__modal.components-modal__frame{background-color:#f7f7f7;color:#333}.activitypub__modal.components-modal__frame .components-modal__header-heading,.activitypub__modal.components-modal__frame h4{color:#333;letter-spacing:inherit;word-spacing:inherit}.activitypub__modal.components-modal__frame .components-modal__header .components-button:hover{color:var(--wp--preset--color--white)}.activitypub__dialog{max-width:40em}.activitypub__dialog h4{line-height:1;margin:0}.activitypub__dialog .activitypub-dialog__section{margin-bottom:2em}.activitypub__dialog .activitypub-dialog__description{font-size:var(--wp--preset--font-size--normal,.75rem);margin:.33em 0 1em}.activitypub__dialog .activitypub-dialog__button-group{align-items:flex-end;display:flex;justify-content:flex-end}.activitypub__dialog .activitypub-dialog__button-group svg{height:21px;margin-right:.5em;width:21px}.activitypub__dialog .activitypub-dialog__button-group input{background-color:var(--wp--preset--color--white);border:1px solid var(--wp--preset--color--black);border-radius:inherit 0;color:var(--wp--preset--color--black);flex:1;padding:6px 12px}.activitypub__dialog .activitypub-dialog__button-group button{align-self:center;background-color:var(--wp--preset--color--black);color:var(--wp--preset--color--white);margin-left:0;text-decoration:none}
diff --git a/wp-content/plugins/activitypub/includes/activity/class-activity.php b/wp-content/plugins/activitypub/includes/activity/class-activity.php
index dd698607..32aa3988 100644
--- a/wp-content/plugins/activitypub/includes/activity/class-activity.php
+++ b/wp-content/plugins/activitypub/includes/activity/class-activity.php
@@ -17,75 +17,15 @@ use Activitypub\Activity\Base_Object;
* @see https://www.w3.org/TR/activitystreams-core/#intransitiveactivities
*/
class Activity extends Base_Object {
- const CONTEXT = array(
+ const JSON_LD_CONTEXT = array(
'https://www.w3.org/ns/activitystreams',
- 'https://w3id.org/security/v1',
- 'https://purl.archive.org/socialweb/webfinger',
- array(
- 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
- 'PropertyValue' => 'schema:PropertyValue',
- 'schema' => 'http://schema.org#',
- 'pt' => 'https://joinpeertube.org/ns#',
- 'toot' => 'http://joinmastodon.org/ns#',
- 'litepub' => 'http://litepub.social/ns#',
- 'lemmy' => 'https://join-lemmy.org/ns#',
- 'value' => 'schema:value',
- 'Hashtag' => 'as:Hashtag',
- 'featured' => array(
- '@id' => 'toot:featured',
- '@type' => '@id',
- ),
- 'featuredTags' => array(
- '@id' => 'toot:featuredTags',
- '@type' => '@id',
- ),
- 'alsoKnownAs' => array(
- '@id' => 'as:alsoKnownAs',
- '@type' => '@id',
- ),
- 'moderators' => array(
- '@id' => 'lemmy:moderators',
- '@type' => '@id',
- ),
- 'postingRestrictedToMods' => 'lemmy:postingRestrictedToMods',
- 'discoverable' => 'toot:discoverable',
- 'indexable' => 'toot:indexable',
- 'sensitive' => 'as:sensitive',
- ),
);
- /**
- * The object's unique global identifier
- *
- * @see https://www.w3.org/TR/activitypub/#obj-id
- *
- * @var string
- */
- protected $id;
-
/**
* @var string
*/
protected $type = 'Activity';
- /**
- * The context within which the object exists or an activity was
- * performed.
- * The notion of "context" used is intentionally vague.
- * The intended function is to serve as a means of grouping objects
- * and activities that share a common originating context or
- * purpose. An example could be all activities relating to a common
- * project or event.
- *
- * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-context
- *
- * @var string
- * | ObjectType
- * | Link
- * | null
- */
- protected $context = self::CONTEXT;
-
/**
* Describes the direct object of the activity.
* For instance, in the activity "John added a movie to his
@@ -94,7 +34,7 @@ class Activity extends Base_Object {
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object-term
*
* @var string
- * | Base_Objectr
+ * | Base_Object
* | Link
* | null
*/
@@ -225,4 +165,21 @@ class Activity extends Base_Object {
$this->set( 'id', $object->get_id() . '#activity' );
}
}
+
+ /**
+ * The context of an Activity is usually just the context of the object it contains.
+ *
+ * @return array $context A compacted JSON-LD context.
+ */
+ public function get_json_ld_context() {
+ if ( $this->object instanceof Base_Object ) {
+ $class = get_class( $this->object );
+ if ( $class && $class::JSON_LD_CONTEXT ) {
+ // Without php 5.6 support this could be just: 'return $this->object::JSON_LD_CONTEXT;'
+ return $class::JSON_LD_CONTEXT;
+ }
+ }
+
+ return static::JSON_LD_CONTEXT;
+ }
}
diff --git a/wp-content/plugins/activitypub/includes/activity/class-actor.php b/wp-content/plugins/activitypub/includes/activity/class-actor.php
index fabd653c..1751aa29 100644
--- a/wp-content/plugins/activitypub/includes/activity/class-actor.php
+++ b/wp-content/plugins/activitypub/includes/activity/class-actor.php
@@ -16,6 +16,39 @@ namespace Activitypub\Activity;
* @see https://www.w3.org/TR/activitystreams-vocabulary/#actor-types
*/
class Actor extends Base_Object {
+ // Reduced context for actors. TODO: still unused.
+ const JSON_LD_CONTEXT = array(
+ 'https://www.w3.org/ns/activitystreams',
+ 'https://w3id.org/security/v1',
+ 'https://purl.archive.org/socialweb/webfinger',
+ array(
+ 'schema' => 'http://schema.org#',
+ 'toot' => 'http://joinmastodon.org/ns#',
+ 'webfinger' => 'https://webfinger.net/#',
+ 'lemmy' => 'https://join-lemmy.org/ns#',
+ 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
+ 'PropertyValue' => 'schema:PropertyValue',
+ 'value' => 'schema:value',
+ 'Hashtag' => 'as:Hashtag',
+ 'featured' => array(
+ '@id' => 'toot:featured',
+ '@type' => '@id',
+ ),
+ 'featuredTags' => array(
+ '@id' => 'toot:featuredTags',
+ '@type' => '@id',
+ ),
+ 'moderators' => array(
+ '@id' => 'lemmy:moderators',
+ '@type' => '@id',
+ ),
+ 'postingRestrictedToMods' => 'lemmy:postingRestrictedToMods',
+ 'discoverable' => 'toot:discoverable',
+ 'indexable' => 'toot:indexable',
+ 'resource' => 'webfinger:resource',
+ ),
+ );
+
/**
* @var string
*/
@@ -133,6 +166,8 @@ class Actor extends Base_Object {
*
* @see https://docs.joinmastodon.org/spec/activitypub/#as
*
+ * @context as:manuallyApprovesFollowers
+ *
* @var boolean
*/
protected $manually_approves_followers = false;
diff --git a/wp-content/plugins/activitypub/includes/activity/class-base-object.php b/wp-content/plugins/activitypub/includes/activity/class-base-object.php
index 1e256cbe..9a5cd3f8 100644
--- a/wp-content/plugins/activitypub/includes/activity/class-base-object.php
+++ b/wp-content/plugins/activitypub/includes/activity/class-base-object.php
@@ -9,6 +9,7 @@ namespace Activitypub\Activity;
use WP_Error;
use ReflectionClass;
+use DateTime;
use function Activitypub\camel_to_snake_case;
use function Activitypub\snake_to_camel_case;
@@ -26,6 +27,13 @@ use function Activitypub\snake_to_camel_case;
* @see https://www.w3.org/TR/activitystreams-core/#object
*/
class Base_Object {
+ const JSON_LD_CONTEXT = array(
+ 'https://www.w3.org/ns/activitystreams',
+ array(
+ 'Hashtag' => 'as:Hashtag',
+ ),
+ );
+
/**
* The object's unique global identifier
*
@@ -457,7 +465,7 @@ class Base_Object {
}
if ( \strncasecmp( $method, 'set', 3 ) === 0 ) {
- $this->set( $var, $params[0] );
+ return $this->set( $var, $params[0] );
}
if ( \strncasecmp( $method, 'add', 3 ) === 0 ) {
@@ -524,7 +532,7 @@ class Base_Object {
$this->$key = $value;
- return $this->$key;
+ return $this;
}
/**
@@ -622,9 +630,11 @@ class Base_Object {
* It tries to get the object attributes if they exist
* and falls back to the getters. Empty values are ignored.
*
+ * @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true.
+ *
* @return array An array built from the Object.
*/
- public function to_array() {
+ public function to_array( $include_json_ld_context = true ) {
$array = array();
$vars = get_object_vars( $this );
@@ -640,7 +650,7 @@ class Base_Object {
}
if ( is_object( $value ) ) {
- $value = $value->to_array();
+ $value = $value->to_array( false );
}
// if value is still empty, ignore it for the array and continue.
@@ -649,11 +659,9 @@ class Base_Object {
}
}
- // replace 'context' key with '@context' and move it to the top.
- if ( array_key_exists( 'context', $array ) ) {
- $context = $array['context'];
- unset( $array['context'] );
- $array = array_merge( array( '@context' => $context ), $array );
+ if ( $include_json_ld_context ) {
+ // Get JsonLD context and move it to '@context' at the top.
+ $array = array_merge( array( '@context' => $this->get_json_ld_context() ), $array );
}
$class = new ReflectionClass( $this );
@@ -668,10 +676,12 @@ class Base_Object {
/**
* Convert Object to JSON.
*
+ * @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true.
+ *
* @return string The JSON string.
*/
- public function to_json() {
- $array = $this->to_array();
+ public function to_json( $include_json_ld_context = true ) {
+ $array = $this->to_array( $include_json_ld_context );
$options = \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT;
/*
@@ -692,4 +702,13 @@ class Base_Object {
public function get_object_var_keys() {
return \array_keys( \get_object_vars( $this ) );
}
+
+ /**
+ * Returns the JSON-LD context of this object.
+ *
+ * @return array $context A compacted JSON-LD context for the ActivityPub object.
+ */
+ public function get_json_ld_context() {
+ return static::JSON_LD_CONTEXT;
+ }
}
diff --git a/wp-content/plugins/activitypub/includes/activity/extended-object/class-event.php b/wp-content/plugins/activitypub/includes/activity/extended-object/class-event.php
new file mode 100644
index 00000000..b0adb84f
--- /dev/null
+++ b/wp-content/plugins/activitypub/includes/activity/extended-object/class-event.php
@@ -0,0 +1,340 @@
+ 'https://joinpeertube.org/ns#',
+ 'mz' => 'https://joinmobilizon.org/ns#',
+ 'status' => 'http://www.w3.org/2002/12/cal/ical#status',
+ 'commentsEnabled' => 'pt:commentsEnabled',
+ 'isOnline' => 'mz:isOnline',
+ 'timezone' => 'mz:timezone',
+ 'participantCount' => 'mz:participantCount',
+ 'anonymousParticipationEnabled' => 'mz:anonymousParticipationEnabled',
+ 'joinMode' => array(
+ '@id' => 'mz:joinMode',
+ '@type' => 'mz:joinModeType',
+ ),
+ 'externalParticipationUrl' => array(
+ '@id' => 'mz:externalParticipationUrl',
+ '@type' => 'schema:URL',
+ ),
+ 'repliesModerationOption' => array(
+ '@id' => 'mz:repliesModerationOption',
+ '@type' => '@vocab',
+ ),
+ 'contacts' => array(
+ '@id' => 'mz:contacts',
+ '@type' => '@id',
+ ),
+ ),
+ );
+
+ /**
+ * Mobilizon compatible values for repliesModertaionOption.
+ * @var array
+ */
+ const REPLIES_MODERATION_OPTION_TYPES = array( 'allow_all', 'closed' );
+
+ /**
+ * Mobilizon compatible values for joinModeTypes.
+ */
+ const JOIN_MODE_TYPES = array( 'free', 'restricted', 'external' ); // and 'invite', but not used by mobilizon atm
+
+ /**
+ * Allowed values for ical VEVENT STATUS.
+ * @var array
+ */
+ const ICAL_EVENT_STATUS_TYPES = array( 'TENTATIVE', 'CONFIRMED', 'CANCELLED' );
+
+ /**
+ * Default event categories.
+ *
+ * These values currently reflect the default set as proposed by Mobilizon to maximize interoperability.
+ * @var array
+ */
+ const DEFAULT_EVENT_CATEGORIES = array(
+ 'ARTS',
+ 'BOOK_CLUBS',
+ 'BUSINESS',
+ 'CAUSES',
+ 'COMEDY',
+ 'CRAFTS',
+ 'FOOD_DRINK',
+ 'HEALTH',
+ 'MUSIC',
+ 'AUTO_BOAT_AIR',
+ 'COMMUNITY',
+ 'FAMILY_EDUCATION',
+ 'FASHION_BEAUTY',
+ 'FILM_MEDIA',
+ 'GAMES',
+ 'LANGUAGE_CULTURE',
+ 'LEARNING',
+ 'LGBTQ',
+ 'MOVEMENTS_POLITICS',
+ 'NETWORKING',
+ 'PARTY',
+ 'PERFORMING_VISUAL_ARTS',
+ 'PETS',
+ 'PHOTOGRAPHY',
+ 'OUTDOORS_ADVENTURE',
+ 'SPIRITUALITY_RELIGION_BELIEFS',
+ 'SCIENCE_TECH',
+ 'SPORTS',
+ 'THEATRE',
+ 'MEETING', // Default value.
+ );
+
+ /**
+ * Event is an implementation of one of the
+ * Activity Streams
+ *
+ * @var string
+ */
+ protected $type = 'Event';
+
+ /**
+ * The Title of the event.
+ */
+ protected $name;
+
+ /**
+ * The events contacts
+ *
+ * @context {
+ * '@id' => 'mz:contacts',
+ * '@type' => '@id',
+ * }
+ *
+ * @var array Array of contacts (ActivityPub actor IDs).
+ */
+ protected $contacts;
+
+ /**
+ * Extension invented by PeerTube whether comments/replies are
+ * Mobilizon also implemented this as a fallback to their own
+ * repliesModerationOption.
+ *
+ * @see https://docs.joinpeertube.org/api/activitypub#video
+ * @see https://docs.joinmobilizon.org/contribute/activity_pub/
+ * @var bool|null
+ */
+ protected $comments_enabled;
+
+ /**
+ * @context https://joinmobilizon.org/ns#timezone
+ * @var string
+ */
+ protected $timezone;
+
+ /**
+ * @context https://joinmobilizon.org/ns#repliesModerationOption
+ * @see https://docs.joinmobilizon.org/contribute/activity_pub/#repliesmoderation
+ * @var string
+ */
+ protected $replies_moderation_option;
+
+ /**
+ * @context https://joinmobilizon.org/ns#anonymousParticipationEnabled
+ * @see https://docs.joinmobilizon.org/contribute/activity_pub/#anonymousparticipationenabled
+ * @var bool
+ */
+ protected $anonymous_participation_enabled;
+
+ /**
+ * @context https://schema.org/category
+ * @var enum
+ */
+ protected $category;
+
+ /**
+ * @context https://schema.org/inLanguage
+ * @var
+ */
+ protected $in_language;
+
+ /**
+ * @context https://joinmobilizon.org/ns#isOnline
+ * @var bool
+ */
+ protected $is_online;
+
+ /**
+ * @context https://www.w3.org/2002/12/cal/ical#status
+ * @var enum
+ */
+ protected $status;
+
+ /**
+ * Which actor created the event.
+ *
+ * This field is needed due to the current group structure of Mobilizon.
+ *
+ * @todo this seems to not be a default property of an Object but needed by mobilizon.
+ * @var string
+ */
+ protected $actor;
+
+ /**
+ * @context https://joinmobilizon.org/ns#externalParticipationUrl
+ * @var string
+ */
+ protected $external_participation_url;
+
+ /**
+ * @context https://joinmobilizon.org/ns#joinMode
+ * @see https://docs.joinmobilizon.org/contribute/activity_pub/#joinmode
+ * @var
+ */
+ protected $join_mode;
+
+ /**
+ * @context https://joinmobilizon.org/ns#participantCount
+ * @var int
+ */
+ protected $participant_count;
+
+ /**
+ * @context https://schema.org/maximumAttendeeCapacity
+ * @see https://docs.joinmobilizon.org/contribute/activity_pub/#maximumattendeecapacity
+ * @var int
+ */
+ protected $maximum_attendee_capacity;
+
+ /**
+ * @context https://schema.org/remainingAttendeeCapacity
+ * @see https://docs.joinmobilizon.org/contribute/activity_pub/#remainignattendeecapacity
+ * @var int
+ */
+ protected $remaining_attendee_capacity;
+
+ /**
+ * Setter for the timezone.
+ *
+ * The passed timezone is only set when it is a valid one, otherwise the site's timezone is used.
+ *
+ * @param string $timezone The timezone string to be set, e.g. 'Europe/Berlin'.
+ */
+ public function set_timezone( $timezone ) {
+ if ( in_array( $timezone, timezone_identifiers_list(), true ) ) {
+ $this->timezone = $timezone;
+ } else {
+ $this->timezone = wp_timezone_string();
+ }
+
+ return $this;
+ }
+
+ /**
+ * Custom setter for repliesModerationOption which also directy sets commentsEnabled accordingly.
+ *
+ * @param string $type
+ */
+ public function set_replies_moderation_option( $type ) {
+ if ( in_array( $type, self::REPLIES_MODERATION_OPTION_TYPES, true ) ) {
+ $this->replies_moderation_option = $type;
+ $this->comments_enabled = ( 'allow_all' === $type ) ? true : false;
+ } else {
+ _doing_it_wrong(
+ __METHOD__,
+ 'The replies moderation option must be either allow_all or closed.',
+ ''
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Custom setter for commentsEnabled which also directly sets repliesModerationOption accordingly.
+ *
+ * @param bool $comments_enabled
+ */
+ public function set_comments_enabled( $comments_enabled ) {
+ if ( is_bool( $comments_enabled ) ) {
+ $this->comments_enabled = $comments_enabled;
+ $this->replies_moderation_option = $comments_enabled ? 'allow_all' : 'closed';
+ } else {
+ _doing_it_wrong(
+ __METHOD__,
+ 'The commentsEnabled must be boolean.',
+ ''
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Custom setter for the ical status that checks whether the status is an ical event status.
+ *
+ * @param string $status
+ */
+ public function set_status( $status ) {
+ if ( in_array( $status, self::ICAL_EVENT_STATUS_TYPES, true ) ) {
+ $this->status = $status;
+ } else {
+ _doing_it_wrong(
+ __METHOD__,
+ 'The status of the event must be a VEVENT iCal status.',
+ ''
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Custom setter for the event category.
+ *
+ * Falls back to Mobilizons default category.
+ *
+ * @param string $category
+ * @param bool $mobilizon_compatibilty Whether the category must be compatibly with Mobilizon.
+ */
+ public function set_category( $category, $mobilizon_compatibilty = true ) {
+ if ( $mobilizon_compatibilty ) {
+ $this->category = in_array( $category, self::DEFAULT_EVENT_CATEGORIES, true ) ? $category : 'MEETING';
+ } else {
+ $this->category = $category;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Custom setter for an external participation url.
+ *
+ * Automatically sets the joinMode to true if called.
+ *
+ * @param string $url
+ */
+ public function set_external_participation_url( $url ) {
+ if ( preg_match( '/^https?:\/\/.*/i', $url ) ) {
+ $this->external_participation_url = $url;
+ $this->join_mode = 'external';
+ }
+
+ return $this;
+ }
+}
diff --git a/wp-content/plugins/activitypub/includes/activity/extended-object/class-place.php b/wp-content/plugins/activitypub/includes/activity/extended-object/class-place.php
new file mode 100644
index 00000000..f84013df
--- /dev/null
+++ b/wp-content/plugins/activitypub/includes/activity/extended-object/class-place.php
@@ -0,0 +1,93 @@
+= 0.0f, <= 100.0f]
+ */
+ protected $accuracy;
+
+ /**
+ * Indicates the altitude of a place. The measurement units is indicated using the units property.
+ * If units is not specified, the default is assumed to be "m" indicating meters.
+ *
+ * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-altitude
+ * @var float xsd:float
+ */
+ protected $altitude;
+
+ /**
+ * The latitude of a place.
+ *
+ * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-latitude
+ * @var float xsd:float
+ */
+ protected $latitude;
+
+ /**
+ * The longitude of a place.
+ *
+ * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-longitude
+ * @var float xsd:float
+ */
+ protected $longitude;
+
+ /**
+ * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-radius
+ * @var float
+ */
+ protected $radius;
+
+ /**
+ * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-units
+ * @var string
+ */
+ protected $units;
+
+ /**
+ * @var Postal_Address|string
+ */
+ protected $address;
+
+ public function set_address( $address ) {
+ if ( is_string( $address ) || is_array( $address ) ) {
+ $this->address = $address;
+ } else {
+ _doing_it_wrong(
+ __METHOD__,
+ 'The address must be either a string or an array like schema.org/PostalAddress.',
+ ''
+ );
+ }
+ }
+}
diff --git a/wp-content/plugins/activitypub/includes/class-activity-dispatcher.php b/wp-content/plugins/activitypub/includes/class-activity-dispatcher.php
index 99aa9600..6278c669 100644
--- a/wp-content/plugins/activitypub/includes/class-activity-dispatcher.php
+++ b/wp-content/plugins/activitypub/includes/class-activity-dispatcher.php
@@ -13,6 +13,7 @@ use Activitypub\Transformer\Comment;
use function Activitypub\is_single_user;
use function Activitypub\is_user_disabled;
use function Activitypub\safe_remote_post;
+use function Activitypub\set_wp_object_state;
/**
* ActivityPub Activity_Dispatcher Class
@@ -26,6 +27,9 @@ class Activity_Dispatcher {
* Initialize the class, registering WordPress hooks.
*/
public static function init() {
+ \add_action( 'activitypub_send_post', array( self::class, 'send_post' ), 10, 2 );
+ \add_action( 'activitypub_send_comment', array( self::class, 'send_comment' ), 10, 2 );
+
\add_action( 'activitypub_send_activity', array( self::class, 'send_activity' ), 10, 2 );
\add_action( 'activitypub_send_activity', array( self::class, 'send_activity_or_announce' ), 10, 2 );
\add_action( 'activitypub_send_update_profile_activity', array( self::class, 'send_profile_update' ), 10, 1 );
@@ -77,7 +81,7 @@ class Activity_Dispatcher {
$activity = $transformer->to_activity( $type );
- self::send_activity_to_inboxes( $activity, $user_id );
+ self::send_activity_to_followers( $activity, $user_id, $wp_object );
}
/**
@@ -103,7 +107,7 @@ class Activity_Dispatcher {
$user_id = $transformer->get_wp_user_id();
$activity = $transformer->to_activity( 'Announce' );
- self::send_activity_to_inboxes( $activity, $user_id );
+ self::send_activity_to_followers( $activity, $user_id, $wp_object );
}
/**
@@ -130,18 +134,24 @@ class Activity_Dispatcher {
$activity->set_to( 'https://www.w3.org/ns/activitystreams#Public' );
// send the update
- self::send_activity_to_inboxes( $activity, $user_id );
+ self::send_activity_to_followers( $activity, $user_id, $user );
}
/**
* Send an Activity to all followers and mentioned users.
*
- * @param Activity $activity The ActivityPub Activity.
- * @param int $user_id The user ID.
+ * @param Activity $activity The ActivityPub Activity.
+ * @param int $user_id The user ID.
+ * @param WP_User|WP_Post|WP_Comment $wp_object The WordPress object.
*
* @return void
*/
- private static function send_activity_to_inboxes( $activity, $user_id ) {
+ private static function send_activity_to_followers( $activity, $user_id, $wp_object ) {
+ // check if the Activity should be send to the followers
+ if ( ! apply_filters( 'activitypub_send_activity_to_followers', true, $activity, $user_id, $wp_object ) ) {
+ return;
+ }
+
$follower_inboxes = Followers::get_inboxes( $user_id );
$mentioned_inboxes = array();
@@ -162,5 +172,57 @@ class Activity_Dispatcher {
foreach ( $inboxes as $inbox ) {
safe_remote_post( $inbox, $json, $user_id );
}
+
+ set_wp_object_state( $wp_object, 'federated' );
+ }
+
+ /**
+ * Send a "Create" or "Update" Activity for a WordPress Post.
+ *
+ * @param int $id The WordPress Post ID.
+ * @param string $type The Activity-Type.
+ *
+ * @return void
+ */
+ public static function send_post( $id, $type ) {
+ $post = get_post( $id );
+
+ if ( ! $post ) {
+ return;
+ }
+
+ do_action( 'activitypub_send_activity', $post, $type );
+ do_action(
+ sprintf(
+ 'activitypub_send_%s_activity',
+ \strtolower( $type )
+ ),
+ $post
+ );
+ }
+
+ /**
+ * Send a "Create" or "Update" Activity for a WordPress Comment.
+ *
+ * @param int $id The WordPress Comment ID.
+ * @param string $type The Activity-Type.
+ *
+ * @return void
+ */
+ public static function send_comment( $id, $type ) {
+ $comment = get_comment( $id );
+
+ if ( ! $comment ) {
+ return;
+ }
+
+ do_action( 'activitypub_send_activity', $comment, $type );
+ do_action(
+ sprintf(
+ 'activitypub_send_%s_activity',
+ \strtolower( $type )
+ ),
+ $comment
+ );
}
}
diff --git a/wp-content/plugins/activitypub/includes/class-activitypub.php b/wp-content/plugins/activitypub/includes/class-activitypub.php
index 535ab40e..1a13d2a2 100644
--- a/wp-content/plugins/activitypub/includes/class-activitypub.php
+++ b/wp-content/plugins/activitypub/includes/class-activitypub.php
@@ -6,9 +6,11 @@ use Activitypub\Signature;
use Activitypub\Collection\Users;
use Activitypub\Collection\Followers;
-use function Activitypub\sanitize_url;
use function Activitypub\is_comment;
+use function Activitypub\sanitize_url;
+use function Activitypub\is_local_comment;
use function Activitypub\is_activitypub_request;
+use function Activitypub\should_comment_be_federated;
/**
* ActivityPub Class
@@ -24,10 +26,9 @@ class Activitypub {
\add_action( 'template_redirect', array( self::class, 'template_redirect' ) );
\add_filter( 'query_vars', array( self::class, 'add_query_vars' ) );
\add_filter( 'pre_get_avatar_data', array( self::class, 'pre_get_avatar_data' ), 11, 2 );
- \add_filter( 'get_comment_link', array( self::class, 'remote_comment_link' ), 11, 3 );
// Add support for ActivityPub to custom post types
- $post_types = \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) ) ? \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) ) : array();
+ $post_types = \get_option( 'activitypub_support_post_types', array( 'post' ) ) ? \get_option( 'activitypub_support_post_types', array( 'post' ) ) : array();
foreach ( $post_types as $post_type ) {
\add_post_type_support( $post_type, 'activitypub' );
@@ -42,8 +43,6 @@ class Activitypub {
\add_action( 'in_plugin_update_message-' . ACTIVITYPUB_PLUGIN_BASENAME, array( self::class, 'plugin_update_message' ) );
- \add_filter( 'comment_class', array( self::class, 'comment_class' ), 10, 3 );
-
// register several post_types
self::register_post_types();
}
@@ -100,6 +99,11 @@ class Activitypub {
return $template;
}
+ // check if blog-user is enabled
+ if ( \is_home() && is_wp_error( Users::get_by_id( Users::BLOG_USER_ID ) ) ) {
+ return $template;
+ }
+
if ( \is_author() ) {
$json_template = ACTIVITYPUB_PLUGIN_DIR . '/templates/author-json.php';
} elseif ( is_comment() ) {
@@ -144,7 +148,7 @@ class Activitypub {
}
// stop if it's not an ActivityPub comment
- if ( is_activitypub_request() && $comment->user_id ) {
+ if ( is_activitypub_request() && ! is_local_comment( $comment ) ) {
return;
}
@@ -225,30 +229,6 @@ class Activitypub {
return \get_comment_meta( $comment->comment_ID, 'avatar_url', true );
}
- /**
- * Link remote comments to source url.
- *
- * @param string $comment_link
- * @param object|WP_Comment $comment
- *
- * @return string $url
- */
- public static function remote_comment_link( $comment_link, $comment ) {
- if ( ! $comment || is_admin() ) {
- return $comment_link;
- }
-
- $comment_meta = \get_comment_meta( $comment->comment_ID );
-
- if ( ! empty( $comment_meta['source_url'][0] ) ) {
- return $comment_meta['source_url'][0];
- } elseif ( ! empty( $comment_meta['source_id'][0] ) ) {
- return $comment_meta['source_id'][0];
- }
-
- return $comment_link;
- }
-
/**
* Store permalink in meta, to send delete Activity.
*
@@ -457,22 +437,4 @@ class Activitypub {
\do_action( 'activitypub_after_register_post_type' );
}
-
- /**
- * Filters the CSS classes to add an ActivityPub class.
- *
- * @param string[] $classes An array of comment classes.
- * @param string[] $css_class An array of additional classes added to the list.
- * @param string $comment_id The comment ID as a numeric string.
- *
- * @return string[] An array of classes.
- */
- public static function comment_class( $classes, $css_class, $comment_id ) {
- // check if ActivityPub comment
- if ( 'activitypub' === get_comment_meta( $comment_id, 'protocol', true ) ) {
- $classes[] = 'activitypub-comment';
- }
-
- return $classes;
- }
}
diff --git a/wp-content/plugins/activitypub/includes/class-admin.php b/wp-content/plugins/activitypub/includes/class-admin.php
index dca3aee7..9443a8bf 100644
--- a/wp-content/plugins/activitypub/includes/class-admin.php
+++ b/wp-content/plugins/activitypub/includes/class-admin.php
@@ -4,6 +4,10 @@ namespace Activitypub;
use WP_User_Query;
use Activitypub\Model\Blog_User;
+use function Activitypub\is_user_disabled;
+use function Activitypub\was_comment_received;
+use function Activitypub\is_comment_federatable;
+
/**
* ActivityPub Admin Class
*
@@ -16,9 +20,11 @@ class Admin {
public static function init() {
\add_action( 'admin_menu', array( self::class, 'admin_menu' ) );
\add_action( 'admin_init', array( self::class, 'register_settings' ) );
+ \add_action( 'load-comment.php', array( self::class, 'edit_comment' ) );
\add_action( 'personal_options_update', array( self::class, 'save_user_description' ) );
\add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_scripts' ) );
\add_action( 'admin_notices', array( self::class, 'admin_notices' ) );
+ \add_filter( 'comment_row_actions', array( self::class, 'comment_row_actions' ), 10, 2 );
if ( ! is_user_disabled( get_current_user_id() ) ) {
\add_action( 'show_user_profile', array( self::class, 'add_profile' ) );
@@ -193,7 +199,7 @@ class Admin {
'type' => 'string',
'description' => \esc_html__( 'Enable ActivityPub support for post types', 'activitypub' ),
'show_in_rest' => true,
- 'default' => array( 'post', 'pages' ),
+ 'default' => array( 'post' ),
)
);
\register_setting(
@@ -304,4 +310,40 @@ class Admin {
wp_enqueue_script( 'activitypub-admin-styles', plugins_url( 'assets/js/activitypub-admin.js', ACTIVITYPUB_PLUGIN_FILE ), array( 'jquery' ), '1.0.0', false );
}
}
+
+ /**
+ * Hook into the edit_comment functionality
+ *
+ * * Disable the edit_comment capability for federated comments.
+ *
+ * @return void
+ */
+ public static function edit_comment() {
+ // Disable the edit_comment capability for federated comments.
+ \add_filter(
+ 'user_has_cap',
+ function ( $allcaps, $caps, $arg ) {
+ if ( 'edit_comment' !== $arg[0] ) {
+ return $allcaps;
+ }
+
+ if ( was_comment_received( $arg[2] ) ) {
+ return false;
+ }
+
+ return $allcaps;
+ },
+ 1,
+ 3
+ );
+ }
+
+ public static function comment_row_actions( $actions, $comment ) {
+ if ( was_comment_received( $comment ) ) {
+ unset( $actions['edit'] );
+ unset( $actions['quickedit'] );
+ }
+
+ return $actions;
+ }
}
diff --git a/wp-content/plugins/activitypub/includes/class-blocks.php b/wp-content/plugins/activitypub/includes/class-blocks.php
index bd6549be..660dcce0 100644
--- a/wp-content/plugins/activitypub/includes/class-blocks.php
+++ b/wp-content/plugins/activitypub/includes/class-blocks.php
@@ -78,6 +78,12 @@ class Blocks {
array( 'icon', 'name', 'webfinger' )
);
}
+
+ // add `@` prefix if it's missing
+ if ( '@' !== substr( $attrs['profileData']['webfinger'], 0, 1 ) ) {
+ $attrs['profileData']['webfinger'] = '@' . $attrs['profileData']['webfinger'];
+ }
+
$wrapper_attributes = get_block_wrapper_attributes(
array(
'aria-label' => __( 'Follow me on the Fediverse', 'activitypub' ),
diff --git a/wp-content/plugins/activitypub/includes/class-comment.php b/wp-content/plugins/activitypub/includes/class-comment.php
new file mode 100644
index 00000000..317316b6
--- /dev/null
+++ b/wp-content/plugins/activitypub/includes/class-comment.php
@@ -0,0 +1,384 @@
+ self::generate_id( $comment ),
+ 'commentId' => $comment->comment_ID,
+ );
+
+ $div = sprintf(
+ '',
+ esc_attr( wp_json_encode( $attrs ) )
+ );
+
+ return apply_filters( 'activitypub_comment_reply_link', $div );
+ }
+
+ /**
+ * Check if it is allowed to comment to a comment.
+ *
+ * Checks if the comment is local only or if the user can comment federated comments.
+ *
+ * @param mixed $comment Comment object or ID.
+ *
+ * @return boolean True if the user can comment, false otherwise.
+ */
+ public static function are_comments_allowed( $comment ) {
+ $comment = \get_comment( $comment );
+
+ if ( ! self::was_received( $comment ) ) {
+ return true;
+ }
+
+ $current_user = get_current_user_id();
+
+ if ( ! $current_user ) {
+ return false;
+ }
+
+ $is_user_disabled = is_user_disabled( $current_user );
+
+ if ( $is_user_disabled ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if a comment is federated.
+ *
+ * We consider a comment federated if comment was received via ActivityPub.
+ *
+ * Use this function to check if it is comment that was received via ActivityPub.
+ *
+ * @param mixed $comment Comment object or ID.
+ *
+ * @return boolean True if the comment is federated, false otherwise.
+ */
+ public static function was_received( $comment ) {
+ $comment = \get_comment( $comment );
+
+ if ( ! $comment ) {
+ return false;
+ }
+
+ $protocol = \get_comment_meta( $comment->comment_ID, 'protocol', true );
+
+ if ( 'activitypub' === $protocol ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Check if a comment was federated.
+ *
+ * This function checks if a comment was federated via ActivityPub.
+ *
+ * @param mixed $comment Comment object or ID.
+ *
+ * @return boolean True if the comment was federated, false otherwise.
+ */
+ public static function was_sent( $comment ) {
+ $comment = \get_comment( $comment );
+
+ if ( ! $comment ) {
+ return false;
+ }
+
+ $status = \get_comment_meta( $comment->comment_ID, 'activitypub_status', true );
+
+ if ( $status ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Check if a comment is local only.
+ *
+ * This function checks if a comment is local only and was not sent or received via ActivityPub.
+ *
+ * @param mixed $comment Comment object or ID.
+ *
+ * @return boolean True if the comment is local only, false otherwise.
+ */
+ public static function is_local( $comment ) {
+ if ( self::was_sent( $comment ) || self::was_received( $comment ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if a comment should be federated.
+ *
+ * We consider a comment should be federated if it is authored by a user that is
+ * not disabled for federation and if it is a reply directly to the post or to a
+ * federated comment.
+ *
+ * Use this function to check if a comment should be federated.
+ *
+ * @param mixed $comment Comment object or ID.
+ *
+ * @return boolean True if the comment should be federated, false otherwise.
+ */
+ public static function should_be_federated( $comment ) {
+ // we should not federate federated comments
+ if ( self::was_received( $comment ) ) {
+ return false;
+ }
+
+ $comment = \get_comment( $comment );
+ $user_id = $comment->user_id;
+
+ // comments without user can't be federated
+ if ( ! $user_id ) {
+ return false;
+ }
+
+ $is_user_disabled = is_user_disabled( $user_id );
+
+ // user is disabled for federation
+ if ( $is_user_disabled ) {
+ return false;
+ }
+
+ // it is a comment to the post and can be federated
+ if ( empty( $comment->comment_parent ) ) {
+ return true;
+ }
+
+ // check if parent comment is federated
+ $parent_comment = \get_comment( $comment->comment_parent );
+
+ return ! self::is_local( $parent_comment );
+ }
+
+ /**
+ * Examine a comment ID and look up an existing comment it represents.
+ *
+ * @param string $id ActivityPub object ID (usually a URL) to check.
+ *
+ * @return int|boolean Comment ID, or false on failure.
+ */
+ public static function object_id_to_comment( $id ) {
+ $comment_query = new WP_Comment_Query(
+ array(
+ 'meta_key' => 'source_id', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
+ 'meta_value' => $id, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
+ )
+ );
+
+ if ( ! $comment_query->comments ) {
+ return false;
+ }
+
+ if ( count( $comment_query->comments ) > 1 ) {
+ return false;
+ }
+
+ return $comment_query->comments[0];
+ }
+
+ /**
+ * Verify if URL is a local comment, or if it is a previously received
+ * remote comment (For threading comments locally)
+ *
+ * @param string $url The URL to check.
+ *
+ * @return int comment_ID or null if not found
+ */
+ public static function url_to_commentid( $url ) {
+ if ( ! $url || ! filter_var( $url, \FILTER_VALIDATE_URL ) ) {
+ return null;
+ }
+
+ // check for local comment
+ if ( \wp_parse_url( \site_url(), \PHP_URL_HOST ) === \wp_parse_url( $url, \PHP_URL_HOST ) ) {
+ $query = \wp_parse_url( $url, \PHP_URL_QUERY );
+
+ if ( $query ) {
+ parse_str( $query, $params );
+
+ if ( ! empty( $params['c'] ) ) {
+ $comment = \get_comment( $params['c'] );
+
+ if ( $comment ) {
+ return $comment->comment_ID;
+ }
+ }
+ }
+ }
+
+ $args = array(
+ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
+ 'meta_query' => array(
+ 'relation' => 'OR',
+ array(
+ 'key' => 'source_url',
+ 'value' => $url,
+ ),
+ array(
+ 'key' => 'source_id',
+ 'value' => $url,
+ ),
+ ),
+ );
+
+ $query = new WP_Comment_Query();
+ $comments = $query->query( $args );
+
+ if ( $comments && is_array( $comments ) ) {
+ return $comments[0]->comment_ID;
+ }
+
+ return null;
+ }
+
+ /**
+ * Filters the CSS classes to add an ActivityPub class.
+ *
+ * @param string[] $classes An array of comment classes.
+ * @param string[] $css_class An array of additional classes added to the list.
+ * @param string $comment_id The comment ID as a numeric string.
+ *
+ * @return string[] An array of classes.
+ */
+ public static function comment_class( $classes, $css_class, $comment_id ) {
+ // check if ActivityPub comment
+ if ( 'activitypub' === get_comment_meta( $comment_id, 'protocol', true ) ) {
+ $classes[] = 'activitypub-comment';
+ }
+
+ return $classes;
+ }
+
+ /**
+ * Link remote comments to source url.
+ *
+ * @param string $comment_link
+ * @param object|WP_Comment $comment
+ *
+ * @return string $url
+ */
+ public static function remote_comment_link( $comment_link, $comment ) {
+ if ( ! $comment || is_admin() ) {
+ return $comment_link;
+ }
+
+ $comment_meta = \get_comment_meta( $comment->comment_ID );
+
+ if ( ! empty( $comment_meta['source_url'][0] ) ) {
+ return $comment_meta['source_url'][0];
+ } elseif ( ! empty( $comment_meta['source_id'][0] ) ) {
+ return $comment_meta['source_id'][0];
+ }
+
+ return $comment_link;
+ }
+
+
+ /**
+ * Generates an ActivityPub URI for a comment
+ *
+ * @param WP_Comment|int $comment A comment object or comment ID
+ *
+ * @return string ActivityPub URI for comment
+ */
+ public static function generate_id( $comment ) {
+ $comment = get_comment( $comment );
+
+ // show external comment ID if it exists
+ $source_id = get_comment_meta( $comment->comment_ID, 'source_id', true );
+ if ( ! empty( $source_id ) ) {
+ return $source_id;
+ }
+
+ // generate URI based on comment ID
+ return \add_query_arg(
+ array(
+ 'c' => $comment->comment_ID,
+ ),
+ \trailingslashit( site_url() )
+ );
+ }
+
+ /**
+ * Enqueue scripts for remote comments
+ */
+ public static function enqueue_scripts() {
+ if ( ! is_singular() ) {
+ return;
+ }
+ $handle = 'activitypub-remote-reply';
+ $data = array(
+ 'namespace' => ACTIVITYPUB_REST_NAMESPACE,
+ );
+ $js = sprintf( 'var _activityPubOptions = %s;', wp_json_encode( $data ) );
+ $asset_file = ACTIVITYPUB_PLUGIN_DIR . 'build/remote-reply/index.asset.php';
+
+ if ( \file_exists( $asset_file ) ) {
+ $assets = require_once $asset_file;
+
+ \wp_enqueue_script(
+ $handle,
+ \plugins_url( 'build/remote-reply/index.js', __DIR__ ),
+ $assets['dependencies'],
+ $assets['version'],
+ true
+ );
+ \wp_add_inline_script( $handle, $js, 'before' );
+
+ \wp_enqueue_style(
+ $handle,
+ \plugins_url( 'build/remote-reply/style-index.css', __DIR__ ),
+ [ 'wp-components' ],
+ $assets['version']
+ );
+ }
+ }
+}
diff --git a/wp-content/plugins/activitypub/includes/class-debug.php b/wp-content/plugins/activitypub/includes/class-debug.php
index 36f8bda5..bdb84c68 100644
--- a/wp-content/plugins/activitypub/includes/class-debug.php
+++ b/wp-content/plugins/activitypub/includes/class-debug.php
@@ -14,11 +14,12 @@ class Debug {
* Initialize the class, registering WordPress hooks
*/
public static function init() {
- if ( WP_DEBUG && WP_DEBUG_LOG ) {
+ if ( WP_DEBUG_LOG ) {
\add_action( 'activitypub_safe_remote_post_response', array( self::class, 'log_remote_post_responses' ), 10, 4 );
}
}
+ // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
public static function log_remote_post_responses( $response, $url, $body, $user_id ) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log, WordPress.PHP.DevelopmentFunctions.error_log_print_r
\error_log( "Request to: {$url} with response: " . \print_r( $response, true ) );
diff --git a/wp-content/plugins/activitypub/includes/class-mention.php b/wp-content/plugins/activitypub/includes/class-mention.php
index 0b8c0b5e..fee01b20 100644
--- a/wp-content/plugins/activitypub/includes/class-mention.php
+++ b/wp-content/plugins/activitypub/includes/class-mention.php
@@ -102,7 +102,7 @@ class Mention {
$username = $metadata['preferredUsername'];
}
- $url = isset( $metadata['url'] ) ? $metadata['url'] : $metadata['url'];
+ $url = isset( $metadata['url'] ) ? $metadata['url'] : $metadata['id'];
if ( \is_array( $url ) ) {
$url = $url[0];
diff --git a/wp-content/plugins/activitypub/includes/class-migration.php b/wp-content/plugins/activitypub/includes/class-migration.php
index adebb7e9..5c57f4e9 100644
--- a/wp-content/plugins/activitypub/includes/class-migration.php
+++ b/wp-content/plugins/activitypub/includes/class-migration.php
@@ -117,6 +117,9 @@ class Migration {
if ( version_compare( $version_from_db, '1.3.0', '<' ) ) {
self::migrate_from_1_2_0();
}
+ if ( version_compare( $version_from_db, '2.1.0', '<' ) ) {
+ self::migrate_from_2_0_0();
+ }
update_option( 'activitypub_db_version', self::get_target_version() );
@@ -197,4 +200,19 @@ class Migration {
wp_cache_delete( sprintf( Followers::CACHE_KEY_INBOXES, $user_id ), 'activitypub' );
}
}
+
+ /**
+ * Unschedule Hooks after updating to 2.0.0
+ *
+ * @return void
+ */
+ private static function migrate_from_2_0_0() {
+ wp_clear_scheduled_hook( 'activitypub_send_post_activity' );
+ wp_clear_scheduled_hook( 'activitypub_send_update_activity' );
+ wp_clear_scheduled_hook( 'activitypub_send_delete_activity' );
+
+ wp_unschedule_hook( 'activitypub_send_post_activity' );
+ wp_unschedule_hook( 'activitypub_send_update_activity' );
+ wp_unschedule_hook( 'activitypub_send_delete_activity' );
+ }
}
diff --git a/wp-content/plugins/activitypub/includes/class-scheduler.php b/wp-content/plugins/activitypub/includes/class-scheduler.php
index 1a05f49f..0db5fe9f 100644
--- a/wp-content/plugins/activitypub/includes/class-scheduler.php
+++ b/wp-content/plugins/activitypub/includes/class-scheduler.php
@@ -2,11 +2,14 @@
namespace Activitypub;
+use Activitypub\Transformer\Post;
use Activitypub\Collection\Users;
use Activitypub\Collection\Followers;
-use Activitypub\Transformer\Post;
+use function Activitypub\was_comment_sent;
use function Activitypub\is_user_type_disabled;
+use function Activitypub\should_comment_be_federated;
+use function Activitypub\get_remote_metadata_by_actor;
/**
* ActivityPub Scheduler Class
@@ -40,20 +43,22 @@ class Scheduler {
}
);
- // Comment transitions
- \add_action( 'transition_comment_status', array( self::class, 'schedule_comment_activity' ), 20, 3 );
- \add_action(
- 'edit_comment',
- function ( $comment_id ) {
- self::schedule_comment_activity( 'approved', 'approved', $comment_id );
- }
- );
- \add_action(
- 'wp_insert_comment',
- function ( $comment_id ) {
- self::schedule_comment_activity( 'approved', '', $comment_id );
- }
- );
+ if ( ! ACTIVITYPUB_DISABLE_OUTGOING_INTERACTIONS ) {
+ // Comment transitions
+ \add_action( 'transition_comment_status', array( self::class, 'schedule_comment_activity' ), 20, 3 );
+ \add_action(
+ 'edit_comment',
+ function ( $comment_id ) {
+ self::schedule_comment_activity( 'approved', 'approved', $comment_id );
+ }
+ );
+ \add_action(
+ 'wp_insert_comment',
+ function ( $comment_id ) {
+ self::schedule_comment_activity( 'approved', '', $comment_id );
+ }
+ );
+ }
// Follower Cleanups
\add_action( 'activitypub_update_followers', array( self::class, 'update_followers' ) );
@@ -136,24 +141,17 @@ class Scheduler {
$type = 'Delete';
}
- if ( ! $type ) {
+ if ( empty( $type ) ) {
return;
}
- \wp_schedule_single_event(
- \time(),
- 'activitypub_send_activity',
- array( $post, $type )
- );
+ $hook = 'activitypub_send_post';
+ $args = array( $post->ID, $type );
- \wp_schedule_single_event(
- \time(),
- sprintf(
- 'activitypub_send_%s_activity',
- \strtolower( $type )
- ),
- array( $post )
- );
+ if ( false === wp_next_scheduled( $hook, $args ) ) {
+ set_wp_object_state( $post, 'federate' );
+ \wp_schedule_single_event( \time(), $hook, $args );
+ }
}
/**
@@ -168,11 +166,13 @@ class Scheduler {
public static function schedule_comment_activity( $new_status, $old_status, $comment ) {
$comment = get_comment( $comment );
- // Federate only approved comments.
+ // federate only comments that are written by a registered user.
if ( ! $comment->user_id ) {
return;
}
+ $type = false;
+
if (
'approved' === $new_status &&
'approved' !== $old_status
@@ -188,24 +188,22 @@ class Scheduler {
$type = 'Delete';
}
- if ( ! $type ) {
+ if ( empty( $type ) ) {
return;
}
- \wp_schedule_single_event(
- \time(),
- 'activitypub_send_activity',
- array( $comment, $type )
- );
+ // check if comment should be federated or not
+ if ( ! should_comment_be_federated( $comment ) ) {
+ return;
+ }
- \wp_schedule_single_event(
- \time(),
- sprintf(
- 'activitypub_send_%s_activity',
- \strtolower( $type )
- ),
- array( $comment )
- );
+ $hook = 'activitypub_send_comment';
+ $args = array( $comment->comment_ID, $type );
+
+ if ( false === wp_next_scheduled( $hook, $args ) ) {
+ set_wp_object_state( $comment, 'federate' );
+ \wp_schedule_single_event( \time(), $hook, $args );
+ }
}
/**
@@ -220,6 +218,7 @@ class Scheduler {
$number = 50;
}
+ $number = apply_filters( 'activitypub_update_followers_number', $number );
$followers = Followers::get_outdated_followers( $number );
foreach ( $followers as $follower ) {
@@ -246,6 +245,7 @@ class Scheduler {
$number = 50;
}
+ $number = apply_filters( 'activitypub_update_followers_number', $number );
$followers = Followers::get_faulty_followers( $number );
foreach ( $followers as $follower ) {
diff --git a/wp-content/plugins/activitypub/includes/class-webfinger.php b/wp-content/plugins/activitypub/includes/class-webfinger.php
index 67b6d4f9..3233fcb5 100644
--- a/wp-content/plugins/activitypub/includes/class-webfinger.php
+++ b/wp-content/plugins/activitypub/includes/class-webfinger.php
@@ -42,16 +42,31 @@ class Webfinger {
return $data;
}
+ if ( ! is_array( $data ) || empty( $data['links'] ) ) {
+ return new WP_Error(
+ 'webfinger_missing_links',
+ __( 'No valid Link elements found.', 'activitypub' ),
+ $data
+ );
+ }
+
foreach ( $data['links'] as $link ) {
if (
'self' === $link['rel'] &&
- 'application/activity+json' === $link['type']
+ (
+ 'application/activity+json' === $link['type'] ||
+ 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' === $link['type']
+ )
) {
return $link['href'];
}
}
- return new WP_Error( 'webfinger_url_no_activitypub', null, $data );
+ return new WP_Error(
+ 'webfinger_url_no_activitypub',
+ __( 'The Site supports WebFinger but not ActivityPub', 'activitypub' ),
+ $data
+ );
}
/**
diff --git a/wp-content/plugins/activitypub/includes/functions.php b/wp-content/plugins/activitypub/includes/functions.php
index 1f8190e7..ed516328 100644
--- a/wp-content/plugins/activitypub/includes/functions.php
+++ b/wp-content/plugins/activitypub/includes/functions.php
@@ -2,8 +2,8 @@
namespace Activitypub;
use WP_Error;
-use WP_Comment_Query;
use Activitypub\Http;
+use Activitypub\Comment;
use Activitypub\Webfinger;
use Activitypub\Activity\Activity;
use Activitypub\Collection\Followers;
@@ -15,7 +15,7 @@ use Activitypub\Collection\Users;
* @return array the activitypub context
*/
function get_context() {
- $context = Activity::CONTEXT;
+ $context = Activity::JSON_LD_CONTEXT;
return \apply_filters( 'activitypub_json_context', $context );
}
@@ -312,6 +312,12 @@ function is_activitypub_request() {
}
}
+ // Check if header already sent.
+ if ( ! \headers_sent() && ACTIVITYPUB_SEND_VARY_HEADER ) {
+ // Send Vary header for Accept header.
+ \header( 'Vary: Accept' );
+ }
+
// One can trigger an ActivityPub request by adding ?activitypub to the URL.
// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.VariableRedeclaration
global $wp_query;
@@ -664,22 +670,7 @@ function get_total_users() {
* @return int|boolean Comment ID, or false on failure.
*/
function object_id_to_comment( $id ) {
- $comment_query = new WP_Comment_Query(
- array(
- 'meta_key' => 'source_id', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
- 'meta_value' => $id, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
- )
- );
-
- if ( ! $comment_query->comments ) {
- return false;
- }
-
- if ( count( $comment_query->comments ) > 1 ) {
- return false;
- }
-
- return $comment_query->comments[0];
+ return Comment::object_id_to_comment( $id );
}
/**
@@ -692,50 +683,7 @@ function object_id_to_comment( $id ) {
* @return int comment_ID or null if not found
*/
function url_to_commentid( $url ) {
- if ( ! $url || ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
- return null;
- }
-
- // check for local comment
- if ( \wp_parse_url( \site_url(), \PHP_URL_HOST ) === \wp_parse_url( $url, \PHP_URL_HOST ) ) {
- $query = \wp_parse_url( $url, PHP_URL_QUERY );
-
- if ( $query ) {
- parse_str( $query, $params );
-
- if ( ! empty( $params['c'] ) ) {
- $comment = \get_comment( $params['c'] );
-
- if ( $comment ) {
- return $comment->comment_ID;
- }
- }
- }
- }
-
- $args = array(
- // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
- 'meta_query' => array(
- 'relation' => 'OR',
- array(
- 'key' => 'source_url',
- 'value' => $url,
- ),
- array(
- 'key' => 'source_id',
- 'value' => $url,
- ),
- ),
- );
-
- $query = new \WP_Comment_Query();
- $comments = $query->query( $args );
-
- if ( $comments && is_array( $comments ) ) {
- return $comments[0]->comment_ID;
- }
-
- return null;
+ return Comment::url_to_commentid( $url );
}
/**
@@ -774,3 +722,108 @@ function object_to_uri( $object ) {
return $object;
}
+
+/**
+ * Check if a comment should be federated.
+ *
+ * We consider a comment should be federated if it is authored by a user that is
+ * not disabled for federation and if it is a reply directly to the post or to a
+ * federated comment.
+ *
+ * @param mixed $comment Comment object or ID.
+ *
+ * @return boolean True if the comment should be federated, false otherwise.
+ */
+function should_comment_be_federated( $comment ) {
+ return Comment::should_be_federated( $comment );
+}
+
+/**
+ * Check if a comment was federated.
+ *
+ * This function checks if a comment was federated via ActivityPub.
+ *
+ * @param mixed $comment Comment object or ID.
+ *
+ * @return boolean True if the comment was federated, false otherwise.
+ */
+function was_comment_sent( $comment ) {
+ return Comment::was_sent( $comment );
+}
+
+/**
+ * Check if a comment is federated.
+ *
+ * We consider a comment federated if comment was received via ActivityPub.
+ *
+ * Use this function to check if it is comment that was received via ActivityPub.
+ *
+ * @param mixed $comment Comment object or ID.
+ *
+ * @return boolean True if the comment is federated, false otherwise.
+ */
+function was_comment_received( $comment ) {
+ return Comment::was_received( $comment );
+}
+
+/**
+ * Check if a comment is local only.
+ *
+ * This function checks if a comment is local only and was not sent or received via ActivityPub.
+ *
+ * @param mixed $comment Comment object or ID.
+ *
+ * @return boolean True if the comment is local only, false otherwise.
+ */
+function is_local_comment( $comment ) {
+ return Comment::is_local( $comment );
+}
+
+/**
+ * Mark a WordPress object as federated.
+ *
+ * @param WP_Comment|WP_Post|mixed $wp_object
+ * @return void
+ */
+function set_wp_object_state( $wp_object, $state ) {
+ $meta_key = 'activitypub_status';
+
+ if ( $wp_object instanceof \WP_Post ) {
+ \update_post_meta( $wp_object->ID, $meta_key, $state );
+ } elseif ( $wp_object instanceof \WP_Comment ) {
+ \update_comment_meta( $wp_object->comment_ID, $meta_key, $state );
+ } else {
+ \apply_filters( 'activitypub_mark_wp_object_as_federated', $wp_object );
+ }
+}
+
+/**
+ * Get the description of a post type.
+ *
+ * Set some default descriptions for the default post types.
+ *
+ * @param WP_Post_Type $post_type The post type object.
+ *
+ * @return string The description of the post type.
+ */
+function get_post_type_description( $post_type ) {
+ $description = '';
+
+ switch ( $post_type->name ) {
+ case 'post':
+ $description = '';
+ break;
+ case 'page':
+ $description = '';
+ break;
+ case 'attachment':
+ $description = ' - ' . __( 'The attachments that you have uploaded to a post (images, videos, documents or other files).', 'activitypub' );
+ break;
+ default:
+ if ( ! empty( $post_type->description ) ) {
+ $description = ' - ' . $post_type->description;
+ }
+ }
+
+ return apply_filters( 'activitypub_post_type_description', $description, $post_type->name, $post_type );
+}
diff --git a/wp-content/plugins/activitypub/includes/handler/class-create.php b/wp-content/plugins/activitypub/includes/handler/class-create.php
index 64788da1..5e965089 100644
--- a/wp-content/plugins/activitypub/includes/handler/class-create.php
+++ b/wp-content/plugins/activitypub/includes/handler/class-create.php
@@ -33,6 +33,10 @@ class Create {
* @return void
*/
public static function handle_create( $array, $user_id, $object = null ) {
+ if ( ACTIVITYPUB_DISABLE_INCOMING_INTERACTIONS ) {
+ return;
+ }
+
if (
! isset( $array['object'] ) ||
! isset( $array['object']['id'] )
diff --git a/wp-content/plugins/activitypub/includes/handler/class-delete.php b/wp-content/plugins/activitypub/includes/handler/class-delete.php
index f2571c05..3cc732bf 100644
--- a/wp-content/plugins/activitypub/includes/handler/class-delete.php
+++ b/wp-content/plugins/activitypub/includes/handler/class-delete.php
@@ -81,7 +81,6 @@ class Delete {
// check if Object is an Actor.
if ( $activity['actor'] === $activity['object'] ) {
self::maybe_delete_follower( $activity );
- self::maybe_delete_interactions( $activity );
} else { // assume a interaction otherwise.
self::maybe_delete_interaction( $activity );
}
@@ -101,6 +100,7 @@ class Delete {
// verify if Actor is deleted.
if ( $follower && Http::is_tombstone( $activity['actor'] ) ) {
$follower->delete();
+ self::maybe_delete_interactions( $activity );
}
}
diff --git a/wp-content/plugins/activitypub/includes/model/class-application-user.php b/wp-content/plugins/activitypub/includes/model/class-application-user.php
index 8fb4ee60..37ff4698 100644
--- a/wp-content/plugins/activitypub/includes/model/class-application-user.php
+++ b/wp-content/plugins/activitypub/includes/model/class-application-user.php
@@ -15,19 +15,17 @@ class Application_User extends Blog_User {
*/
protected $_id = Users::APPLICATION_USER_ID; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
- /**
- * The User-Type
- *
- * @var string
- */
- protected $type = 'Application';
+ public function get_type() {
+ return 'Application';
+ }
- /**
- * If the User is discoverable.
- *
- * @var boolean
- */
- protected $discoverable = false;
+ public function get_discoverable() {
+ return false;
+ }
+
+ public function get_manually_approves_followers() {
+ return true;
+ }
/**
* Get the User-Url.
@@ -52,7 +50,7 @@ class Application_User extends Blog_User {
}
public function get_preferred_username() {
- return $this::get_name();
+ return $this->get_name();
}
public function get_followers() {
@@ -78,8 +76,4 @@ class Application_User extends Blog_User {
public function get_indexable() {
return false;
}
-
- public function get_type() {
- return $this->type;
- }
}
diff --git a/wp-content/plugins/activitypub/includes/model/class-blog-user.php b/wp-content/plugins/activitypub/includes/model/class-blog-user.php
index 53f07d48..579f7ba2 100644
--- a/wp-content/plugins/activitypub/includes/model/class-blog-user.php
+++ b/wp-content/plugins/activitypub/includes/model/class-blog-user.php
@@ -2,7 +2,8 @@
namespace Activitypub\Model;
use WP_Query;
-use Activitypub\Signature;
+use WP_Error;
+
use Activitypub\Collection\Users;
use function Activitypub\is_single_user;
@@ -17,19 +18,13 @@ class Blog_User extends User {
*/
protected $_id = Users::BLOG_USER_ID; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
- /**
- * The User-Type
- *
- * @var string
- */
- protected $type = null;
+ public function get_manually_approves_followers() {
+ return false;
+ }
- /**
- * Is Account discoverable?
- *
- * @var boolean
- */
- protected $discoverable = true;
+ public function get_discoverable() {
+ return true;
+ }
public static function from_wp_user( $user_id ) {
if ( is_user_disabled( $user_id ) ) {
diff --git a/wp-content/plugins/activitypub/includes/model/class-follower.php b/wp-content/plugins/activitypub/includes/model/class-follower.php
index b2833e9c..4590ea49 100644
--- a/wp-content/plugins/activitypub/includes/model/class-follower.php
+++ b/wp-content/plugins/activitypub/includes/model/class-follower.php
@@ -162,8 +162,10 @@ class Follower extends Actor {
}
}
+ $post_id = $this->get__id();
+
$args = array(
- 'ID' => $this->get__id(),
+ 'ID' => $post_id,
'guid' => esc_url_raw( $this->get_id() ),
'post_title' => wp_strip_all_tags( sanitize_text_field( $this->get_name() ) ),
'post_author' => 0,
@@ -174,6 +176,14 @@ class Follower extends Actor {
'meta_input' => $this->get_post_meta_input(),
);
+ if ( ! empty( $post_id ) ) {
+ // If this is an update, prevent the "followed" date from being
+ // overwritten by the current date.
+ $post = get_post( $post_id );
+ $args['post_date'] = $post->post_date;
+ $args['post_date_gmt'] = $post->post_date_gmt;
+ }
+
$post_id = wp_insert_post( $args );
$this->_id = $post_id;
@@ -286,6 +296,25 @@ class Follower extends Actor {
return $icon;
}
+ /**
+ * Get the Icon URL (Avatar)
+ *
+ * @return string The URL to the Avatar.
+ */
+ public function get_image_url() {
+ $image = $this->get_image();
+
+ if ( ! $image ) {
+ return '';
+ }
+
+ if ( is_array( $image ) ) {
+ return $image['url'];
+ }
+
+ return $image;
+ }
+
/**
* Get the shared inbox, with a fallback to the inbox.
*
diff --git a/wp-content/plugins/activitypub/includes/model/class-user.php b/wp-content/plugins/activitypub/includes/model/class-user.php
index e773da4d..a62efb30 100644
--- a/wp-content/plugins/activitypub/includes/model/class-user.php
+++ b/wp-content/plugins/activitypub/includes/model/class-user.php
@@ -23,6 +23,11 @@ class User extends Actor {
*
* @see https://docs.joinmastodon.org/spec/activitypub/#featured
*
+ * @context {
+ * "@id": "http://joinmastodon.org/ns#featured",
+ * "@type": "@id"
+ * }
+ *
* @var string
*/
protected $featured;
@@ -36,18 +41,17 @@ class User extends Actor {
*/
protected $moderators;
- /**
- * The User-Type
- *
- * @var string
- */
- protected $type = 'Person';
+ public function get_type() {
+ return 'Person';
+ }
/**
* If the User is discoverable.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
*
+ * @context http://joinmastodon.org/ns#discoverable
+ *
* @var boolean
*/
protected $discoverable = true;
@@ -55,6 +59,8 @@ class User extends Actor {
/**
* If the User is indexable.
*
+ * @context http://joinmastodon.org/ns#indexable
+ *
* @var boolean
*/
protected $indexable;
diff --git a/wp-content/plugins/activitypub/includes/rest/class-collection.php b/wp-content/plugins/activitypub/includes/rest/class-collection.php
index 365641c2..680235ee 100644
--- a/wp-content/plugins/activitypub/includes/rest/class-collection.php
+++ b/wp-content/plugins/activitypub/includes/rest/class-collection.php
@@ -5,7 +5,8 @@ use WP_Error;
use WP_REST_Server;
use WP_REST_Response;
use Activitypub\Transformer\Post;
-use Activitypub\Activity\Activity;
+use Activitypub\Activity\Actor;
+use Activitypub\Activity\Base_Object;
use Activitypub\Collection\Users as User_Collection;
use function Activitypub\esc_hashtag;
@@ -102,7 +103,7 @@ class Collection {
}
$response = array(
- '@context' => Activity::CONTEXT,
+ '@context' => Base_Object::JSON_LD_CONTEXT,
'id' => get_rest_url_by_path( sprintf( 'users/%d/collections/tags', $user->get__id() ) ),
'type' => 'Collection',
'totalItems' => is_countable( $tags ) ? count( $tags ) : 0,
@@ -160,7 +161,7 @@ class Collection {
}
$response = array(
- '@context' => Activity::CONTEXT,
+ '@context' => Base_Object::JSON_LD_CONTEXT,
'id' => get_rest_url_by_path( sprintf( 'users/%d/collections/featured', $user_id ) ),
'type' => 'OrderedCollection',
'totalItems' => is_countable( $posts ) ? count( $posts ) : 0,
@@ -168,7 +169,7 @@ class Collection {
);
foreach ( $posts as $post ) {
- $response['orderedItems'][] = Post::transform( $post )->to_object()->to_array();
+ $response['orderedItems'][] = Post::transform( $post )->to_object()->to_array( false );
}
$rest_response = new WP_REST_Response( $response, 200 );
@@ -186,7 +187,7 @@ class Collection {
*/
public static function moderators_get( $request ) {
$response = array(
- '@context' => Activity::CONTEXT,
+ '@context' => Actor::JSON_LD_CONTEXT,
'id' => get_rest_url_by_path( 'collections/moderators' ),
'type' => 'OrderedCollection',
'orderedItems' => array(),
diff --git a/wp-content/plugins/activitypub/includes/rest/class-comment.php b/wp-content/plugins/activitypub/includes/rest/class-comment.php
new file mode 100644
index 00000000..70df2a0e
--- /dev/null
+++ b/wp-content/plugins/activitypub/includes/rest/class-comment.php
@@ -0,0 +1,91 @@
+\d+)/remote-reply',
+ array(
+ array(
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => array( self::class, 'remote_reply_get' ),
+ 'permission_callback' => '__return_true',
+ 'args' => array(
+ 'resource' => array(
+ 'required' => true,
+ 'sanitize_callback' => 'sanitize_text_field',
+ ),
+ ),
+ ),
+ )
+ );
+ }
+
+ /**
+ * Endpoint for remote follow UI/Block
+ *
+ * @param WP_REST_Request $request The request object.
+ *
+ * @return void|string The URL to the remote follow page
+ */
+ public static function remote_reply_get( WP_REST_Request $request ) {
+ $resource = $request->get_param( 'resource' );
+ $comment_id = $request->get_param( 'comment_id' );
+
+ $comment = get_comment( $comment_id );
+
+ if ( ! $comment ) {
+ return new WP_Error( 'activitypub_comment_not_found', __( 'Comment not found', 'activitypub' ), array( 'status' => 404 ) );
+ }
+
+ $is_local = Comment_Utils::is_local( $comment );
+
+ if ( $is_local ) {
+ return new WP_Error( 'activitypub_local_only_comment', __( 'Comment is local only', 'activitypub' ), array( 'status' => 403 ) );
+ }
+
+ $template = Webfinger_Utils::get_remote_follow_endpoint( $resource );
+
+ if ( is_wp_error( $template ) ) {
+ return $template;
+ }
+
+ $resource = \get_comment_meta( $comment_id, 'source_id', true );
+
+ if ( ! $resource ) {
+ $resource = Comment_Utils::generate_id( $comment );
+ }
+
+ $url = str_replace( '{uri}', $resource, $template );
+
+ return new WP_REST_Response(
+ array( 'url' => $url ),
+ 200
+ );
+ }
+}
diff --git a/wp-content/plugins/activitypub/includes/rest/class-followers.php b/wp-content/plugins/activitypub/includes/rest/class-followers.php
index 75a1f24b..a3f71ada 100644
--- a/wp-content/plugins/activitypub/includes/rest/class-followers.php
+++ b/wp-content/plugins/activitypub/includes/rest/class-followers.php
@@ -96,7 +96,7 @@ class Followers {
$json->orderedItems = array_map(
function ( $item ) use ( $context ) {
if ( 'full' === $context ) {
- return $item->to_array();
+ return $item->to_array( false );
}
return $item->get_url();
},
diff --git a/wp-content/plugins/activitypub/includes/rest/class-inbox.php b/wp-content/plugins/activitypub/includes/rest/class-inbox.php
index c527040f..c0ef5630 100644
--- a/wp-content/plugins/activitypub/includes/rest/class-inbox.php
+++ b/wp-content/plugins/activitypub/includes/rest/class-inbox.php
@@ -11,7 +11,6 @@ use function Activitypub\get_context;
use function Activitypub\object_to_uri;
use function Activitypub\url_to_authorid;
use function Activitypub\get_rest_url_by_path;
-use function Activitypub\get_remote_metadata_by_actor;
use function Activitypub\extract_recipients_from_activity;
/**
diff --git a/wp-content/plugins/activitypub/includes/rest/class-nodeinfo.php b/wp-content/plugins/activitypub/includes/rest/class-nodeinfo.php
index 0c49026f..38cbf0c3 100644
--- a/wp-content/plugins/activitypub/includes/rest/class-nodeinfo.php
+++ b/wp-content/plugins/activitypub/includes/rest/class-nodeinfo.php
@@ -129,7 +129,7 @@ class Nodeinfo {
$nodeinfo = array();
- $nodeinfo['version'] = '1.0';
+ $nodeinfo['version'] = '2.0';
$nodeinfo['server'] = array(
'baseUrl' => \home_url( '/' ),
'name' => \get_bloginfo( 'name' ),
diff --git a/wp-content/plugins/activitypub/includes/rest/class-outbox.php b/wp-content/plugins/activitypub/includes/rest/class-outbox.php
index d640d173..ab00778a 100644
--- a/wp-content/plugins/activitypub/includes/rest/class-outbox.php
+++ b/wp-content/plugins/activitypub/includes/rest/class-outbox.php
@@ -59,7 +59,7 @@ class Outbox {
return $user;
}
- $post_types = \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) );
+ $post_types = \get_option( 'activitypub_support_post_types', array( 'post' ) );
$page = $request->get_param( 'page', 1 );
@@ -108,10 +108,8 @@ class Outbox {
$post = Post::transform( $post )->to_object();
$activity = new Activity();
$activity->set_type( 'Create' );
- $activity->set_context( null );
$activity->set_object( $post );
-
- $json->orderedItems[] = $activity->to_array(); // phpcs:ignore
+ $json->orderedItems[] = $activity->to_array( false ); // phpcs:ignore
}
}
diff --git a/wp-content/plugins/activitypub/includes/rest/class-server.php b/wp-content/plugins/activitypub/includes/rest/class-server.php
index 1bad5a73..13e70736 100644
--- a/wp-content/plugins/activitypub/includes/rest/class-server.php
+++ b/wp-content/plugins/activitypub/includes/rest/class-server.php
@@ -49,10 +49,6 @@ class Server {
public static function application_actor() {
$user = new Application_User();
- $user->set_context(
- \Activitypub\Activity\Activity::CONTEXT
- );
-
$json = $user->to_array();
$rest_response = new WP_REST_Response( $json, 200 );
diff --git a/wp-content/plugins/activitypub/includes/rest/class-users.php b/wp-content/plugins/activitypub/includes/rest/class-users.php
index ed3d2aa8..db9d14cf 100644
--- a/wp-content/plugins/activitypub/includes/rest/class-users.php
+++ b/wp-content/plugins/activitypub/includes/rest/class-users.php
@@ -88,10 +88,6 @@ class Users {
*/
\do_action( 'activitypub_rest_users_pre' );
- $user->set_context(
- Activity::CONTEXT
- );
-
$json = $user->to_array();
$rest_response = new WP_REST_Response( $json, 200 );
diff --git a/wp-content/plugins/activitypub/includes/transformer/class-base.php b/wp-content/plugins/activitypub/includes/transformer/class-base.php
index 92df86fd..b66703fa 100644
--- a/wp-content/plugins/activitypub/includes/transformer/class-base.php
+++ b/wp-content/plugins/activitypub/includes/transformer/class-base.php
@@ -30,7 +30,7 @@ abstract class Base {
*
* @param WP_Post|WP_Comment $wp_object The WordPress object
*
- * @return void
+ * @return Base_Object
*/
public static function transform( $object ) {
return new static( $object );
@@ -46,13 +46,13 @@ abstract class Base {
}
/**
- * Transform the WordPress Object into an ActivityPub Object.
+ * Transform all properties with available get(ter) functions.
*
- * @return Activitypub\Activity\Base_Object
+ * @param Base_Object|object $object
+ *
+ * @return Base_Object|object $object
*/
- public function to_object() {
- $activitypub_object = new Base_Object();
-
+ protected function transform_object_properties( $activitypub_object ) {
$vars = $activitypub_object->get_object_var_keys();
foreach ( $vars as $var ) {
@@ -68,6 +68,17 @@ abstract class Base {
}
}
}
+ return $activitypub_object;
+ }
+
+ /**
+ * Transform the WordPress Object into an ActivityPub Object.
+ *
+ * @return Activitypub\Activity\Base_Object
+ */
+ public function to_object() {
+ $activitypub_object = new Base_Object();
+ $activitypub_object = $this->transform_object_properties( $activitypub_object );
return $activitypub_object;
}
@@ -84,6 +95,8 @@ abstract class Base {
$activity = new Activity();
$activity->set_type( $type );
+
+ // Pre-fill the Activity with data (for example cc and to).
$activity->set_object( $object );
// Use simple Object (only ID-URI) for Like and Announce
diff --git a/wp-content/plugins/activitypub/includes/transformer/class-comment.php b/wp-content/plugins/activitypub/includes/transformer/class-comment.php
index f77cd212..209a7ab3 100644
--- a/wp-content/plugins/activitypub/includes/transformer/class-comment.php
+++ b/wp-content/plugins/activitypub/includes/transformer/class-comment.php
@@ -4,6 +4,8 @@ namespace Activitypub\Transformer;
use WP_Comment;
use WP_Comment_Query;
+use Activitypub\Webfinger;
+use Activitypub\Comment as Comment_Utils;
use Activitypub\Model\Blog_User;
use Activitypub\Collection\Users;
use Activitypub\Transformer\Base;
@@ -51,7 +53,7 @@ class Comment extends Base {
$comment = $this->wp_object;
$object = parent::to_object();
- $object->set_url( \get_comment_link( $comment->comment_ID ) );
+ $object->set_url( $this->get_id() );
$object->set_type( 'Note' );
$published = \strtotime( $comment->comment_date_gmt );
@@ -107,10 +109,10 @@ class Comment extends Base {
$comment = $this->wp_object;
$content = $comment->comment_content;
- $content = \wpautop( $content );
+ $content = \apply_filters( 'comment_text', $content, $comment, array() );
$content = \preg_replace( '/[\n\r\t]/', '', $content );
$content = \trim( $content );
- $content = \apply_filters( 'the_content', $content, $comment );
+ $content = \apply_filters( 'activitypub_the_content', $content, $comment );
return $content;
}
@@ -123,7 +125,12 @@ class Comment extends Base {
protected function get_in_reply_to() {
$comment = $this->wp_object;
- $parent_comment = \get_comment( $comment->comment_parent );
+ $parent_comment = null;
+ $in_reply_to = null;
+
+ if ( $comment->comment_parent ) {
+ $parent_comment = \get_comment( $comment->comment_parent );
+ }
if ( $parent_comment ) {
$comment_meta = \get_comment_meta( $parent_comment->comment_ID );
@@ -132,8 +139,8 @@ class Comment extends Base {
$in_reply_to = $comment_meta['source_id'][0];
} elseif ( ! empty( $comment_meta['source_url'][0] ) ) {
$in_reply_to = $comment_meta['source_url'][0];
- } else {
- $in_reply_to = $this->generate_id( $parent_comment );
+ } elseif ( ! empty( $parent_comment->user_id ) ) {
+ $in_reply_to = Comment_Utils::generate_id( $parent_comment );
}
} else {
$in_reply_to = \get_permalink( $comment->comment_post_ID );
@@ -152,25 +159,7 @@ class Comment extends Base {
*/
protected function get_id() {
$comment = $this->wp_object;
- return $this->generate_id( $comment );
- }
-
- /**
- * Generates an ActivityPub URI for a comment
- *
- * @param WP_Comment|int $comment A comment object or comment ID
- *
- * @return string ActivityPub URI for comment
- */
- protected function generate_id( $comment ) {
- $comment = get_comment( $comment );
-
- return \add_query_arg(
- array(
- 'c' => $comment->comment_ID,
- ),
- \trailingslashit( site_url() )
- );
+ return Comment_Utils::generate_id( $comment );
}
/**
@@ -190,31 +179,7 @@ class Comment extends Base {
}
}
- $comment_query = new WP_Comment_Query(
- array(
- 'post_id' => $this->wp_object->comment_post_ID,
- // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
- 'meta_query' => array(
- array(
- 'key' => 'source_id',
- 'compare' => 'EXISTS',
- ),
- ),
- )
- );
-
- if ( $comment_query->comments ) {
- foreach ( $comment_query->comments as $comment ) {
- if ( empty( $comment->comment_author_url ) ) {
- continue;
- }
- $cc[] = \esc_url( $comment->comment_author_url );
- }
- }
-
- $cc = \array_unique( $cc );
-
- return $cc;
+ return array_unique( $cc );
}
/**
@@ -248,9 +213,53 @@ class Comment extends Base {
* @return array The list of @-Mentions.
*/
protected function get_mentions() {
+ \add_filter( 'activitypub_extract_mentions', array( $this, 'extract_reply_context' ) );
+
return apply_filters( 'activitypub_extract_mentions', array(), $this->wp_object->comment_content, $this->wp_object );
}
+ /**
+ * Collect all other Users that participated in this comment-thread
+ * to send them a notification about the new reply.
+ *
+ * @param array $mentions The already mentioned ActivityPub users
+ *
+ * @return array The list of all Repliers.
+ */
+ public function extract_reply_context( $mentions ) {
+ // Check if `$this->wp_object` is a WP_Comment
+ if ( 'WP_Comment' !== get_class( $this->wp_object ) ) {
+ return $mentions;
+ }
+
+ $comment_query = new WP_Comment_Query(
+ array(
+ 'post_id' => $this->wp_object->comment_post_ID,
+ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
+ 'meta_query' => array(
+ array(
+ 'key' => 'protocol',
+ 'value' => 'activitypub',
+ ),
+ ),
+ )
+ );
+
+ if ( $comment_query->comments ) {
+ foreach ( $comment_query->comments as $comment ) {
+ if ( ! empty( $comment->comment_author_url ) ) {
+ $acct = Webfinger::uri_to_acct( $comment->comment_author_url );
+ if ( $acct && ! is_wp_error( $acct ) ) {
+ $acct = str_replace( 'acct:', '@', $acct );
+ $mentions[ $acct ] = $comment->comment_author_url;
+ }
+ }
+ }
+ }
+
+ return $mentions;
+ }
+
/**
* Returns the locale of the post.
*
diff --git a/wp-content/plugins/activitypub/integration/class-enable-mastodon-apps.php b/wp-content/plugins/activitypub/integration/class-enable-mastodon-apps.php
new file mode 100644
index 00000000..69899043
--- /dev/null
+++ b/wp-content/plugins/activitypub/integration/class-enable-mastodon-apps.php
@@ -0,0 +1,172 @@
+get_id() );
+
+ if ( $acct && ! is_wp_error( $acct ) ) {
+ $acct = \str_replace( 'acct:', '', $acct );
+ } else {
+ $acct = $item->get_url();
+ }
+
+ $activitypub_follower = array(
+ 'id' => \strval( $item->get__id() ),
+ 'username' => $item->get_preferred_username(),
+ 'acct' => $acct,
+ 'display_name' => $item->get_name(),
+ 'url' => $item->get_url(),
+ 'uri' => $item->get_id(),
+ 'avatar' => $item->get_icon_url(),
+ 'avatar_static' => $item->get_icon_url(),
+ 'created_at' => gmdate( DATE_W3C, strtotime( $item->get_published() ) ),
+ 'last_status_at' => gmdate( DATE_W3C, strtotime( $item->get_published() ) ),
+ 'note' => $item->get_summary(),
+ 'header' => $item->get_image_url(),
+ 'header_static' => $item->get_image_url(),
+ 'followers_count' => 0,
+ 'following_count' => 0,
+ 'statuses_count' => 0,
+ 'bot' => false,
+ 'locked' => false,
+ 'group' => false,
+ 'discoversable' => false,
+ 'indexable' => false,
+ 'hide_collections' => false,
+ 'noindex' => false,
+ 'fields' => array(),
+ 'emojis' => array(),
+ 'roles' => array(),
+ );
+
+ return $activitypub_follower;
+ },
+ $activitypub_followers
+ );
+
+ $followers = array_merge( $mastodon_followers, $followers );
+
+ return $followers;
+ }
+
+ /**
+ * Add followers count to Mastodon API
+ *
+ * @param Enable_Mastodon_Apps\Entity\Account $account The account
+ * @param int $user_id The user id
+ *
+ * @return Enable_Mastodon_Apps\Entity\Account The filtered Account
+ */
+ public static function api_account_add_followers( $account, $user_id ) {
+ if ( ! $account instanceof Account ) {
+ return $account;
+ }
+
+ $user = Users::get_by_id( $user_id );
+
+ if ( ! $user || is_wp_error( $user ) ) {
+ return $account;
+ }
+
+ $account->followers_count = Followers::count_followers( $user_id );
+ return $account;
+ }
+
+ /**
+ * Resolve external accounts for Mastodon API
+ *
+ * @param Enable_Mastodon_Apps\Entity\Account $user_data The user data
+ * @param string $user_id The user id
+ *
+ * @return Enable_Mastodon_Apps\Entity\Account The filtered Account
+ */
+ public static function api_account_external( $user_data, $user_id ) {
+ if ( ! preg_match( '/^' . ACTIVITYPUB_USERNAME_REGEXP . '$/', $user_id ) ) {
+ return $user_data;
+ }
+
+ $uri = Webfinger_Util::resolve( $user_id );
+
+ if ( ! $uri ) {
+ return $user_data;
+ }
+
+ $acct = Webfinger_Util::uri_to_acct( $uri );
+ $data = get_remote_metadata_by_actor( $uri );
+
+ if ( ! $data || is_wp_error( $data ) ) {
+ return $user_data;
+ }
+
+ if ( $user_data instanceof Account ) {
+ $account = $user_data;
+ } else {
+ $account = new Account();
+ }
+
+ $account->id = strval( $user_id );
+ $account->username = $acct;
+ $account->acct = $acct;
+ $account->display_name = $data['name'];
+ $account->url = $uri;
+ if ( ! empty( $data['summary'] ) ) {
+ $account->note = $data['summary'];
+ }
+
+ if (
+ isset( $data['icon']['type'] ) &&
+ isset( $data['icon']['url'] ) &&
+ 'Image' === $data['icon']['type']
+ ) {
+ $account->avatar = $data['icon']['url'];
+ $account->avatar_static = $data['icon']['url'];
+ }
+
+ if ( isset( $data['image'] ) ) {
+ $account->header = $data['image'];
+ $account->header_static = $data['image'];
+ }
+
+ $account->created_at = new DateTime( $data['published'] );
+
+ return $account;
+ }
+}
diff --git a/wp-content/plugins/activitypub/readme.txt b/wp-content/plugins/activitypub/readme.txt
index eac5397f..fa2e3f93 100644
--- a/wp-content/plugins/activitypub/readme.txt
+++ b/wp-content/plugins/activitypub/readme.txt
@@ -3,7 +3,7 @@ Contributors: automattic, pfefferle, mediaformat, mattwiebe, akirk, jeherve, nur
Tags: OStatus, fediverse, activitypub, activitystream
Requires at least: 5.5
Tested up to: 6.4
-Stable tag: 2.0.1
+Stable tag: 2.2.0
Requires PHP: 5.6
License: MIT
License URI: http://opensource.org/licenses/MIT
@@ -105,10 +105,56 @@ Where 'blog' is the path to the subdirectory at which your blog resides.
In that case you don't need the redirect, because the index.php will take care of that.
+= Constants =
+
+The plugin uses PHP Constants to enable, disable or change its default behaviour. Please use them with caution and only if you know what you are doing.
+
+* `ACTIVITYPUB_REST_NAMESPACE` - Change the default Namespace of the REST endpoint. Default: `activitypub/1.0`.
+* `ACTIVITYPUB_EXCERPT_LENGTH` - Change the length of the Excerpt. Default: `400`.
+* `ACTIVITYPUB_SHOW_PLUGIN_RECOMMENDATIONS` - show plugin recommendations in the ActivityPub settings. Default: `true`.
+* `ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS` - Change the number of attachments, that should be federated. Default: `3`.
+* `ACTIVITYPUB_HASHTAGS_REGEXP` - Change the default regex to detect hashtext in a text. Default: `(?:(?<=\s)|(?<=
)|(?<= )|^)#([A-Za-z0-9_]+)(?:(?=\s|[[:punct:]]|$))`.
+* `ACTIVITYPUB_USERNAME_REGEXP` - Change the default regex to detect @-replies in a text. Default: `(?:([A-Za-z0-9\._-]+)@((?:[A-Za-z0-9_-]+\.)+[A-Za-z]+))`.
+* `ACTIVITYPUB_CUSTOM_POST_CONTENT` - Change the default template for Activities. Default: `[ap_title]\n\n[ap_content]\n\n[ap_hashtags]\n\n[ap_shortlink]`.
+* `ACTIVITYPUB_AUTHORIZED_FETCH` - Enable AUTHORIZED_FETCH. Default: `false`.
+* `ACTIVITYPUB_DISABLE_REWRITES` - Disable auto generation of `mod_rewrite` rules. Default: `false`.
+* `ACTIVITYPUB_DISABLE_INCOMING_INTERACTIONS` - Block incoming replies/comments/likes. Default: `false`.
+* `ACTIVITYPUB_DISABLE_OUTGOING_INTERACTIONS` - Disable outgoing replies/comments/likes. Default: `false`.
+* `ACTIVITYPUB_SHARED_INBOX_FEATURE` - Enable the shared inbox. Default: `false`.
+* `ACTIVITYPUB_SEND_VARY_HEADER` - Enable to send the `Vary: Accept` header. Default: `false`.
+
+= Where can you manage your followers? =
+
+If you have activated the blog user, you will find the list of his followers in the settings under `/wp-admin/options-general.php?page=activitypub&tab=followers`.
+
+The followers of a user can be found in the menu under "Users" -> "Followers" or under `wp-admin/users.php?page=activitypub-followers-list`.
+
+For reasons of data protection, it is not possible to see the followers of other users.
+
== Changelog ==
Project maintained on GitHub at [automattic/wordpress-activitypub](https://github.com/automattic/wordpress-activitypub).
+= 2.2.0 =
+
+* Added: Remote-Reply lightbox
+* Added: Support `application/ld+json` mime-type with AP profile in WebFinger
+* Fixed: Prevent scheduler overload
+
+= 2.1.1 =
+
+* Added: Add `@` prefix to Follow-Block
+* Added: Apply `comment_text` filter to Activity
+
+= 2.1.0 =
+
+* Fixed: Some Federated Comment improvements
+* Fixed: Remove old/abandoned Crons
+* Added: Various endpoints for the "Enable Mastodon Apps" plugin
+* Added: Event Objects
+* Added: Send notification to all Repliers if a new Comment is added
+* Added: Vary-Header support behind feature flag
+
= 2.0.1 =
* Fixed: Comment `Update` Federation
diff --git a/wp-content/plugins/activitypub/templates/author-json.php b/wp-content/plugins/activitypub/templates/author-json.php
index 7043131f..63f6d12f 100644
--- a/wp-content/plugins/activitypub/templates/author-json.php
+++ b/wp-content/plugins/activitypub/templates/author-json.php
@@ -1,10 +1,6 @@
set_context(
- \Activitypub\Activity\Activity::CONTEXT
-);
-
/*
* Action triggerd prior to the ActivityPub profile being created and sent to the client
*/
diff --git a/wp-content/plugins/activitypub/templates/blog-json.php b/wp-content/plugins/activitypub/templates/blog-json.php
index 3ca54dc2..8090b135 100644
--- a/wp-content/plugins/activitypub/templates/blog-json.php
+++ b/wp-content/plugins/activitypub/templates/blog-json.php
@@ -1,10 +1,6 @@
set_context(
- \Activitypub\Activity\Activity::CONTEXT
-);
-
/*
* Action triggerd prior to the ActivityPub profile being created and sent to the client
*/
diff --git a/wp-content/plugins/activitypub/templates/post-json.php b/wp-content/plugins/activitypub/templates/post-json.php
index 1db29a6e..f90a1bca 100644
--- a/wp-content/plugins/activitypub/templates/post-json.php
+++ b/wp-content/plugins/activitypub/templates/post-json.php
@@ -3,7 +3,6 @@
$post = \get_post();
$post_object = \Activitypub\Transformer\Factory::get_transformer( $post )->to_object();
-$post_object->set_context( \Activitypub\get_context() );
/*
* Action triggerd prior to the ActivityPub profile being created and sent to the client
diff --git a/wp-content/plugins/activitypub/templates/settings.php b/wp-content/plugins/activitypub/templates/settings.php
index 642ab164..b62c7665 100644
--- a/wp-content/plugins/activitypub/templates/settings.php
+++ b/wp-content/plugins/activitypub/templates/settings.php
@@ -118,7 +118,7 @@