Skip to content

v4.0.0 - Z Day⚡🇿, Jan 1st, 2026

Latest

Choose a tag to compare

@DanielSnor DanielSnor released this 01 Jan 00:05
· 5 commits to main since this release
daf892f

🎯 Overview

Version 4.0.0 represents a major overhaul of the IFTTT filter script, focusing on:

  • Performance optimization (~100x faster entity processing)
  • Code cleanup (removal of legacy compatibility layers)
  • Enhanced RSS support (proper retweet formatting from rss.app feeds)
  • Size reduction (~7KB smaller, more room for future features)

⚠️ BREAKING CHANGES: This is a major version update with breaking changes. See Migration Guide below.


⚠️ BREAKING CHANGES

1. FilterRule API Changes

Removed legacy properties:

  • keywords?: string[] (use content instead)
  • rule?: FilterRule (use nested filter structures)

Migration:

// BEFORE (v3.x):
{
  type: "and",
  keywords: ["tech", "AI"]
}

// AFTER (v4.0.0):
{
  type: "and",
  content: ["tech", "AI"]
}

2. URL_REPLACE_FROM - Array Only

Single string format removed:

// BEFORE (v3.x):
URL_REPLACE_FROM: "https://twitter.com/"  // ❌ No longer supported

// AFTER (v4.0.0):
URL_REPLACE_FROM: ["https://twitter.com/"]  // ✅ Array required

3. Cache System Removed

Internal cache system (getCached(), getCachedRegex()) has been removed. Regex compilation is now handled directly with optimized patterns.

Impact: None for users - internal change only.

4. Polyfills Removed

ES5 polyfills for String.prototype.startsWith, String.prototype.endsWith, and Array.from fallbacks have been removed. IFTTT runtime now natively supports these features.

Impact: None - IFTTT environment supports ES6+ features.


✨ New Features

RSS Retweet Formatting Support

Added comprehensive support for retweets from RSS feeds (via rss.app):

Features:

  • ✅ Recognizes "RT by @username:" format (rss.app variant)
  • ✅ Normalizes duplicate RT prefixes
  • ✅ Proper formatting: RetweetingUser 𝕏📤 https://x.com/OriginalAuthor:

Example:

Input (from rss.app):
EntryTitle: "RT by @UdalostiBrno: RT by @UdalostiBrno: Content..."
EntryAuthor: "@Minarik_CT"

Output:
UdalostiBrno 𝕏📤 https://x.com/Minarik_CT:
Content...
https://x.com/Minarik_CT/status/123

Changes:

  • Updated REPOST_PREFIX regex: /^(RT (?:by )?@([^:]+): )/i
  • Updated REPOST_USER regex: /RT (?:by )?(@[a-z0-9_]+)/gi
  • Updated RT_PREFIX regex: /^RT\s+(?:by\s+)?@[\w]+/i
  • Enhanced formatRepost() with RSS-specific logic
  • Added duplicate RT prefix normalization in composeContent()

🚀 Performance Optimizations

1. CHAR_MAP Processing - 100x Faster

Before (v3.x):

  • 70 iterations through string per entity
  • Complexity: O(n×m) where n=string length, m=entities
  • For 500-char post: ~105,000 character comparisons

After (v4.0.0):

  • Single-pass regex replacement
  • Pre-compiled pattern: /( |…|&|...)/g
  • Complexity: O(n) - linear
  • For 500-char post: ~500 character comparisons

Performance gain: ~210x faster

2. HTML Entity Decoding - Single Pass

Created codePointToChar() helper function to eliminate duplicate surrogate pair logic:

Before:

// Decimal entities: full surrogate logic
str = str.replace(/&#(\d+);/g, function(m, dec) {
  // ... surrogate pair handling ...
});

// Hex entities: DUPLICATE surrogate logic
str = str.replace(/&#x([0-9a-fA-F]+);/gi, function(m, hex) {
  // ... same surrogate pair handling ...
});

After:

// Helper function (DRY):
function codePointToChar(cp) {
  if (cp > 0xFFFF) { /* surrogate pairs */ }
  return String.fromCharCode(cp);
}

// Single unified regex:
str.replace(/&#(?:x([0-9a-fA-F]+)|(\d+));/gi, function(m, hex, dec) {
  return codePointToChar(parseInt(hex || dec, hex ? 16 : 10));
});

Savings: ~430 characters, cleaner code

3. Unified Filter Matching - Loop-Based

Refactored matchesUnifiedFilter() from 6 duplicate blocks to loop-based approach:

Before (v3.x):

// Block 1: content literal matching
if (rule.content && rule.content.length > 0) {
  // ... 8 lines of code ...
}

// Block 2: contentRegex matching
if (rule.contentRegex && rule.contentRegex.length > 0) {
  // ... 8 lines of code ...
}

// Blocks 3-6: Same pattern for username, usernameRegex, domain, domainRegex

After (v4.0.0):

// Single parameterized function called 6 times:
processFilterArrays(lowerStr, rule.content, rule.contentRegex, results);
processFilterArrays(lowerUsername, rule.username, rule.usernameRegex, results);
processFilterArrays(domainStr, rule.domain, rule.domainRegex, results);

Savings: ~1217 characters

4. Other Optimizations

  • findLastSentenceEnd() - removed slice/regex operations
  • platformConfigs - centralized platform configuration with useFeedTitleAuthor
  • processStatus() - removed redundant ternary operator
  • ✅ Plus sign Unicode fix: \uFE63\uFE62 (SMALL PLUS SIGN)

📊 Code Metrics

Metric v3.2.1 v4.0.0 Change
File Size ~63 KB ~56 KB -7 KB (-11%)
Lines of Code 1,423 1,138 -285 lines (-20%)
Functions 42+ 30 -12 functions (-29%)
IFTTT Limit 65 KB 65 KB -
Available Space ~2 KB ~9 KB +7 KB buffer

🐛 Bug Fixes

1. Plus Sign Replacement

Issue: Plus signs were incorrectly converted to SMALL HYPHEN-MINUS () instead of SMALL PLUS SIGN ().

Fixed:

// Before:
str = str.replace(/\+/g, "\uFE63");  // ❌ U+FE63 (looks like minus)

// After:
str = str.replace(/\+/g, "\uFE62");  // ✅ U+FE62 (looks like plus)

Impact: C++ now displays as C﹢﹢ (plus) instead of C﹣﹣ (minus)

2. RSS Feed Author Handling

Fixed processContent() to properly use feedUsername fallback when author is empty for RSS feeds.

3. Duplicate RT Prefix Normalization

RSS feeds from rss.app sometimes generate duplicate RT prefixes:

RT by @user: RT by @user: Content

Now automatically normalized to:

RT by @user: Content

🔧 Technical Improvements

1. Platform Configuration System

Introduced centralized platformConfigs object:

const platformConfigs: { [key: string]: PlatformConfig } = {
  BS: { handleQuotes: true, useFeedTitleAuthor: true, useGetContent: true },
  RSS: { handleRetweets: true, useGetContent: true },
  TW: { 
    handleQuotes: true, 
    handleReplies: true, 
    handleRetweets: true, 
    useFeedTitleAuthor: true, 
    useParsedText: true 
  },
  YT: { useGetContent: true }
};

Benefits:

  • Cleaner separation of platform-specific behavior
  • Easier to maintain and extend
  • Reduced conditional logic throughout codebase

2. Enhanced TypeScript Interfaces

interface PlatformConfig {
  handleQuotes?: boolean;
  handleReplies?: boolean;
  handleRetweets?: boolean;
  useFeedTitleAuthor?: boolean;
  useGetContent?: boolean;
  useParsedText?: boolean;
}

3. Improved Helper Functions

New optimized helper functions:

  • codePointToChar(cp: number): string - Unicode code point conversion
  • processFilterArrays() - Unified filter array processing
  • Optimized findLastSentenceEnd() - Sentence boundary detection

📝 Migration Guide

Step 1: Update FilterRule Definitions

Search your configuration for keywords property:

// Find and replace:
PHRASES_REQUIRED: [
  { type: "and", keywords: ["tech", "AI"] }  // OLD
]

// With:
PHRASES_REQUIRED: [
  { type: "and", content: ["tech", "AI"] }  // NEW
]

Step 2: Update URL_REPLACE_FROM

If using single string format:

// Change:
URL_REPLACE_FROM: "https://twitter.com/"

// To:
URL_REPLACE_FROM: ["https://twitter.com/"]

Step 3: Test Your Configuration

  1. Deploy to @BetaBot test account
  2. Monitor 50-100 posts
  3. Verify:
    • Content filtering works correctly
    • URL replacement functions as expected
    • Retweets format properly (if using RSS feeds)

Step 4: Deploy to Production

Once testing confirms everything works:

  1. Update all bot configurations
  2. Deploy script to production accounts
  3. Monitor for any issues

🧪 Testing

Test Coverage:

  • ✅ 204 total tests (all versions 3.0.0 to 3.1.4)
  • ✅ 45/45 matchesUnifiedFilter tests passed
  • ✅ 41/41 findLastSentenceEnd tests passed
  • ✅ RSS retweet formatting validated with real-world data

Validation:

  • ✅ Real production data from @Minarik_CT, @Dostal_CT, @Vitaskova_CT feeds
  • ✅ All edge cases covered (duplicates, self-reposts, etc.)

📚 Documentation

Updated documentation:

  • Settings_for_IFTTT_filter_script_-_v4_0_0.md
  • Unified_Filter_Guide__-_v4_0_0.md
  • ✅ Migration guide (this document)

🎉 Credits

Development: Daniel Šnor (@zpravobot)
Testing: Production validation on Zprávobot.news network
Special Thanks: Claude AI for optimization suggestions and code review


📦 Files in Release

  • ifttt-filter-4.0.0.ts - Production script (56 KB)
  • RELEASE_NOTES_v4.0.0.md - This file
  • MIGRATION_GUIDE_v4.0.0.md - Detailed migration instructions
  • Test suites (historical compatibility)

🔗 Links


📅 Release Timeline

Date Event
Dec 28, 2025 Refactoring started (breaking changes planning)
Dec 29, 2025 Optimization phase completed
Dec 30, 2025 RSS retweet formatting implemented
Dec 31, 2025 Tests
Jan 1, 2026 v4.0.0 Released 🚀

🔮 What's Next?

Planned for v4.1.0:

  • Further documentation updates
  • Additional RSS platform enhancements
  • Performance monitoring and analytics

Planned for v4.2.0:

  • Potential BlueSky API improvements
  • Enhanced content filtering options

⚠️ Known Issues

None at release time.

If you encounter any issues, please report them on GitHub Issues.


💬 Feedback

We'd love to hear your feedback! If you're using this script:

  • ⭐ Star the repository on GitHub
  • 🐛 Report bugs via GitHub Issues
  • 💡 Suggest features via GitHub Discussions
  • ☕ Support via Ko-fi: ko-fi.com/zpravobot

Thank you for using Zprávobot.news IFTTT Filter Script! 🎉