From 4f63399d4aa66c22d8da9d85adab62073f7351b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20Klabbers?= Date: Thu, 18 Mar 2021 16:58:29 +0100 Subject: [PATCH] Adds the ability to push new posts onto discussions that aren't public. (#17) It's very frustrating having pusher installed, but not seeing new posts pop up on non public discussions. This PR simply re-uses the existing channels per user by reading all similar private user channels (which require authentication) and then pushing the websocket message over the line. This only happens in case the discussion is not public and it only sends to connected users. --- extensions/pusher/js/src/forum/index.js | 33 ++++++++++++------- .../pusher/src/Listener/PushNewPost.php | 27 ++++++++++++++- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/extensions/pusher/js/src/forum/index.js b/extensions/pusher/js/src/forum/index.js index cb2871d8e..f6e565622 100644 --- a/extensions/pusher/js/src/forum/index.js +++ b/extensions/pusher/js/src/forum/index.js @@ -9,7 +9,7 @@ import Button from 'flarum/components/Button'; app.initializers.add('flarum-pusher', () => { const loadPusher = new Promise((resolve) => { - $.getScript('//cdn.jsdelivr.net/npm/pusher-js@3.0.0/dist/pusher.min.js', () => { + $.getScript('//cdn.jsdelivr.net/npm/pusher-js@7.0.3/dist/web/pusher.min.js', () => { const socket = new Pusher(app.forum.attribute('pusherKey'), { authEndpoint: app.forum.attribute('apiUrl') + '/pusher/auth', cluster: app.forum.attribute('pusherCluster'), @@ -21,8 +21,11 @@ app.initializers.add('flarum-pusher', () => { }); return resolve({ - main: socket.subscribe('public'), - user: app.session.user ? socket.subscribe('private-user' + app.session.user.id()) : null + channels: { + main: socket.subscribe('public'), + user: app.session.user ? socket.subscribe('private-user' + app.session.user.id()) : null + }, + pusher: socket }); }); }); @@ -31,8 +34,10 @@ app.initializers.add('flarum-pusher', () => { app.pushedUpdates = []; extend(DiscussionList.prototype, 'oncreate', function() { - app.pusher.then(channels => { - channels.main.bind('newPost', data => { + app.pusher.then(binding => { + const pusher = binding.pusher; + + pusher.bind('newPost', data => { const params = app.discussions.getParams(); if (!params.q && !params.sort && !params.filter) { @@ -59,8 +64,8 @@ app.initializers.add('flarum-pusher', () => { }); extend(DiscussionList.prototype, 'onremove', function () { - app.pusher.then(channels => { - channels.main.unbind('newPost'); + app.pusher.then(binding => { + binding.pusher.unbind('newPost'); }); }); @@ -107,8 +112,10 @@ app.initializers.add('flarum-pusher', () => { }); extend(DiscussionPage.prototype, 'oncreate', function() { - app.pusher.then(channels => { - channels.main.bind('newPost', data => { + app.pusher.then(binding => { + const pusher = binding.pusher; + + pusher.bind('newPost', data => { const id = String(data.discussionId); if (this.discussion && this.discussion.id() === id && this.stream) { @@ -129,8 +136,8 @@ app.initializers.add('flarum-pusher', () => { }); extend(DiscussionPage.prototype, 'onremove', function () { - app.pusher.then(channels => { - channels.main.unbind('newPost') + app.pusher.then(binding => { + binding.pusher.unbind('newPost'); }); }); @@ -138,7 +145,9 @@ app.initializers.add('flarum-pusher', () => { items.remove('refresh'); }); - app.pusher.then(channels => { + app.pusher.then(binding => { + const channels = binding.channels; + if (channels.user) { channels.user.bind('notification', () => { app.session.user.pushAttributes({ diff --git a/extensions/pusher/src/Listener/PushNewPost.php b/extensions/pusher/src/Listener/PushNewPost.php index a55f1014e..851b14251 100644 --- a/extensions/pusher/src/Listener/PushNewPost.php +++ b/extensions/pusher/src/Listener/PushNewPost.php @@ -11,6 +11,8 @@ namespace Flarum\Pusher\Listener; use Flarum\Post\Event\Posted; use Flarum\User\Guest; +use Flarum\User\User; +use Illuminate\Support\Str; use Pusher; class PushNewPost @@ -27,10 +29,33 @@ class PushNewPost public function handle(Posted $event) { + $channels = []; + if ($event->post->isVisibleTo(new Guest)) { + $channels[] = 'public'; + } else { + // Retrieve private channels, used for each user. + $response = $this->pusher->get_channels([ + 'filter_by_prefix' => 'private-user' + ]); + + if (! $response) { + return; + } + + foreach ($response->channels as $name => $channel) { + $userId = Str::after($name, 'private-user'); + + if (($user = User::find($userId)) && $event->post->isVisibleTo($user)) { + $channels[] = $name; + } + } + } + + if (count($channels)) { $tags = $event->post->discussion->tags; - $this->pusher->trigger('public', 'newPost', [ + $this->pusher->trigger($channels, 'newPost', [ 'postId' => $event->post->id, 'discussionId' => $event->post->discussion->id, 'tagIds' => $tags ? $tags->pluck('id') : null