Category: WordPress

  • WP RSS Aggregator v5: A Developer’s Look Under the Hood

    Reading Time: 5 minutes

    We recently shipped version 5 of WP RSS Aggregator, and let’s be clear — this wasn’t just a version bump or a shiny new UI. This was a complete teardown and rebuild of the plugin from the ground up.

    Why? Because the old architecture — like most legacy WordPress plugins — was never built with scale, performance, or developer experience in mind. It worked, sure, but it wasn’t something we were proud to put in front of enterprise teams or large-scale use cases.

    As the lead developer behind v5, I wanted to share some behind-the-scenes insights into what we changed, why we changed it, and what this means if you’re a developer building on, with, or around WP RSS Aggregator.

    1. A Developer-Friendly Codebase

    Let’s be honest — most plugin codebases are not fun to work with. Either they’re massive monoliths or spaghetti files with zero abstraction.

    We approached v5 differently.

    What we did:

    • Modular architecture — The plugin is cleanly split into modules. You only load what you need.
    • Interfaces and contracts — You can inject your own RssReader or extend the Importer without fighting the framework.
    • Typed data and services — No mystery arrays. Clear contracts. Predictable behavior.
    • Unit tested — We’ve invested heavily in automated tests so we can ship confidently and extend easily.
    • Well-documented internals — Every method, interface, and core service is documented. Not just with PHPDoc — with actual context.

    If you’re building a feature, a custom add-on, or contributing upstream — this codebase won’t make you hate your life.

    WP RSS Aggregator v5 isn’t just a feature-packed plugin — it’s an opinionated architecture built on real software design patterns, the kind you’ll actually recognize if you’ve worked on large PHP systems or frameworks.

    We didn’t just slap some interfaces on procedural code — we built the internal structure to be predictable, composable, and testable. Here’s a look at a few key patterns we rely on heavily:

    Generator Pattern

    In section #2, you’ll see how we use PHP generators for memory efficiency — a pattern that flows throughout the data processing layer — but under the hood, that’s part of a deliberate Generator Pattern that flows throughout the data processing layer.

    public function convert(Source $source, iterable $items, ...): iterable {
        foreach ($items as $item) {
            $post = $this->makePost($item);
            if ($post !== null) {
                yield $post;
            }
        }
    }

    This is how we process tens of thousands of feed items without blowing up memory or execution time. It’s lazy-loaded, pipeline-style processing — and it’s everywhere.

    Module Manager + Dependency Injection

    We don’t use a bloated container like Symfony’s — instead, we wrote our own lightweight module manager via the Plugin class in our SDK.

    Each module registers itself with a unique ID and a factory. Dependencies are resolved and injected at runtime — clean constructor injection without the mess.

    $plugin->addModule('rss.reader', ['http.client'], function($http) {
        return new RssReader($http);
    });

    It’s a simple pattern, but powerful: we get loose coupling, clear dependency trees, and testable modules — without needing a full-blown framework.

    Custom Plugin SDK

    Everything above is tied together with our custom plugin SDK, based on rebelcode/wp-plugin-sdk.

    This gives us:

    • A clean module manager
    • A DI container
    • Centralized bootstrapping
    • Lifecycle hooks
    • Shared interfaces and contracts

    It’s how we can ship modules and future extensions without coupling them tightly. Developers extending the plugin can just hook into the SDK and build modular add-ons without rewriting internal logic.

    I’ve also written a blog post on design patterns that offers valuable insights related to this topic. You can read it here: Unlocking Enterprise-Level WordPress Development: 8 Design Patterns to Know

    2. PHP Generators: Why We Ditched Array Hell

    Let’s start with the biggest game-changer: PHP generators.

    In previous versions (and still in most feed plugins), RSS items were loaded into memory all at once. That’s fine if you’re aggregating from a couple of sources. But start pulling from 50, 100, or a thousand feeds? You’re looking at memory exhaustion, slow imports, and frustrated users.

    How we solved it:

    We switched to a generator-based pipeline.

    This pattern runs deep in our architecture — especially in our Importer::convert() method, which takes an iterable of raw RssItem objects and yields well-formed IrPost objects one at a time, minimizing memory usage even with tens of thousands of items.

    Bottom line: This isn’t just cleaner code — it’s what makes v5 stable on large-scale sites, where other plugins fall over.

    3. A Real Tech Stack — Not Just PHP and Hope

    Too many WordPress plugins are still stuck in 2014: procedural PHP, jQuery spaghetti, and zero build tools. We wanted better — for ourselves and for anyone contributing.

    So we modernized the entire stack.

    Backend

    • PHP 7.4+ — Modern language features, strict types, better performance.
    • PSR-standards — We adhere to PSR-3 (psr/log) for logging, among others. This isn’t just nice — it’s what lets us slot cleanly into any serious PHP project.
    • Custom Plugin SDK — Built on rebelcode/wp-plugin-sdk, which gives us a DI container, service registration, clean lifecycle hooks, and sane code organization.

    Frontend

    • React + TypeScript — Our admin UI is a full SPA with strict typing, scoped components, and a responsive UX that doesn’t choke on large datasets.
    • Vite — Our build tool of choice. Lightning-fast hot reloads and production builds. No Webpack mess.
    • Tailwind CSS — Utility-first styling for rapid iteration and consistency across the UI.
    • Storybook — For isolated component development, documentation, and visual testing.

    Developer to developer: This stack doesn’t just look good on a slide. It means you can jump into any part of the codebase — backend or frontend — and understand what’s going on, without feeling like you’ve time-traveled back to the WordPress 3.x era.

    4. Built for Scale, Not Just Simplicity

    A lot of plugins solve a small problem well. That’s fine — unless you’re working on a content-heavy site or need automation and control at scale. Then you need more than checkbox settings and hope.

    What v5 brings to the table:

    • Custom database tables — We ditched wp_posts for storing imported feed items. This keeps things lean and queryable even at 100k+ items.
    • Per-source import limits — Granular control over how many items get imported.
    • Age-based expiration — Automatically deletes old content to keep things clean.
    • Scheduling & reconciliation — You define how and when sources are checked, and whether content should be updated or left untouched.
    • Result-based error handling — We use a Result object pattern across the codebase. This means no more vague error logs or random failures. If something fails, we know exactly what and why.

    And yes — everything is WP-CLI-enabled. Import feeds, clean old items, run batch jobs — all from the command line. Perfect for CI/CD or dev-ops workflows.

    5. WP VIP & Enterprise-Ready: Why It Matters

    We’ve built WP RSS Aggregator to meet the expectations of WordPress VIP customers — think performance audits, security standards, scalability, and long-term maintainability.

    Compared to other plugins

    FeatureWP RSS AggregatorOther RSS plugins
    Memory ManagementPHP GeneratorsArrays
    Frontend StackReact, TS, VitejQuery, HTML
    ExtensibilityModular + SDKFilter-based
    CLI SupportFull WP-CLI suiteMinimal
    Error HandlingResult object patternStandard WP errors

    Let’s be clear — Other RSS plugins are good for simpler use cases. But when you’re running an editorial workflow, aggregating 500k items, and need clean error reporting, CLI automation, and dev-friendly code… you want something built like WP RSS Aggregator.

    Final Thoughts

    We didn’t build v5 to be trendy. We built it because the ecosystem desperately needs more serious, scalable, and developer-first plugins.

    If you’re a developer working on high-scale WordPress projects, or just someone who wants to peek under the hood of a real-world plugin rewrite — we hope this gives you some inspiration.

    Want to contribute? Try building a custom integration? Or just talk dev-architecture over coffee? Hit me up.

    More deep dives are coming soon — next up, I’ll break down our generator pipeline, Vite setup, and CLI framework in dedicated posts.

  • Front-End WordPress Submission via Telegram Bot

    Reading Time: 9 minutes

    Last week, while working on our Aggregator plugin, I explored new ways to enhance its functionality. During my research, I stumbled upon Telegram’s Bot API—something I had never used before. Out of curiosity, I decided to test its capabilities. What started as simple experimentation quickly turned into a quick open source project: Why not enable front-end WordPress submission via a Telegram bot?

    This guide walks you through setting up a Telegram bot, integrating it with WordPress, and automating post submissions—all without needing to access the admin panel. In this post, I’ll share my journey of integrating Telegram with WordPress and building a bot to streamline front-end post submissions.

    I’ll walk you through my journey of integrating Telegram with WordPress and building a bot that streamlines front-end post submissions. Enough talk—let’s get started!

    1. Creating a Telegram Bot with BotFather

    Telegram provides BotFather, an official bot for managing bots. Follow these steps to create your bot:

    1. Open Telegram and search for BotFather.
    2. Start a chat with BotFather and type /newbot.
    3. Follow the instructions to set up your bot:
      • Choose a name for your bot (e.g., “WP Post Bot”).
      • Choose a username for your bot (must end with bot, e.g., “WPPostSubmissionBot”).
    4. Once created, BotFather will provide you with a Bot Token—save this token securely, as it will be needed to authenticate API requests.

    Now that we have our bot set up, let’s move on to building the WordPress plugin.

    2. Creating Your WordPress Plugin

    To interact with Telegram’s Bot API in PHP, we’ll use the Telegram Bot SDK, a well-maintained library that simplifies bot development. Before writing any code, install the SDK via Composer.

    Step 1: Create the Plugin Folder & File

    Inside the wp-content/plugins/ directory, create a new folder:

    mkdir wp-content/plugins/telegram-post-bot

    Inside this folder, create a new file named telegram-post-bot.php and open it in your code editor.

    Installing Telegram Bot SDK via Composer

    Ensure you have Composer installed on your system, then run the following command in your project directory:

    composer require irazasyed/telegram-bot-sdk

    This will download and install the SDK and its dependencies. Once installed, you can start using the library to communicate with Telegram’s API.


    Step 2: Understanding the Main Plugin File

    This file is the entry point for the plugin and initializes everything. Here’s the breakdown of the code:

    if ( ! defined( 'ABSPATH' ) ) {
        exit; // Prevent direct access
    }
    
    if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
        require_once __DIR__ . '/vendor/autoload.php';
    }
    
    use Telegram\Bot\Api;
    use Dotenv\Dotenv;
    
    try {
        $dotenv = Dotenv::createImmutable( __DIR__ );
        $dotenv->safeLoad();
    } catch ( Exception $e ) {
        error_log( 'Telegram Post Bot: Failed to load .env file - ' . $e->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
    }
    
    define( 'TELEGRAM_BOT_TOKEN', $_ENV['TELEGRAM_BOT_TOKEN'] ?: ''  );
    define( 'TELEGRAM_AUTHORIZED_USERS', $_ENV['TELEGRAM_AUTHORIZED_USERS'] ?: ''  );
    • The ABSPATH check ensures the file is accessed only within WordPress, preventing direct execution.
    • This checks if Composer dependencies are installed (including the Telegram SDK).
    • I use Dotenv to include tokens from a .env file. You can find examples in the repository.
    • If found, it loads them automatically, ensuring we can use the SDK in our plugin.

    Step 3: Registering a Telegram Webhook Route

    This snippet creates a custom REST API endpoint in WordPress to receive messages from Telegram.

    add_action( 'rest_api_init', 'register_telegram_webhook_route' );
    
    /**
     * Registers the Telegram webhook REST API endpoint.
     *
     * @return void
     */
    function register_telegram_webhook_route() {
        register_rest_route(
            'telegram/v1',
            '/webhook/',
            array(
                'methods'             => 'POST',
                'callback'            => 'handle_telegram_update',
                'permission_callback' => '__return_true',
            )
        );
    }

    Explanation:

    • register_rest_route: Registers a new REST API route under /wp-json/telegram/v1/webhook/.
    • methods => 'POST': This endpoint only accepts POST requests.
    • callback => 'handle_telegram_update': When Telegram sends data, this function processes it.
    • permission_callback => '__return_true': Allows open access (you may want to restrict it for security).

    This ensures that Telegram messages are received at /wp-json/telegram/v1/webhook/. the next step is to handle incoming Telegram messages and process post submissions. which we’ll cover in the next section.


    Step 4: Handling Telegram Messages (In-Depth Breakdown)

    The function below processes incoming messages from Telegram, collects blog post details, and stores them in a temporary session.

    /**
     * Handles incoming Telegram messages and processes user input for post creation.
     *
     * @param WP_REST_Request $request The REST API request object.
     *
     * @return WP_REST_Response REST response indicating success or failure.
     */
    function handle_telegram_update( WP_REST_Request $request ) {
        if ( empty( TELEGRAM_BOT_TOKEN ) ) {
            return new WP_REST_Response( esc_html__( 'Bot token missing', 'telegram-post-bot' ), 400 );
        }
    
        $authorized_users = array_map( 'absint', explode( ',', TELEGRAM_AUTHORIZED_USERS ) );
        $update = $request->get_json_params();
        $message = $update['message'] ?? null;
    
        if ( ! $message ) {
            return new WP_REST_Response( esc_html__( 'No message received', 'telegram-post-bot' ), 400 );
        }
    
        $chat_id = absint( $message['chat']['id'] );
        $user_id = absint( $message['from']['id'] );
        $text    = sanitize_text_field( $message['text'] ?? '' );
    
        if ( ! in_array( $user_id, $authorized_users, true ) ) {
            send_telegram_message( $chat_id, esc_html__( 'Unauthorized user.', 'telegram-post-bot' ) );
            return new WP_REST_Response( esc_html__( 'Unauthorized user', 'telegram-post-bot' ), 403 );
        }
    
    	if ("/start" === $text ) {
    		$keyboard = [
    			'keyboard' => [
    				[['text' => '/post'], ['text' => '/endsession']]
    			],
    			'resize_keyboard' => true,
    			'one_time_keyboard' => false
    		];
    
    		send_telegram_message( $chat_id, esc_html__( 'Welcome! Use the menu below to navigate: /post - Begin a new session /endsession - Cancel the current session.', 'telegram-post-bot' ), array('reply_markup' => json_encode($keyboard)) );
    
    		return new WP_REST_Response('Session started', 200);
    	}
    
    	if ($text === "/endsession") {
            delete_transient("telegram_post_{$user_id}");
    		send_telegram_message( $chat_id, esc_html__( 'Session ended. Use /start to begin again.', 'telegram-post-bot' ) );
    
            return new WP_REST_Response('Session ended', 200);
        }
    
        $user_state = get_transient("telegram_post_{$user_id}") ?: [];
    
        if ( "/post" === $text ) {
            send_telegram_message( $chat_id, esc_html__( 'Send the post title.', 'telegram-post-bot' ) );
        } elseif ( ! isset( $user_state['title'] ) ) {
            $user_state['title'] = $text;
            set_transient( "telegram_post_{$user_id}", $user_state, HOUR_IN_SECONDS );
            send_telegram_message( $chat_id, esc_html__( 'Title saved. Now, send tags (comma-separated).', 'telegram-post-bot' ) );
        } elseif ( ! isset( $user_state['tags'] ) ) {
            $user_state['tags'] = array_map( 'sanitize_text_field', explode( ',', $text ) );
            set_transient( "telegram_post_{$user_id}", $user_state, HOUR_IN_SECONDS );
            send_telegram_message( $chat_id, esc_html__( 'Tags saved. Now, send a category.', 'telegram-post-bot' ) );
        } elseif ( ! isset( $user_state['category'] ) ) {
            $user_state['category'] = $text;
            set_transient( "telegram_post_{$user_id}", $user_state, HOUR_IN_SECONDS );
            send_telegram_message( $chat_id, esc_html__( 'Category saved. Now, send the content.', 'telegram-post-bot' ) );
        } elseif ( ! isset( $user_state['content'] ) ) {
            $user_state['content'] = $text;
            set_transient( "telegram_post_{$user_id}", $user_state, HOUR_IN_SECONDS );
            send_telegram_message( $chat_id, esc_html__( 'Content saved. Type publish to submit your post.', 'telegram-post-bot' ) );
        } elseif ( 'publish' === strtolower( $text ) ) {
            create_wordpress_post( $user_state, $chat_id );
            delete_transient( "telegram_post_{$user_id}" );
            return new WP_REST_Response( esc_html__( 'Post submitted and session ended', 'telegram-post-bot' ), 200 );
        } else {
            send_telegram_message( $chat_id, esc_html__( 'Invalid command. Type publish to submit your post.', 'telegram-post-bot' ) );
        }
    
        return new WP_REST_Response( esc_html__( 'Request processed', 'telegram-post-bot' ), 200 );
    }
    

    Now that we have our Telegram bot set up and a webhook to receive messages, we need to process those messages, validate users, and guide them through submitting a post to WordPress. This is done in the handle_telegram_update function.

    I’m going to explain the code in detail. Let’s break it down.

    Fetching API Credentials and Checking Authorization:

    function handle_telegram_update(WP_REST_Request $request) {
        $bot_token = TELEGRAM_BOT_TOKEN;
    
        if (!$bot_token) return new WP_REST_Response('Bot token missing', 400);
        ....
    }
    • We retrieve the bot token and the list of authorized users (who are allowed to submit posts) from the .env file.
    • If the bot token is missing, we return an error response.

    Getting the Incoming Message from Telegram:

        $update = $request->get_json_params();
        $message = $update['message'] ?? null;
    
        if (!$message) return new WP_REST_Response('No message received', 400);
    • The message sent by the user is extracted from the request payload.
    • If there’s no message, we return an error response.

    Extracting User Data:

    $chat_id = $message['chat']['id'];
    $user_id = $message['from']['id'];
    $text = $message['text'] ?? '';
    • $chat_id: This is the chat where we need to send responses.
    • $user_id: The Telegram user’s ID (used to track progress).
    • $text: The message content sent by the user.

    Checking If the User Is Authorized:

    $authorized_users = explode(',', TELEGRAM_AUTHORIZED_USERS);
    
    if ( ! in_array( $user_id, $authorized_users, true ) ) {
            send_telegram_message( $chat_id, esc_html__( 'Unauthorized user.', 'telegram-post-bot' ) );
            return new WP_REST_Response( esc_html__( 'Unauthorized user', 'telegram-post-bot' ), 403 );
    }
    • We verify if the user is in the list of authorized users.
    • If they are not, we send them a Unauthorized user message and reject the request.

    Using get_transient for Temporary Data Storage:

    $user_state = get_transient("telegram_post_{$user_id}") ?: [];

    In our transient system, we use the string telegram_post_ combined with the Telegram user ID. This ensures that each user can submit only one blog post at a time. Additionally, you could add a feature allowing users to edit their unfinished post steps based on this transient. This is one of the key advantages of using transients in this approach, and I will highlight some others in the following:

    • This acts like a temporary session for each user.
    • Instead of storing each message permanently in the database, we save data temporarily.
    • It reduces unnecessary database writes, keeping things efficient.
    • You can delete the post while it’s being submitted by using a Telegram command like /endsession.
    • The only disadvantage is that over time, transients in the options table may accumulate. However, you can use plugins to clean them up.

    Collecting Post Details in Steps:

    Here’s where the magic happens—we guide the user step by step through the post submission process:

    if ( "/post" === $text ) {
            send_telegram_message( $chat_id, esc_html__( 'Send the post title.', 'telegram-post-bot' ) );
        } elseif ( ! isset( $user_state['title'] ) ) {
            $user_state['title'] = $text;
            set_transient( "telegram_post_{$user_id}", $user_state, HOUR_IN_SECONDS );
            send_telegram_message( $chat_id, esc_html__( 'Title saved. Now, send tags (comma-separated).', 'telegram-post-bot' ) );
        } elseif ( ! isset( $user_state['tags'] ) ) {
            $user_state['tags'] = array_map( 'sanitize_text_field', explode( ',', $text ) );
            set_transient( "telegram_post_{$user_id}", $user_state, HOUR_IN_SECONDS );
            send_telegram_message( $chat_id, esc_html__( 'Tags saved. Now, send a category.', 'telegram-post-bot' ) );
        } elseif ( ! isset( $user_state['category'] ) ) {
            $user_state['category'] = $text;
            set_transient( "telegram_post_{$user_id}", $user_state, HOUR_IN_SECONDS );
            send_telegram_message( $chat_id, esc_html__( 'Category saved. Now, send the content.', 'telegram-post-bot' ) );
        } elseif ( ! isset( $user_state['content'] ) ) {
            $user_state['content'] = $text;
            set_transient( "telegram_post_{$user_id}", $user_state, HOUR_IN_SECONDS );
            send_telegram_message( $chat_id, esc_html__( 'Content saved. Type publish to submit your post.', 'telegram-post-bot' ) );
        } elseif ( 'publish' === strtolower( $text ) ) {
            create_wordpress_post( $user_state, $chat_id );
            delete_transient( "telegram_post_{$user_id}" );
            return new WP_REST_Response( esc_html__( 'Post submitted and session ended', 'telegram-post-bot' ), 200 );
        } else {
            send_telegram_message( $chat_id, esc_html__( 'Invalid command. Type publish to submit your post.', 'telegram-post-bot' ) );
    }

    How This Works:

    1. First, we check if the command /post comes from Telegram, then we begin the process.
    2. Then, we check if the title is not missing → If yes, we save the title and ask for tags.
    3. Then, we check if the tags are not missing → If yes, we save the tags and ask for the category.
    4. Then, we check if the category is not missing → If yes, we save the category and ask for content.
    5. Then, we check if the content is not missing → If yes, we save the content and ask for the “publish” command.
    6. Finally, when the user types “publish”, we create the post in WordPress and clear the session.

    Step 5: Sending a Response to the User

    $telegram->sendMessage(['chat_id' => $chat_id, 'text' => $response_message]);
        return new WP_REST_Response('Request processed', 200);
    }
    • After each step, we send a confirmation message to guide the user.
    • The function returns a successful response to Telegram.

    Creating a WordPress Post

    When the user types "publish", the following function inserts the collected data as a draft post in WordPress.

    function create_wordpress_post( $data, $chat_id ) {
    	$category_name = sanitize_text_field( $data['category'] );
    	$category_slug = sanitize_title( $category_name );
    
    	// Check if category exists.
    	$category = get_category_by_slug( $category_slug );
    
    	if ( !$category ) {
    		$category_id = wp_insert_term( $category_name, 'category', array( 'slug' => $category_slug ) );
    
    		if ( is_wp_error( $category_id ) ) {
    			send_telegram_message( $chat_id, esc_html__( 'Error creating category: ', 'telegram-post-bot' ) . $category_id->get_error_message() );
    			return;
    		}
    
    		$category_id = $category_id['term_id'];
    	} else {
    		$category_id = $category->term_id;
    	}
    
        $post_id = wp_insert_post(
            array(
                'post_title'    => sanitize_text_field( $data['title'] ),
                'post_content'  => wp_kses_post( $data['content'] ),
                'post_status'   => 'draft',
                'post_type'     => 'post',
                'tags_input'    => array_map( 'sanitize_text_field', $data['tags'] ),
                'post_category' => ( $category_id ) ? array( $category_id ) : array(),
            ),
            true
        );
    
        if ( is_wp_error( $post_id ) ) {
            send_telegram_message( $chat_id, esc_html__( 'Error creating post: ', 'telegram-post-bot' ) . $post_id->get_error_message() );
            return;
        }
    
        send_telegram_message( $chat_id, esc_html__( 'Post submitted successfully! View: ', 'telegram-post-bot' ) . esc_url( get_permalink( $post_id ) ) );
    }
    • Creates a post using wp_insert_post().
    • Sanitizes input to prevent security issues.
    • Assigns or create a category & tags based on user input.
    • Handles errors and returns an error response if post creation fails.
    • Sends a Telegram message with the post link upon success

    Sending Messages via Telegram API in WordPress:

    The send_telegram_message function plays a crucial role in our Telegram bot integration, allowing it to send messages to users. Here’s how it works:

    /**
     * Sends a message to a Telegram chat.
     *
     * @param int    $chat_id Telegram chat ID.
     * @param string $message The message to send.
     *
     * @return void
     */
    function send_telegram_message( $chat_id, $message, $data = array() ) {
        if ( empty( TELEGRAM_BOT_TOKEN ) ) {
            return;
        }
    
        $telegram = new Api( TELEGRAM_BOT_TOKEN );
    
        try {
            $telegram->sendMessage(
                array(
                    'chat_id' => absint( $chat_id ),
                    'text'    => $message,
    				extract($data)
                )
            );
        } catch ( Exception $e ) {
            error_log( 'Telegram Post Bot: Failed to send message - ' . $e->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
        }
    }

    In each step, we send a message to this function, which creates an instance of the Telegram\Bot\Api library bot and handles sending responses to the Telegram bot. While this library offers many capabilities, this is a simple use case demonstrating how you can interact with and utilize the WP REST API to create a Telegram bot. With some help from AI and the library’s repository, you can explore more advanced examples.

    3. Register the REST API to Telegram Bot webhook

    Once you’ve set up your custom WordPress REST API endpoint (/wp-json/telegram/v1/webhook/), you need to register it with Telegram so that the bot can receive messages. This can be done using Postman or the terminal (cURL).

    Enter the following URL in Postman:

    https://api.telegram.org/bot<YOUR_BOT_TOKEN>/setWebhook?url=<YOUR_WEBHOOK_URL>

    Replace:

    • <YOUR_BOT_TOKEN> with your Telegram bot token (generated from BotFather).
    • <YOUR_WEBHOOK_URL> with your WordPress endpoint (https://yourwebsite.com/wp-json/telegram/v1/webhook/).

    or simply use terminal

    curl -X POST "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/setWebhook" -d "url=<YOUR_WEBHOOK_URL>"

    Conclusion

    With front-end WordPress submission via a Telegram bot, users can publish posts without logging in. Setting up a Telegram bot using a custom WordPress REST API route is a powerful way to integrate automated messaging with your website. In this guide, I provided a quick overview of the process, including creating a custom REST endpoint, registering the webhook with the Telegram API, and verifying that the integration works.

    However, this is just a basic demonstration to show the core functionality. In a real-world implementation, there are many improvements needed, including:

    • Security Enhancements – The REST API should validate requests properly, including verifying Telegram tokens to prevent unauthorized access.
    • Caching – Implementing caching mechanisms to avoid redundant requests and improve performance.
    • Error Handling & Fault Tolerance – Adding proper logging, retry mechanisms, and fallback strategies to ensure stability.
    • Capability & Permission Checks – Ensuring only authorized users can interact with the bot and access the API endpoint.
    • Advanced REST API Optimization – Improving response times and managing rate limits for better efficiency.

    In conclusion, you can use AI to refine and expand this plugin with additional features or even create your own version. However, I generally don’t recommend using ChatGPT to generate code and deploy it in production without fully understanding how it works. I’ve created a repository for this blog post as a quick demonstration of WP REST API and post submission via a Telegram bot. You’re free to fork, download, and contribute to the repository, but please use it cautiously, as it’s not intended for production. Feel free to check out the open-source repository: Telegram Post Bot on GitHub.