diff --git a/Resources/Scripts/code.js b/Resources/Scripts/code.js
index 6a0e6b98..3d4f20c3 100644
--- a/Resources/Scripts/code.js
+++ b/Resources/Scripts/code.js
@@ -80,43 +80,76 @@
   //
   // Function: Event callback for a new tweet.
   //
-  var onNewTweet = function(column, tweet){
-    if (column.model.getHasNotification()){
-      let html = $(tweet.render({
-        withFooter: false,
-        withTweetActions: false,
-        withMediaPreview: true,
-        isMediaPreviewOff: true,
-        isMediaPreviewSmall: false,
-        isMediaPreviewLarge: false
-      }));
-      
-      html.css("border", "0");
-      html.find("footer").last().remove(); // apparently withTweetActions breaks for certain tweets, nice
-      html.find(".js-media").last().remove(); // and quoted tweets still show media previews, nice nice
-      html.find(".js-quote-detail").removeClass("is-actionable"); // prevent quoted tweets from changing the cursor
-      
-      html.find("a[href='#']").each(function(){ // remove <a> tags around links that don't lead anywhere (such as account names the tweet replied to)
-        this.outerHTML = this.innerHTML;
-      });
-      
-      if (tweet.getChirpType().includes("list_member")){
-        html.find(".activity-header").first().css("margin-top", "2px");
-        html.find(".avatar").first().css("margin-bottom", "0");
+  var onNewTweet = (function(){
+    let recentTweets = new Set();
+    let recentTweetTimer = null;
+    
+    let startRecentTweetTimer = () => {
+      if (recentTweetTimer){
+        window.clearTimeout(recentTweetTimer);
       }
       
-      let source = tweet.getRelatedTweet();
-      let duration = source ? source.text.length+(source.quotedTweet ? source.quotedTweet.text.length : 0) : tweet.text.length;
-      let tweetUrl = source ? source.getChirpURL() : "";
-      let quoteUrl = source && source.quotedTweet ? source.quotedTweet.getChirpURL() : "";
-      
-      $TD.onTweetPopup(columnTypes[column.getColumnType()] || "", html.html(), duration, tweetUrl, quoteUrl);
-    }
+      recentTweetTimer = window.setTimeout(() => {
+        recentTweetTimer = null;
+        recentTweets.clear();
+      }, 10000);
+    };
     
-    if (column.model.getHasSound()){
-      $TD.onTweetSound();
-    }
-  };
+    let checkRecentTweet = id => {
+      if (recentTweets.size > 50){
+        recentTweets.clear();
+      }
+      else if (recentTweets.has(id)){
+        return true;
+      }
+      
+      recentTweets.add(id);
+      startRecentTweetTimer();
+      return false;
+    };
+    
+    return function(column, tweet){
+      if (checkRecentTweet(tweet.id)){
+        return;
+      }
+      
+      if (column.model.getHasNotification()){
+        let html = $(tweet.render({
+          withFooter: false,
+          withTweetActions: false,
+          withMediaPreview: true,
+          isMediaPreviewOff: true,
+          isMediaPreviewSmall: false,
+          isMediaPreviewLarge: false
+        }));
+
+        html.css("border", "0");
+        html.find("footer").last().remove(); // apparently withTweetActions breaks for certain tweets, nice
+        html.find(".js-media").last().remove(); // and quoted tweets still show media previews, nice nice
+        html.find(".js-quote-detail").removeClass("is-actionable"); // prevent quoted tweets from changing the cursor
+
+        html.find("a[href='#']").each(function(){ // remove <a> tags around links that don't lead anywhere (such as account names the tweet replied to)
+          this.outerHTML = this.innerHTML;
+        });
+
+        if (tweet.getChirpType().includes("list_member")){
+          html.find(".activity-header").first().css("margin-top", "2px");
+          html.find(".avatar").first().css("margin-bottom", "0");
+        }
+
+        let source = tweet.getRelatedTweet();
+        let duration = source ? source.text.length+(source.quotedTweet ? source.quotedTweet.text.length : 0) : tweet.text.length;
+        let tweetUrl = source ? source.getChirpURL() : "";
+        let quoteUrl = source && source.quotedTweet ? source.quotedTweet.getChirpURL() : "";
+
+        $TD.onTweetPopup(columnTypes[column.getColumnType()] || "", html.html(), duration, tweetUrl, quoteUrl);
+      }
+
+      if (column.model.getHasSound()){
+        $TD.onTweetSound();
+      }
+    };
+  })();
   
   //
   // Function: Retrieves the tags to be put into <head> for notification HTML code.