]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/ActivitySpam/ActivitySpamPlugin.php
Cannot use NoticeListemItem as type-hint as NoticeListItemAdapter exists.
[quix0rs-gnu-social.git] / plugins / ActivitySpam / ActivitySpamPlugin.php
1 <?php
2 /**
3  * StatusNet - the distributed open-source microblogging tool
4  * Copyright (C) 2011,2012, StatusNet, Inc.
5  *
6  * ActivitySpam Plugin
7  *
8  * PHP version 5
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Affero General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Affero General Public License for more details.
19  *
20  * You should have received a copy of the GNU Affero General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * @category  Spam
24  * @package   StatusNet
25  * @author    Evan Prodromou <evan@status.net>
26  * @copyright 2011,2012 StatusNet, Inc.
27  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
28  * @link      http://status.net/
29  */
30
31 if (!defined('STATUSNET')) {
32     // This check helps protect against security problems;
33     // your code file can't be executed directly from the web.
34     exit(1);
35 }
36
37 /**
38  * Check new notices with activity spam service.
39  *
40  * @category  Spam
41  * @package   StatusNet
42  * @author    Evan Prodromou <evan@status.net>
43  * @copyright 2011,2012 StatusNet, Inc.
44  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
45  * @link      http://status.net/
46  */
47 class ActivitySpamPlugin extends Plugin
48 {
49     const PLUGIN_VERSION = '2.0.0';
50
51     public $server = null;
52     public $hideSpam = false;
53
54     const REVIEWSPAM = 'ActivitySpamPlugin::REVIEWSPAM';
55     const TRAINSPAM = 'ActivitySpamPlugin::TRAINSPAM';
56
57     /**
58      * Initializer
59      *
60      * @return boolean hook value; true means continue processing, false means stop.
61      */
62     function initialize()
63     {
64         $this->filter = new SpamFilter(common_config('activityspam', 'server'),
65                                        common_config('activityspam', 'consumerkey'),
66                                        common_config('activityspam', 'secret'));
67
68         $this->hideSpam = common_config('activityspam', 'hidespam');
69
70         // Let DB_DataObject find Spam_score
71
72         common_config_set('db', 'class_location',
73                           common_config('db', 'class_location') .':'.dirname(__FILE__));
74
75         return true;
76     }
77
78     /**
79      * Database schema setup
80      *
81      * @see Schema
82      * @see ColumnDef
83      *
84      * @return boolean hook value; true means continue processing, false means stop.
85      */
86
87     function onCheckSchema()
88     {
89         $schema = Schema::get();
90         $schema->ensureTable('spam_score', Spam_score::schemaDef());
91
92         Spam_score::upgrade();
93
94         return true;
95     }
96
97     /**
98      * When a notice is saved, check its spam score
99      *
100      * @param Notice $notice Notice that was just saved
101      *
102      * @return boolean hook value; true means continue processing, false means stop.
103      */
104
105     function onEndNoticeSave(Notice $notice)
106     {
107         try {
108
109             $result = $this->filter->test($notice);
110
111             $score = Spam_score::saveNew($notice, $result);
112
113             $this->log(LOG_INFO, "Notice " . $notice->id . " has spam score " . $score->score);
114
115         } catch (Exception $e) {
116             // Log but continue
117             $this->log(LOG_ERR, $e->getMessage());
118         }
119
120         return true;
121     }
122
123     function onNoticeDeleteRelated($notice) {
124         $score = Spam_score::getKV('notice_id', $notice->id);
125         if (!empty($score)) {
126             $score->delete();
127         }
128         return true;
129     }
130
131     function onUserRightsCheck($profile, $right, &$result) {
132         switch ($right) {
133         case self::REVIEWSPAM:
134         case self::TRAINSPAM:
135             $result = ($profile->hasRole(Profile_role::MODERATOR) || $profile->hasRole('modhelper'));
136             return false;
137         default:
138             return true;
139         }
140     }
141
142     function onGetSpamFilter(&$filter) {
143         $filter = $this->filter;
144         return false;
145     }
146
147     function onEndShowNoticeOptionItems($nli)
148     {
149         // FIXME: Cannot use type-hint NoticeListItem as NoticeListItemAdapter exists, too!
150         assert(is_object($nli));
151
152         $profile = Profile::current();
153
154         if (!empty($profile) && $profile->hasRight(self::TRAINSPAM)) {
155
156             $notice = $nli->getNotice();
157             $out = $nli->getOut();
158
159             if (!empty($notice)) {
160
161                 $score = Spam_score::getKV('notice_id', $notice->id);
162
163                 if (empty($score)) {
164                     // If it's empty, we can train it.
165                     $form = new TrainSpamForm($out, $notice);
166                     $form->show();
167                 } else if ($score->is_spam) {
168                     $form = new TrainHamForm($out, $notice);
169                     $form->show();
170                 } else if (!$score->is_spam) {
171                     $form = new TrainSpamForm($out, $notice);
172                     $form->show();
173                 }
174             }
175         }
176
177         return true;
178     }
179
180     /**
181      * Map URLs to actions
182      *
183      * @param URLMapper $m path-to-action mapper
184      *
185      * @return boolean hook value; true means continue processing, false means stop.
186      */
187
188     public function onRouterInitialized(URLMapper $m)
189     {
190         $m->connect('main/train/spam',
191                     ['action' => 'train',
192                      'category' => 'spam']);
193         $m->connect('main/train/ham',
194                     ['action' => 'train',
195                      'category' => 'ham']);
196         $m->connect('main/spam',
197                     ['action' => 'spam']);
198         return true;
199     }
200
201     function onEndShowStyles($action)
202     {
203         $action->element('style', null,
204                          '.form-train-spam input.submit { background: url('.$this->path('icons/bullet_black.png').') no-repeat 0px 0px } ' . "\n" .
205                          '.form-train-ham input.submit { background: url('.$this->path('icons/exclamation.png').') no-repeat 0px 0px } ');
206         return true;
207     }
208
209     function onEndPublicGroupNav(Menu $nav)
210     {
211         $user = common_current_user();
212
213         if (!empty($user) && $user->hasRight(self::REVIEWSPAM)) {
214             $nav->out->menuItem(common_local_url('spam'),
215                                 _m('MENU','Spam'),
216                                 // TRANS: Menu item title in search group navigation panel.
217                                 _('Notices marked as spam'),
218                                 $nav->actionName == 'spam',
219                                 'nav_timeline_spam');
220         }
221
222         return true;
223     }
224
225     function onPluginVersion(array &$versions)
226     {
227         $versions[] = array('name' => 'ActivitySpam',
228                             'version' => self::PLUGIN_VERSION,
229                             'author' => 'Evan Prodromou',
230                             'homepage' => 'https://git.gnu.io/gnu/gnu-social/tree/master/plugins/ActivitySpam',
231                             'description' =>
232                             _m('Test notices against the Activity Spam service.'));
233         return true;
234     }
235
236     function onEndNoticeInScope(Notice $notice, Profile $profile, &$bResult)
237     {
238         if ($this->hideSpam) {
239             if ($bResult) {
240
241                 $score = Spam_score::getKV('notice_id', $notice->id);
242
243                 if (!empty($score) && $score->is_spam) {
244                     if (empty($profile) ||
245                         ($profile->id !== $notice->profile_id &&
246                          !$profile->hasRight(self::REVIEWSPAM))) {
247                         $bResult = false;
248                     }
249                 }
250             }
251         }
252
253         return true;
254     }
255
256     /**
257      * Pre-cache our spam scores if needed.
258      */
259     function onEndNoticeListPrefill(array &$notices, array &$profiles, array $notice_ids, Profile $scoped=null) {
260         if ($this->hideSpam) {
261             Spam_score::multiGet('notice_id', $notice_ids);
262         }
263         return true;
264     }
265 }