3 * StatusNet - the distributed open-source microblogging tool
4 * Copyright (C) 2012, StatusNet, Inc.
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.
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.
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/>.
25 * @author Evan Prodromou <evan@status.net>
26 * @copyright 2012 StatusNet, Inc.
27 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
28 * @link http://status.net/
31 if (!defined('STATUSNET')) {
32 // This check helps protect against security problems;
33 // your code file can't be executed directly from the web.
40 * Local proxy for remote filter
44 * @author Evan Prodromou <evan@status.net>
45 * @copyright 2012 StatusNet, Inc.
46 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
47 * @link http://status.net/
50 class SpamFilter extends OAuthClient {
57 function __construct($server, $consumerKey, $secret) {
58 parent::__construct($consumerKey, $secret);
59 $this->server = $server;
62 protected function toActivity($notice) {
63 // FIXME: need this to autoload ActivityStreamsMediaLink
64 $doc = new ActivityStreamJSONDocument();
66 $activity = $notice->asActivity(null);
71 public function test($notice) {
73 $activity = $this->toActivity($notice);
74 return $this->testActivity($activity);
77 public function testActivity($activity) {
79 $response = $this->postJSON($this->server . "/is-this-spam", $activity->asArray());
81 $result = json_decode($response->getBody());
86 public function train($notice, $category) {
88 $activity = $this->toActivity($notice);
89 return $this->trainActivity($activity, $category);
93 public function trainActivity($activity, $category) {
97 $endpoint = '/this-is-ham';
100 $endpoint = '/this-is-spam';
103 throw new Exception("Unknown category: " + $category);
106 $response = $this->postJSON($this->server . $endpoint, $activity->asArray());
108 // We don't do much with the results
112 public function trainOnError($notice, $category) {
114 $activity = $this->toActivity($notice);
116 return $this->trainActivityOnError($activity, $category);
119 public function trainActivityOnError($activity, $category) {
121 $result = $this->testActivity($activity);
123 if (($category === self::SPAM && $result->isSpam) ||
124 ($category === self::HAM && !$result->isSpam)) {
127 return $this->trainActivity($activity, $category);
131 function postJSON($url, $body)
133 $request = OAuthRequest::from_consumer_and_token($this->consumer,
138 $request->sign_request($this->sha1_method,
142 $hclient = new HTTPClient($url);
144 $hclient->setConfig(array('connect_timeout' => 120,
146 'follow_redirects' => true,
147 'ssl_verify_peer' => false,
148 'ssl_verify_host' => false));
150 $hclient->setMethod(HTTP_Request2::METHOD_POST);
151 $hclient->setBody(json_encode($body));
152 $hclient->setHeader('Content-Type', 'application/json');
153 $hclient->setHeader($request->to_header());
155 // Twitter is strict about accepting invalid "Expect" headers
156 // No reason not to clear it still here -ESP
158 $hclient->setHeader('Expect', '');
161 $response = $hclient->send();
162 $code = $response->getStatus();
163 if (!$response->isOK()) {
164 throw new OAuthClientException($response->getBody(), $code);
167 } catch (Exception $e) {
168 throw new OAuthClientException($e->getMessage(), $e->getCode());