FEATURE: Various improvements and refactoring (#32)

FEATURE: Various improvements and refactoring (#32)

  • FEATURE: Show Akismet status in flag post modal

This can help understand why some posts were marked as spam or not by Akismet.

  • DEV: Move all styles into a single stylesheet

Both previous stylesheets combined have less than 15 lines together.

  • FEATURE: Send feedback for posts belonging to spammers

  • DEV: Prefer require_relative to load dependencies

  • FIX: Ensure post is checked when raw changes

This solves two edge cases. The first one is the basic one when the user simply edits the post, which did not trigger a re-check of new raw.

The other case is more complicated and exploits the fact that deleted posts are skipped. Users can post spam, quickly delete the post, wait for the post to be processed and skipped because it is deleted and then restore it with the spam content.

  • FIX: Resolve all reviewables of a user

Acting on an Akismet reviewable did not automatically update the status of all other reviewable or submit feedback.

  • DEV: Rename state new to pending

  • UX: Add descriptions to reviewable actions

  • DEV: Remove Excon stubs

Excon stubs used to leak between tests.

diff --git a/assets/javascripts/discourse-akismet/connectors/admin-users-list-icon/akismet-icon.hbs b/assets/javascripts/discourse-akismet/connectors/admin-users-list-icon/akismet-icon.hbs
index 694590a..96cb692 100644
--- a/assets/javascripts/discourse-akismet/connectors/admin-users-list-icon/akismet-icon.hbs
+++ b/assets/javascripts/discourse-akismet/connectors/admin-users-list-icon/akismet-icon.hbs
@@ -1,9 +1,3 @@
-{{#if new}}
-  {{d-icon "far-clock" title=(concat "admin.akismet_states." user.akismet_state)}}
-{{else if skipped}}
-  {{d-icon "question" title=(concat "admin.akismet_states." user.akismet_state)}}
-{{else if checked}}
-  {{d-icon "check" title=(concat "admin.akismet_states." user.akismet_state)}}
-{{else if spam}}
-  {{d-icon "times" title=(concat "admin.akismet_states." user.akismet_state)}}
+{{#if user.akismet_state}}
+  {{d-icon icon title=(concat "akismet.user_state." user.akismet_state)}}
 {{/if}}
diff --git a/assets/javascripts/discourse-akismet/connectors/admin-users-list-icon/akismet-icon.js.es6 b/assets/javascripts/discourse-akismet/connectors/admin-users-list-icon/akismet-icon.js.es6
index a74b832..dab4e86 100644
--- a/assets/javascripts/discourse-akismet/connectors/admin-users-list-icon/akismet-icon.js.es6
+++ b/assets/javascripts/discourse-akismet/connectors/admin-users-list-icon/akismet-icon.js.es6
@@ -4,10 +4,19 @@ export default {
   },
 
   setupComponent(args, component) {
-    const state = args.user.akismet_state;
-    component.set("new", state === "new");
-    component.set("skipped", state === "skipped");
-    component.set("checked", state === "confirmed_ham");
-    component.set("spam", state === "confirmed_spam");
+    switch (args.user.akismet_state) {
+      case "pending":
+        component.set("icon", "far-clock");
+        break;
+      case "skipped":
+        component.set("icon", "question");
+        break;
+      case "confirmed_ham":
+        component.set("icon", "check");
+        break;
+      case "confirmed_spam":
+        component.set("icon", "times");
+        break;
+    }
   },
 };
diff --git a/assets/javascripts/discourse-akismet/connectors/flag-modal-bottom/akismet-status.hbs b/assets/javascripts/discourse-akismet/connectors/flag-modal-bottom/akismet-status.hbs
new file mode 100644
index 0000000..e9aa88c
--- /dev/null
+++ b/assets/javascripts/discourse-akismet/connectors/flag-modal-bottom/akismet-status.hbs
@@ -0,0 +1,3 @@
+<div class="consent_banner alert alert-info">
+  <span>{{i18n (concat "akismet.post_state." (or post.akismet_state "skipped"))}}.</span>
+</div>
diff --git a/assets/javascripts/discourse-akismet/connectors/flag-modal-bottom/akismet-status.js.es6 b/assets/javascripts/discourse-akismet/connectors/flag-modal-bottom/akismet-status.js.es6
new file mode 100644
index 0000000..fc279ea
--- /dev/null
+++ b/assets/javascripts/discourse-akismet/connectors/flag-modal-bottom/akismet-status.js.es6
@@ -0,0 +1,5 @@
+export default {
+  setupComponent(args, component) {
+    component.set("post", args.post);
+  },
+};
diff --git a/assets/javascripts/discourse/initializers/add-akismet-state.js.es6 b/assets/javascripts/discourse/initializers/add-akismet-state.js.es6
new file mode 100644
index 0000000..27dd793
--- /dev/null
+++ b/assets/javascripts/discourse/initializers/add-akismet-state.js.es6
@@ -0,0 +1,11 @@
+import { withPluginApi } from "discourse/lib/plugin-api";
+
+export default {
+  name: "add-akismet-state",
+
+  initialize() {
+    withPluginApi("0.8.31", (api) => {
+      api.includePostAttributes("akismet_state");
+    });
+  },
+};
diff --git a/assets/stylesheets/akismet-icon.scss b/assets/stylesheets/akismet-icon.scss
deleted file mode 100644
index d6777fe..0000000
--- a/assets/stylesheets/akismet-icon.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.akismet-icon {
-  display: inline-block;
-}
diff --git a/assets/stylesheets/akismet.scss b/assets/stylesheets/akismet.scss
new file mode 100644
index 0000000..9b8a523
--- /dev/null
+++ b/assets/stylesheets/akismet.scss
@@ -0,0 +1,13 @@
+.akismet-icon {
+  display: inline-block;
+}
+
+.reviewable-akismet-post {
+  .created-by {
+    margin-right: 1em;
+  }
+
+  .reviewable-scores {
+    width: 100%;
+  }
+}
diff --git a/assets/stylesheets/reviewable-akismet-post-styles.scss b/assets/stylesheets/reviewable-akismet-post-styles.scss
deleted file mode 100644
index 0fea259..0000000
--- a/assets/stylesheets/reviewable-akismet-post-styles.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-.reviewable-akismet-post {
-  .created-by {
-    margin-right: 1em;
-  }
-
-  .reviewable-scores {
-    width: 100%;
-  }
-}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 4507f1f..3667603 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -7,27 +7,34 @@ en:
             confirmed_ham: "Not spam"
             confirmed_spam: "Confirm spam"
             confirmed_spam_deleted: "Confirm spam and delete user"
-            dismissed: 'Dismiss spam'
-            ignored: 'Ignore spam'
-      akismet_states:
-        new: Akismet hasn't check this user for spam yet.
-        skipped: This user doesn't have enough information to be reviewed by Akismet.
-        confirmed_ham: Akismet checked this user and decided that it's not spam.
-        confirmed_spam: Akismet decided that this user is spam.
+            dismissed: "Dismiss spam"
+            ignored: "Ignore spam"
       akismet_api_error: "Akismet API Error:"
-            
+
     akismet:
       title: "Akismet"
-      confirm_spam: "Confirm Spam"
+      confirm_spam: "Delete Post"
+      confirm_spam_description: "Agree with flag, delete the post and submit feedback to Akismet."
       not_spam: "Not Spam"
       confirm_delete: "Confirm Spam & Delete User"
-      confirm_suspend: "Confirm Spam & Suspend User"
-      reject_spam_user_delete: "Delete User"
+      confirm_suspend: "Suspend User"
+      confirm_suspend_description: "Agree with flag and suspend the user."
       dismiss: "Dismiss"
       ignore: "Ignore"
       reviewable_delete_prompt: "Are you sure you want to delete this user? This will remove all of their posts and block their email and ip address."
-      topic_deleted: Our automated spam filter, Akismet, has temporarily hidden your topic.
+      topic_deleted: "Our automated spam filter, Akismet, has temporarily hidden your topic."
+
+      user_state:
+        pending: "Akismet hasn't checked this user yet."
+        skipped: "This user has not been verified by Akismet."
+        confirmed_ham: "Akismet decided that this user is not spam."
+        confirmed_spam: "Akismet decided that this user is spam."
 
+      post_state:
+        pending: "Akismet hasn't checked this post yet."
+        skipped: "This post has not be verified by Akismet."
+        confirmed_ham: "This post was marked as not spam by Akismet."
+        confirmed_spam: "This post was marked as spam by Akismet."
 
     review:
       user:
@@ -37,4 +44,3 @@ en:
           title: "Akismet Flagged Post"
         reviewable_akismet_user:
           title: "Akismet Flagged User"
-
diff --git a/db/migrate/20210929143222_rename_akismet_state_new_to_pending.rb b/db/migrate/20210929143222_rename_akismet_state_new_to_pending.rb
new file mode 100644
index 0000000..f9ad037
--- /dev/null
+++ b/db/migrate/20210929143222_rename_akismet_state_new_to_pending.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RenameAkismetStateNewToPending < ActiveRecord::Migration[6.1]
+  def up
+    execute "UPDATE post_custom_fields SET value = 'pending' WHERE name = 'AKISMET_STATE' AND value = 'new'"
+    execute "UPDATE user_custom_fields SET value = 'pending' WHERE name = 'AKISMET_STATE' AND value = 'new'"
+  end
+
+  def down
+    execute "UPDATE post_custom_fields SET value = 'new' WHERE name = 'AKISMET_STATE' AND value = 'pending'"
+    execute "UPDATE user_custom_fields SET value = 'new' WHERE name = 'AKISMET_STATE' AND value = 'pending'"
+  end
+end

[... diff too long, it was truncated ...]

GitHub sha: 3730f08313e2e515564ba7abf332d38e2bae9316

This commit appears in #32 which was approved by ZogStriP. It was merged by udan11.