From 34b25e032e223cbf85652fa85fe33856d720eeac Mon Sep 17 00:00:00 2001 From: Hannes Mannerheim Date: Fri, 4 Mar 2016 00:22:25 +0100 Subject: [PATCH] mute etc --- QvitterPlugin.php | 21 ++ actions/apiqvitterblocks.php | 2 +- actions/apiqvittermutes.php | 182 +++++++++++++ actions/apiqvittersandboxcreate.php | 107 ++++++++ actions/apiqvittersandboxdestroy.php | 103 ++++++++ actions/apiqvittersandboxed.php | 6 +- actions/apiqvittersilencecreate.php | 7 + actions/apiqvittersilenced.php | 5 +- actions/apiqvittersilencedestroy.php | 100 ++++++++ actions/qvitter.php | 23 +- classes/NotificationStream.php | 10 + classes/QvitterMuted.php | 105 ++++++++ css/qvitter.css | 154 ++++++++--- js/ajax-functions.js | 68 ++++- js/dom-functions.js | 129 +++++++--- js/lib/bowser.min.js | 2 +- js/misc-functions.js | 367 +++++++++++++++++++++++++-- js/qvitter.js | 244 +++++++++++++++--- js/stream-router.js | 26 +- locale/ar.json | 23 +- locale/ast.json | 19 +- locale/ca.json | 19 +- locale/de.json | 19 +- locale/en.json | 23 +- locale/eo.json | 51 ++-- locale/es.json | 19 +- locale/es_ahorita.json | 19 +- locale/eu.json | 19 +- locale/fa.json | 19 +- locale/fi.json | 19 +- locale/fr.json | 19 +- locale/gl.json | 19 +- locale/he.json | 19 +- locale/io.json | 19 +- locale/it.json | 19 +- locale/ja.json | 89 ++++--- locale/nb.json | 19 +- locale/nl.json | 37 ++- locale/pt.json | 19 +- locale/pt_br.json | 89 ++++--- locale/ru.json | 19 +- locale/sq.json | 19 +- locale/sv.json | 21 +- locale/tr.json | 19 +- locale/zh_cn.json | 19 +- locale/zh_tw.json | 19 +- 46 files changed, 2103 insertions(+), 271 deletions(-) create mode 100644 actions/apiqvittermutes.php create mode 100644 actions/apiqvittersandboxcreate.php create mode 100644 actions/apiqvittersandboxdestroy.php create mode 100644 actions/apiqvittersilencedestroy.php create mode 100644 classes/QvitterMuted.php diff --git a/QvitterPlugin.php b/QvitterPlugin.php index 36a1db5..742a1ff 100644 --- a/QvitterPlugin.php +++ b/QvitterPlugin.php @@ -153,14 +153,25 @@ class QvitterPlugin extends Plugin { // route/reroute urls public function onRouterInitialized($m) { + $m->connect(':nickname/mutes', + array('action' => 'qvitter', + 'nickname' => Nickname::INPUT_FMT)); + $m->connect('api/qvitter/mutes.json', + array('action' => 'ApiQvitterMutes')); $m->connect('api/qvitter/sandboxed.:format', array('action' => 'ApiQvitterSandboxed', 'format' => '(xml|json)')); $m->connect('api/qvitter/silenced.:format', array('action' => 'ApiQvitterSilenced', 'format' => '(xml|json)')); + $m->connect('api/qvitter/sandbox/create.json', + array('action' => 'ApiQvitterSandboxCreate')); + $m->connect('api/qvitter/sandbox/destroy.json', + array('action' => 'ApiQvitterSandboxDestroy')); $m->connect('api/qvitter/silence/create.json', array('action' => 'ApiQvitterSilenceCreate')); + $m->connect('api/qvitter/silence/destroy.json', + array('action' => 'ApiQvitterSilenceDestroy')); $m->connect('services/oembed.:format', array('action' => 'apiqvitteroembednotice', 'format' => '(xml|json)')); @@ -1285,6 +1296,16 @@ class QvitterPlugin extends Plugin { $notification->whereAdd(sprintf('qvitternotification.from_profile_id IN (SELECT subscribed FROM subscription WHERE subscriber = %u)', $user_id)); } + // the user might have opted out from notifications from profiles they have muted + $hide_notifications_from_muted_users = Profile_prefs::getConfigData($profile, 'qvitter', 'hide_notifications_from_muted_users'); + if($hide_notifications_from_muted_users == '1') { + $muted_ids = QvitterMuted::getMutedIDs($profile->id,0,10000); // get all (hopefully not more than 10 000...) + if($muted_ids !== false && count($muted_ids) > 0) { + $ids_imploded = implode(',',$muted_ids); + $notification->whereAdd('qvitternotification.from_profile_id NOT IN ('.$ids_imploded.')'); + } + } + // the user might have opted out from certain notification types $current_profile = $user->getProfile(); $disable_notify_replies_and_mentions = Profile_prefs::getConfigData($current_profile, 'qvitter', 'disable_notify_replies_and_mentions'); diff --git a/actions/apiqvitterblocks.php b/actions/apiqvitterblocks.php index f6d7bb2..d970605 100644 --- a/actions/apiqvitterblocks.php +++ b/actions/apiqvitterblocks.php @@ -96,7 +96,7 @@ class ApiQvitterBlocksAction extends ApiPrivateAuthAction } /** - * Get the user's subscribers (followers) as an array of profiles + * Get the user's blocked profiles * * @return array Profiles */ diff --git a/actions/apiqvittermutes.php b/actions/apiqvittermutes.php new file mode 100644 index 0000000..ec56189 --- /dev/null +++ b/actions/apiqvittermutes.php @@ -0,0 +1,182 @@ + \\\\_\ · + · \\) \____) · + · · + · · + · · + · Qvitter is free software: you can redistribute it and / or modify it · + · under the terms of the GNU Affero General Public License as published by · + · the Free Software Foundation, either version three of the License or (at · + · your option) any later version. · + · · + · Qvitter is distributed in hope that it will be useful but WITHOUT ANY · + · WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS · + · FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for · + · more details. · + · · + · You should have received a copy of the GNU Affero General Public License · + · along with Qvitter. If not, see . · + · · + · Contact h@nnesmannerhe.im if you have any questions. · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */ + +if (!defined('GNUSOCIAL')) { exit(1); } + + +class ApiQvitterMutesAction extends ApiPrivateAuthAction +{ + var $profiles = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + protected function prepare(array $args=array()) + { + parent::prepare($args); + + $this->format = 'json'; + + $this->count = (int)$this->arg('count', 100); + + return true; + } + + /** + * Handle the request + * + * Show the profiles + * + * @return void + */ + protected function handle() + { + parent::handle(); + + $this->target = Profile::current(); + + if(!$this->target instanceof Profile) { + $this->clientError(_('You have to be logged in to view your mutes.'), 403); + } + + $this->profiles = $this->getProfiles(); + + $this->initDocument('json'); + print json_encode($this->showProfiles()); + $this->endDocument('json'); + } + + /** + * Get the user's muted profiles + * + * @return array Profiles + */ + protected function getProfiles() + { + $offset = ($this->page - 1) * $this->count; + $limit = $this->count; + + $mutes = QvitterMuted::getMutedProfiles($this->target->id, $offset, $limit); + + if($mutes) { + return $mutes; + } else { + return false; + } + } + + /** + * Is this action read only? + * + * @param array $args other arguments + * + * @return boolean true + */ + function isReadOnly($args) + { + return true; + } + + /** + * When was this feed last modified? + * + * @return string datestamp of the latest profile in the stream + */ + function lastModified() + { + if (!empty($this->profiles) && (count($this->profiles) > 0)) { + return strtotime($this->profiles[0]->modified); + } + + return null; + } + + /** + * An entity tag for this action + * + * Returns an Etag based on the action name, language, user ID, and + * timestamps of the first and last profiles in the subscriptions list + * There's also an indicator to show whether this action is being called + * as /api/statuses/(friends|followers) or /api/(friends|followers)/ids + * + * @return string etag + */ + function etag() + { + if (!empty($this->profiles) && (count($this->profiles) > 0)) { + + $last = count($this->profiles) - 1; + + return '"' . implode( + ':', + array($this->arg('action'), + common_user_cache_hash($this->auth_user), + common_language(), + $this->target->id, + 'Profiles', + strtotime($this->profiles[0]->modified), + strtotime($this->profiles[$last]->modified)) + ) + . '"'; + } + + return null; + } + + /** + * Show the profiles as Twitter-style useres and statuses + * + * @return void + */ + function showProfiles() + { + $user_arrays = array(); + if($this->profiles !== false) { + foreach ($this->profiles as $profile) { + $user_arrays[] = $this->twitterUserArray($profile, false ); + } + } + return $user_arrays; + } +} diff --git a/actions/apiqvittersandboxcreate.php b/actions/apiqvittersandboxcreate.php new file mode 100644 index 0000000..f713e61 --- /dev/null +++ b/actions/apiqvittersandboxcreate.php @@ -0,0 +1,107 @@ + \\\\_\ · + · \\) \____) · + · · + · · + · · + · Qvitter is free software: you can redistribute it and / or modify it · + · under the terms of the GNU Affero General Public License as published by · + · the Free Software Foundation, either version three of the License or (at · + · your option) any later version. · + · · + · Qvitter is distributed in hope that it will be useful but WITHOUT ANY · + · WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS · + · FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for · + · more details. · + · · + · You should have received a copy of the GNU Affero General Public License · + · along with Qvitter. If not, see . · + · · + · Contact h@nnesmannerhe.im if you have any questions. · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */ + + +if (!defined('GNUSOCIAL')) { exit(1); } + +class ApiQvitterSandboxCreateAction extends ApiAuthAction +{ + + protected $needPost = true; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + protected function prepare(array $args=array()) + { + parent::prepare($args); + + $this->format = 'json'; + + $this->other = $this->getTargetProfile($this->arg('id')); + + return true; + } + + /** + * Handle the request + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + protected function handle() + { + parent::handle(); + + if (!$this->other instanceof Profile) { + $this->clientError(_('No such user.'), 404); + } + + if ($this->scoped->id == $this->other->id) { + $this->clientError(_("You cannot sandbox yourself!"), 403); + } + + if (!$this->scoped->hasRight(Right::SANDBOXUSER)) { + $this->clientError(_('You cannot sandbox users on this site.'), 403); + } + // Only administrators can sandbox other privileged users (such as others who have the right to sandbox). + if ($this->scoped->isPrivileged() && !$this->scoped->hasRole(Profile_role::ADMINISTRATOR)) { + $this->clientError(_('You cannot sandbox other privileged users.'), 403); + } + + // only sandbox of the user isn't sandboxed + if (!$this->other->isSandboxed()) { + try { + $this->other->sandbox(); + } catch (Exception $e) { + $this->clientError($e->getMessage(), $e->getCode()); + } + } + + $this->initDocument('json'); + $this->showJsonObjects($this->twitterUserArray($this->other)); + $this->endDocument('json'); + } +} diff --git a/actions/apiqvittersandboxdestroy.php b/actions/apiqvittersandboxdestroy.php new file mode 100644 index 0000000..1b55e23 --- /dev/null +++ b/actions/apiqvittersandboxdestroy.php @@ -0,0 +1,103 @@ + \\\\_\ · + · \\) \____) · + · · + · · + · · + · Qvitter is free software: you can redistribute it and / or modify it · + · under the terms of the GNU Affero General Public License as published by · + · the Free Software Foundation, either version three of the License or (at · + · your option) any later version. · + · · + · Qvitter is distributed in hope that it will be useful but WITHOUT ANY · + · WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS · + · FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for · + · more details. · + · · + · You should have received a copy of the GNU Affero General Public License · + · along with Qvitter. If not, see . · + · · + · Contact h@nnesmannerhe.im if you have any questions. · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */ + + +if (!defined('GNUSOCIAL')) { exit(1); } + +class ApiQvitterSandboxDestroyAction extends ApiAuthAction +{ + + protected $needPost = true; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + protected function prepare(array $args=array()) + { + parent::prepare($args); + + $this->format = 'json'; + + $this->other = $this->getTargetProfile($this->arg('id')); + + return true; + } + + /** + * Handle the request + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + protected function handle() + { + parent::handle(); + + if (!$this->other instanceof Profile) { + $this->clientError(_('No such user.'), 404); + } + + if ($this->scoped->id == $this->other->id) { + $this->clientError(_("You cannot unsandbox yourself!"), 403); + } + + if (!$this->scoped->hasRight(Right::SANDBOXUSER)) { + $this->clientError(_('You cannot unsandbox users on this site.'), 403); + } + + // only unsandbox if the user is sandboxed + if ($this->other->isSandboxed()) { + try { + $this->other->unsandbox(); + } catch (Exception $e) { + $this->clientError($e->getMessage(), $e->getCode()); + } + } + + $this->initDocument('json'); + $this->showJsonObjects($this->twitterUserArray($this->other)); + $this->endDocument('json'); + } +} diff --git a/actions/apiqvittersandboxed.php b/actions/apiqvittersandboxed.php index f0d3bd1..cc87210 100644 --- a/actions/apiqvittersandboxed.php +++ b/actions/apiqvittersandboxed.php @@ -110,10 +110,7 @@ class ApiQvitterSandboxedAction extends ApiPrivateAuthAction $profile = $this->getSandboxed( ($this->page - 1) * $this->count, - $this->count, - $this->since_id, - $this->max_id - ); + $this->count); while ($profile->fetch()) { $profiles[] = clone($profile); @@ -130,6 +127,7 @@ class ApiQvitterSandboxedAction extends ApiPrivateAuthAction function getSandboxed($offset=null, $limit=null) // offset is null because DataObject wants it, 0 would mean no results { + $profiles = new Profile(); $profiles->joinAdd(array('id', 'profile_role:profile_id')); $profiles->whereAdd(sprintf('profile_role.role = \'%s\'', Profile_role::SANDBOXED)); diff --git a/actions/apiqvittersilencecreate.php b/actions/apiqvittersilencecreate.php index 1383067..b465077 100644 --- a/actions/apiqvittersilencecreate.php +++ b/actions/apiqvittersilencecreate.php @@ -44,6 +44,7 @@ if (!defined('GNUSOCIAL')) { exit(1); } class ApiQvitterSilenceCreateAction extends ApiAuthAction { + protected $needPost = true; /** * Take arguments for running @@ -56,6 +57,8 @@ class ApiQvitterSilenceCreateAction extends ApiAuthAction { parent::prepare($args); + $this->format = 'json'; + $this->other = $this->getTargetProfile($this->arg('id')); return true; @@ -82,6 +85,10 @@ class ApiQvitterSilenceCreateAction extends ApiAuthAction try { $this->other->silenceAs($this->scoped); + } catch (AlreadyFulfilledException $e) { + // don't throw client error here, just return the user array like + // if we successfully silenced the user. the client is only interested + // in making sure the user is silenced. } catch (Exception $e) { $this->clientError($e->getMessage(), $e->getCode()); } diff --git a/actions/apiqvittersilenced.php b/actions/apiqvittersilenced.php index 1f97ab3..5f29169 100644 --- a/actions/apiqvittersilenced.php +++ b/actions/apiqvittersilenced.php @@ -110,10 +110,7 @@ class ApiQvitterSilencedAction extends ApiPrivateAuthAction $profile = $this->getSilenced( ($this->page - 1) * $this->count, - $this->count, - $this->since_id, - $this->max_id - ); + $this->count); while ($profile->fetch()) { $profiles[] = clone($profile); diff --git a/actions/apiqvittersilencedestroy.php b/actions/apiqvittersilencedestroy.php new file mode 100644 index 0000000..92e206a --- /dev/null +++ b/actions/apiqvittersilencedestroy.php @@ -0,0 +1,100 @@ + \\\\_\ · + · \\) \____) · + · · + · · + · · + · Qvitter is free software: you can redistribute it and / or modify it · + · under the terms of the GNU Affero General Public License as published by · + · the Free Software Foundation, either version three of the License or (at · + · your option) any later version. · + · · + · Qvitter is distributed in hope that it will be useful but WITHOUT ANY · + · WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS · + · FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for · + · more details. · + · · + · You should have received a copy of the GNU Affero General Public License · + · along with Qvitter. If not, see . · + · · + · Contact h@nnesmannerhe.im if you have any questions. · + · · + · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */ + + +if (!defined('GNUSOCIAL')) { exit(1); } + +class ApiQvitterSilenceDestroyAction extends ApiAuthAction +{ + + protected $needPost = true; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + protected function prepare(array $args=array()) + { + parent::prepare($args); + + $this->format = 'json'; + + $this->other = $this->getTargetProfile($this->arg('id')); + + return true; + } + + /** + * Handle the request + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + protected function handle() + { + parent::handle(); + + if (!$this->other instanceof Profile) { + $this->clientError(_('No such user.'), 404); + } + + if ($this->scoped->id == $this->other->id) { + $this->clientError(_("You cannot unsilence yourself!"), 403); + } + + try { + $this->other->unsilenceAs($this->scoped); + } catch (AlreadyFulfilledException $e) { + // don't throw client error here, just return the user array like + // if we successfully unsilenced the user. the client is only interested + // in making sure the user is unsilenced. + } catch (Exception $e) { + $this->clientError($e->getMessage(), $e->getCode()); + } + + $this->initDocument('json'); + $this->showJsonObjects($this->twitterUserArray($this->other)); + $this->endDocument('json'); + } +} diff --git a/actions/qvitter.php b/actions/qvitter.php index fcc1c75..79f263b 100644 --- a/actions/qvitter.php +++ b/actions/qvitter.php @@ -429,7 +429,19 @@ class QvitterAction extends ApiAction ?> - "> + "> -
  • +
  • -
  • -
  • -
  • @@ -480,6 +489,8 @@ class QvitterAction extends ApiAction
  • + +