commit 2762cf5f998e76c603b59f164bf441ba7ff3c373 Author: Toby Zerner Date: Fri Sep 4 12:44:02 2015 +0930 Initial commit diff --git a/extensions/akismet/.editorconfig b/extensions/akismet/.editorconfig new file mode 100644 index 000000000..87694ddab --- /dev/null +++ b/extensions/akismet/.editorconfig @@ -0,0 +1,19 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 2 + +[*.{diff,md}] +trim_trailing_whitespace = false + +[*.php] +indent_size = 4 diff --git a/extensions/akismet/.eslintignore b/extensions/akismet/.eslintignore new file mode 100644 index 000000000..86b7c8854 --- /dev/null +++ b/extensions/akismet/.eslintignore @@ -0,0 +1,5 @@ +**/bower_components/**/* +**/node_modules/**/* +vendor/**/* +**/Gulpfile.js +**/dist/**/* diff --git a/extensions/akismet/.eslintrc b/extensions/akismet/.eslintrc new file mode 100644 index 000000000..9e89e6ba6 --- /dev/null +++ b/extensions/akismet/.eslintrc @@ -0,0 +1,175 @@ +{ + "parser": "babel-eslint", // https://github.com/babel/babel-eslint + "env": { // http://eslint.org/docs/user-guide/configuring.html#specifying-environments + "browser": true // browser global variables + }, + "ecmaFeatures": { + "arrowFunctions": true, + "blockBindings": true, + "classes": true, + "defaultParams": true, + "destructuring": true, + "forOf": true, + "generators": false, + "modules": true, + "objectLiteralComputedProperties": true, + "objectLiteralDuplicateProperties": false, + "objectLiteralShorthandMethods": true, + "objectLiteralShorthandProperties": true, + "spread": true, + "superInFunctions": true, + "templateStrings": true, + "jsx": true + }, + "globals": { + "m": true, + "app": true, + "$": true, + "moment": true + }, + "plugins": [ + "react" + ], + "rules": { + "react/jsx-uses-vars": 1, + +/** + * Strict mode + */ + // babel inserts "use strict"; for us + "strict": [2, "never"], // http://eslint.org/docs/rules/strict + +/** + * ES6 + */ + "no-var": 2, // http://eslint.org/docs/rules/no-var + "prefer-const": 2, // http://eslint.org/docs/rules/prefer-const + +/** + * Variables + */ + "no-shadow": 2, // http://eslint.org/docs/rules/no-shadow + "no-shadow-restricted-names": 2, // http://eslint.org/docs/rules/no-shadow-restricted-names + "no-unused-vars": [2, { // http://eslint.org/docs/rules/no-unused-vars + "vars": "local", + "args": "after-used" + }], + "no-use-before-define": 2, // http://eslint.org/docs/rules/no-use-before-define + +/** + * Possible errors + */ + "comma-dangle": [2, "never"], // http://eslint.org/docs/rules/comma-dangle + "no-cond-assign": [2, "always"], // http://eslint.org/docs/rules/no-cond-assign + "no-console": 1, // http://eslint.org/docs/rules/no-console + "no-debugger": 1, // http://eslint.org/docs/rules/no-debugger + "no-alert": 1, // http://eslint.org/docs/rules/no-alert + "no-constant-condition": 1, // http://eslint.org/docs/rules/no-constant-condition + "no-dupe-keys": 2, // http://eslint.org/docs/rules/no-dupe-keys + "no-duplicate-case": 2, // http://eslint.org/docs/rules/no-duplicate-case + "no-empty": 2, // http://eslint.org/docs/rules/no-empty + "no-ex-assign": 2, // http://eslint.org/docs/rules/no-ex-assign + "no-extra-boolean-cast": 0, // http://eslint.org/docs/rules/no-extra-boolean-cast + "no-extra-semi": 2, // http://eslint.org/docs/rules/no-extra-semi + "no-func-assign": 2, // http://eslint.org/docs/rules/no-func-assign + "no-inner-declarations": 2, // http://eslint.org/docs/rules/no-inner-declarations + "no-invalid-regexp": 2, // http://eslint.org/docs/rules/no-invalid-regexp + "no-irregular-whitespace": 2, // http://eslint.org/docs/rules/no-irregular-whitespace + "no-obj-calls": 2, // http://eslint.org/docs/rules/no-obj-calls + "no-reserved-keys": 2, // http://eslint.org/docs/rules/no-reserved-keys + "no-sparse-arrays": 2, // http://eslint.org/docs/rules/no-sparse-arrays + "no-unreachable": 2, // http://eslint.org/docs/rules/no-unreachable + "use-isnan": 2, // http://eslint.org/docs/rules/use-isnan + "block-scoped-var": 2, // http://eslint.org/docs/rules/block-scoped-var + +/** + * Best practices + */ + "consistent-return": 2, // http://eslint.org/docs/rules/consistent-return + "curly": [2, "multi-line"], // http://eslint.org/docs/rules/curly + "default-case": 2, // http://eslint.org/docs/rules/default-case + "dot-notation": [2, { // http://eslint.org/docs/rules/dot-notation + "allowKeywords": true + }], + "eqeqeq": 2, // http://eslint.org/docs/rules/eqeqeq + "no-caller": 2, // http://eslint.org/docs/rules/no-caller + "no-else-return": 2, // http://eslint.org/docs/rules/no-else-return + "no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null + "no-eval": 2, // http://eslint.org/docs/rules/no-eval + "no-extend-native": 2, // http://eslint.org/docs/rules/no-extend-native + "no-extra-bind": 2, // http://eslint.org/docs/rules/no-extra-bind + "no-fallthrough": 2, // http://eslint.org/docs/rules/no-fallthrough + "no-floating-decimal": 2, // http://eslint.org/docs/rules/no-floating-decimal + "no-implied-eval": 2, // http://eslint.org/docs/rules/no-implied-eval + "no-lone-blocks": 2, // http://eslint.org/docs/rules/no-lone-blocks + "no-loop-func": 2, // http://eslint.org/docs/rules/no-loop-func + "no-multi-str": 2, // http://eslint.org/docs/rules/no-multi-str + "no-native-reassign": 2, // http://eslint.org/docs/rules/no-native-reassign + "no-new": 2, // http://eslint.org/docs/rules/no-new + "no-new-func": 2, // http://eslint.org/docs/rules/no-new-func + "no-new-wrappers": 2, // http://eslint.org/docs/rules/no-new-wrappers + "no-octal": 2, // http://eslint.org/docs/rules/no-octal + "no-octal-escape": 2, // http://eslint.org/docs/rules/no-octal-escape + "no-param-reassign": 2, // http://eslint.org/docs/rules/no-param-reassign + "no-proto": 2, // http://eslint.org/docs/rules/no-proto + "no-redeclare": 2, // http://eslint.org/docs/rules/no-redeclare + "no-return-assign": 2, // http://eslint.org/docs/rules/no-return-assign + "no-self-compare": 2, // http://eslint.org/docs/rules/no-self-compare + "no-sequences": 2, // http://eslint.org/docs/rules/no-sequences + "no-throw-literal": 2, // http://eslint.org/docs/rules/no-throw-literal + "no-with": 2, // http://eslint.org/docs/rules/no-with + "radix": 2, // http://eslint.org/docs/rules/radix + "vars-on-top": 2, // http://eslint.org/docs/rules/vars-on-top + "wrap-iife": [2, "any"], // http://eslint.org/docs/rules/wrap-iife + "yoda": 2, // http://eslint.org/docs/rules/yoda + +/** + * Style + */ + "indent": [2, 2], // http://eslint.org/docs/rules/indent + "brace-style": [2, // http://eslint.org/docs/rules/brace-style + "1tbs", { + "allowSingleLine": true + }], + "quotes": [ + 2, "single", "avoid-escape" // http://eslint.org/docs/rules/quotes + ], + "camelcase": [2, { // http://eslint.org/docs/rules/camelcase + "properties": "never" + }], + "comma-spacing": [2, { // http://eslint.org/docs/rules/comma-spacing + "before": false, + "after": true + }], + "comma-style": [2, "last"], // http://eslint.org/docs/rules/comma-style + "eol-last": 2, // http://eslint.org/docs/rules/eol-last + "key-spacing": [2, { // http://eslint.org/docs/rules/key-spacing + "beforeColon": false, + "afterColon": true + }], + "new-cap": [2, { // http://eslint.org/docs/rules/new-cap + "newIsCap": true + }], + "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines + "max": 2 + }], + "no-new-object": 2, // http://eslint.org/docs/rules/no-new-object + "no-spaced-func": 2, // http://eslint.org/docs/rules/no-spaced-func + "no-trailing-spaces": 2, // http://eslint.org/docs/rules/no-trailing-spaces + "no-wrap-func": 2, // http://eslint.org/docs/rules/no-wrap-func + "no-underscore-dangle": 0, // http://eslint.org/docs/rules/no-underscore-dangle + "one-var": [2, "never"], // http://eslint.org/docs/rules/one-var + "padded-blocks": [2, "never"], // http://eslint.org/docs/rules/padded-blocks + "semi": [2, "always"], // http://eslint.org/docs/rules/semi + "semi-spacing": [2, { // http://eslint.org/docs/rules/semi-spacing + "before": false, + "after": true + }], + "space-after-keywords": 2, // http://eslint.org/docs/rules/space-after-keywords + "space-before-blocks": 2, // http://eslint.org/docs/rules/space-before-blocks + "space-before-function-paren": [2, "never"], // http://eslint.org/docs/rules/space-before-function-paren + "space-infix-ops": 2, // http://eslint.org/docs/rules/space-infix-ops + "space-return-throw-case": 2, // http://eslint.org/docs/rules/space-return-throw-case + "spaced-line-comment": 2, // http://eslint.org/docs/rules/spaced-line-comment + } +} diff --git a/extensions/akismet/.gitignore b/extensions/akismet/.gitignore new file mode 100644 index 000000000..a4f3b125e --- /dev/null +++ b/extensions/akismet/.gitignore @@ -0,0 +1,4 @@ +/vendor +composer.phar +.DS_Store +Thumbs.db diff --git a/extensions/akismet/.php_cs b/extensions/akismet/.php_cs new file mode 100755 index 000000000..20d29c766 --- /dev/null +++ b/extensions/akismet/.php_cs @@ -0,0 +1,26 @@ + + +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +EOF; + +Symfony\CS\Fixer\Contrib\HeaderCommentFixer::setHeader($header); + +$finder = Symfony\CS\Finder\DefaultFinder::create() + ->exclude('js') + ->exclude('less') + ->in(__DIR__); + +return Symfony\CS\Config\Config::create() + ->level(Symfony\CS\FixerInterface::PSR2_LEVEL) + ->fixers([ + 'short_array_syntax', + 'header_comment', + '-psr0' + ]) + ->finder($finder); diff --git a/extensions/akismet/.travis.yml b/extensions/akismet/.travis.yml new file mode 100644 index 000000000..692e09f86 --- /dev/null +++ b/extensions/akismet/.travis.yml @@ -0,0 +1,23 @@ +language: php + +php: + - 5.5 + - 5.6 + +matrix: + allow_failures: + - php: hhvm + fast_finish: true + +before_script: + - curl -s http://getcomposer.org/installer | php + - php composer.phar install + +script: + - php composer.phar style + +notifications: + email: + on_failure: change + +sudo: false diff --git a/extensions/akismet/LICENSE b/extensions/akismet/LICENSE new file mode 100644 index 000000000..aa1e5fb86 --- /dev/null +++ b/extensions/akismet/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2015 Toby Zerner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/extensions/akismet/bootstrap.php b/extensions/akismet/bootstrap.php new file mode 100644 index 000000000..763eda504 --- /dev/null +++ b/extensions/akismet/bootstrap.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require __DIR__.'/vendor/autoload.php'; + +return 'Flarum\Akismet\Extension'; diff --git a/extensions/akismet/composer.json b/extensions/akismet/composer.json new file mode 100644 index 000000000..a80d21fab --- /dev/null +++ b/extensions/akismet/composer.json @@ -0,0 +1,13 @@ +{ + "autoload": { + "psr-4": { + "Flarum\\Akismet\\": "src/" + } + }, + "require": { + "tijsverkoyen/akismet": "^1.1" + }, + "scripts": { + "style": "phpcs --standard=PSR2 -np src" + } +} diff --git a/extensions/akismet/composer.lock b/extensions/akismet/composer.lock new file mode 100644 index 000000000..c47b9ab9e --- /dev/null +++ b/extensions/akismet/composer.lock @@ -0,0 +1,57 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "f4f26918432f8f6ed40008ffd516708d", + "packages": [ + { + "name": "tijsverkoyen/akismet", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/Akismet.git", + "reference": "0c5185956e11824ed310d134d38d0b2c936f3d3a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/Akismet/zipball/0c5185956e11824ed310d134d38d0b2c936f3d3a", + "reference": "0c5185956e11824ed310d134d38d0b2c936f3d3a", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "akismet@verkoyen.eu", + "role": "Developer" + } + ], + "description": "Akismet is a wrapper-class to communicate with the Akismet API.", + "homepage": "https://github.com/tijsverkoyen/Akismet", + "time": "2012-10-13 17:59:41" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/extensions/akismet/flarum.json b/extensions/akismet/flarum.json new file mode 100644 index 000000000..5489efdac --- /dev/null +++ b/extensions/akismet/flarum.json @@ -0,0 +1,26 @@ +{ + "name": "akismet", + "title": "Akismet", + "description": "Stop spam using the Akismet anti-spam service.", + "keywords": [], + "version": "0.1.0-beta.2", + "author": { + "name": "Toby Zerner", + "email": "toby@flarum.org", + "homepage": "http://tobyzerner.com" + }, + "license": "MIT", + "require": { + "flarum": ">=0.1.0-beta.2", + "reports": ">=0.1.0-beta.2" + }, + "support": { + "source": "https://github.com/flarum/akismet", + "issues": "https://github.com/flarum/core/issues" + }, + "icon": { + "name": "filter", + "backgroundColor": "#5e8e14", + "color": "#fff" + } +} diff --git a/extensions/akismet/js/.gitignore b/extensions/akismet/js/.gitignore new file mode 100644 index 000000000..372e20a51 --- /dev/null +++ b/extensions/akismet/js/.gitignore @@ -0,0 +1,3 @@ +bower_components +node_modules +dist diff --git a/extensions/akismet/js/admin/Gulpfile.js b/extensions/akismet/js/admin/Gulpfile.js new file mode 100644 index 000000000..d67501f07 --- /dev/null +++ b/extensions/akismet/js/admin/Gulpfile.js @@ -0,0 +1,7 @@ +var gulp = require('flarum-gulp'); + +gulp({ + modules: { + 'akismet': 'src/**/*.js' + } +}); diff --git a/extensions/akismet/js/admin/package.json b/extensions/akismet/js/admin/package.json new file mode 100644 index 000000000..62ea6c691 --- /dev/null +++ b/extensions/akismet/js/admin/package.json @@ -0,0 +1,7 @@ +{ + "private": true, + "devDependencies": { + "gulp": "^3.8.11", + "flarum-gulp": "^0.1.0" + } +} diff --git a/extensions/akismet/js/admin/src/components/AkismetSettingsModal.js b/extensions/akismet/js/admin/src/components/AkismetSettingsModal.js new file mode 100644 index 000000000..dd0c62661 --- /dev/null +++ b/extensions/akismet/js/admin/src/components/AkismetSettingsModal.js @@ -0,0 +1,57 @@ +import Modal from 'flarum/components/Modal'; +import Button from 'flarum/components/Button'; +import saveConfig from 'flarum/utils/saveConfig'; + +export default class AkismetSettingsModal extends Modal { + constructor(...args) { + super(...args); + + this.apiKey = m.prop(app.config['akismet.api_key'] || ''); + } + + className() { + return 'AkismetSettingsModal Modal--small'; + } + + title() { + return 'Akismet Settings'; + } + + content() { + return ( +
+
+
+ + +
+ +
+ {Button.component({ + type: 'submit', + className: 'Button Button--primary AkismetSettingsModal-save', + loading: this.loading, + children: 'Save Changes' + })} +
+
+
+ ); + } + + onsubmit(e) { + e.preventDefault(); + + this.loading = true; + + saveConfig({ + 'akismet.api_key': this.apiKey() + }).then( + () => this.hide(), + () => { + this.loading = false; + m.redraw(); + } + ); + } +} diff --git a/extensions/akismet/js/admin/src/main.js b/extensions/akismet/js/admin/src/main.js new file mode 100644 index 000000000..717203d6a --- /dev/null +++ b/extensions/akismet/js/admin/src/main.js @@ -0,0 +1,8 @@ +import { extend } from 'flarum/extend'; +import app from 'flarum/app'; + +import AkismetSettingsModal from 'akismet/components/AkismetSettingsModal'; + +app.initializers.add('akismet', () => { + app.extensionSettings.akismet = () => app.modal.show(new AkismetSettingsModal()); +}); diff --git a/extensions/akismet/js/forum/Gulpfile.js b/extensions/akismet/js/forum/Gulpfile.js new file mode 100644 index 000000000..d67501f07 --- /dev/null +++ b/extensions/akismet/js/forum/Gulpfile.js @@ -0,0 +1,7 @@ +var gulp = require('flarum-gulp'); + +gulp({ + modules: { + 'akismet': 'src/**/*.js' + } +}); diff --git a/extensions/akismet/js/forum/package.json b/extensions/akismet/js/forum/package.json new file mode 100644 index 000000000..62ea6c691 --- /dev/null +++ b/extensions/akismet/js/forum/package.json @@ -0,0 +1,7 @@ +{ + "private": true, + "devDependencies": { + "gulp": "^3.8.11", + "flarum-gulp": "^0.1.0" + } +} diff --git a/extensions/akismet/js/forum/src/main.js b/extensions/akismet/js/forum/src/main.js new file mode 100644 index 000000000..5215ad8ac --- /dev/null +++ b/extensions/akismet/js/forum/src/main.js @@ -0,0 +1,24 @@ +import { extend } from 'flarum/extend'; +import app from 'flarum/app'; + +import Button from 'flarum/components/Button'; +import CommentPost from 'flarum/components/CommentPost'; +import PostControls from 'flarum/utils/PostControls'; + +app.initializers.add('akismet', () => { + extend(CommentPost.prototype, 'reportActionItems', function(items) { + if (this.props.post.reports()[0].reporter() === 'Akismet') { + items.add('notSpam', + + ); + } + }); +}, -10); // set initializer priority to run after reports diff --git a/extensions/akismet/locale/en.yml b/extensions/akismet/locale/en.yml new file mode 100644 index 000000000..4df16ec26 --- /dev/null +++ b/extensions/akismet/locale/en.yml @@ -0,0 +1,2 @@ +akismet: + # hello_world: "Hello, world!" diff --git a/extensions/akismet/src/Extension.php b/extensions/akismet/src/Extension.php new file mode 100644 index 000000000..acb4901f6 --- /dev/null +++ b/extensions/akismet/src/Extension.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Akismet; + +use Flarum\Support\Extension as BaseExtension; +use Illuminate\Events\Dispatcher; + +class Extension extends BaseExtension +{ + public function listen(Dispatcher $events) + { + $events->subscribe('Flarum\Akismet\Listeners\AddClientAssets'); + $events->subscribe('Flarum\Akismet\Listeners\ValidatePost'); + } +} diff --git a/extensions/akismet/src/Listeners/AddClientAssets.php b/extensions/akismet/src/Listeners/AddClientAssets.php new file mode 100644 index 000000000..854d60c77 --- /dev/null +++ b/extensions/akismet/src/Listeners/AddClientAssets.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Akismet\Listeners; + +use Flarum\Events\RegisterLocales; +use Flarum\Events\BuildClientView; +use Illuminate\Contracts\Events\Dispatcher; + +class AddClientAssets +{ + public function subscribe(Dispatcher $events) + { + $events->listen(RegisterLocales::class, [$this, 'addLocale']); + $events->listen(BuildClientView::class, [$this, 'addAssets']); + } + + public function addLocale(RegisterLocales $event) + { + $event->addTranslations('en', __DIR__.'/../../locale/en.yml'); + } + + public function addAssets(BuildClientView $event) + { + $event->forumAssets([ + __DIR__.'/../../js/forum/dist/extension.js' + ]); + + $event->forumBootstrapper('akismet/main'); + + $event->forumTranslations([ + // 'akismet.hello_world' + ]); + + $event->adminAssets([ + __DIR__.'/../../js/admin/dist/extension.js' + ]); + + $event->adminBootstrapper('akismet/main'); + + $event->adminTranslations([ + // 'akismet.hello_world' + ]); + } +} diff --git a/extensions/akismet/src/Listeners/ValidatePost.php b/extensions/akismet/src/Listeners/ValidatePost.php new file mode 100644 index 000000000..e74d14cd4 --- /dev/null +++ b/extensions/akismet/src/Listeners/ValidatePost.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Akismet\Listeners; + +use Flarum\Events\PostWillBeSaved; +use Illuminate\Contracts\Events\Dispatcher; +use TijsVerkoyen\Akismet\Akismet; +use Flarum\Core; +use Flarum\Core\Posts\CommentPost; +use Flarum\Core\Settings\SettingsRepository; +use Flarum\Report\Report; + +class ValidatePost +{ + protected $settings; + + private $savingPost; + + public function __construct(SettingsRepository $settings) + { + $this->settings = $settings; + } + + public function subscribe(Dispatcher $events) + { + $events->listen(PostWillBeSaved::class, [$this, 'validatePost']); + } + + public function validatePost(PostWillBeSaved $event) + { + $post = $event->post; + + if ($post->exists || $post->user->groups()->count()) { + return; + } + + $akismet = new Akismet($this->settings->get('akismet.api_key'), Core::url()); + + $isSpam = $akismet->isSpam( + $post->content, + $post->user->username, + $post->user->email, + null, + 'comment' + ); + + if ($isSpam) { + $post->hide(); + + $this->savingPost = $post; + + CommentPost::saved(function (CommentPost $post) { + if ($post !== $this->savingPost) { + return; + } + + $report = new Report; + + $report->post_id = $post->id; + $report->reporter = 'Akismet'; + $report->reason = 'spam'; + $report->time = time(); + + $report->save(); + + $this->savingPost = null; + }); + } + } +}