CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-slackeventsapi

Python Slack Events API adapter for Flask that provides event-driven Slack app development

Pending
Overview
Eval results
Files

server-integration.mddocs/

Server Integration

Integration capabilities for incorporating Slack event handling into existing Flask applications, Blueprints, and other WSGI-compatible web frameworks. The SlackServer class handles HTTP request processing, signature verification, and Slack-specific protocol requirements.

Capabilities

SlackServer Internal Implementation

Internal Flask server that processes HTTP requests and handles Slack Events API protocol requirements.

class SlackServer(Flask):
    def __init__(self, signing_secret, endpoint, emitter, server):
        """
        Internal server for handling Slack Events API requests.
        
        Parameters:
        - signing_secret: str - Slack app's signing secret
        - endpoint: str - URL endpoint for receiving events
        - emitter: SlackEventAdapter - Event emitter instance
        - server: Flask/Blueprint/LocalProxy or None - Server to bind to
        
        Raises:
        - TypeError: If server is not Flask, Blueprint, or LocalProxy instance
        """

Route Binding

Binds the Slack event handling route to existing Flask applications or Blueprints.

def bind_route(self, server):
    """
    Bind the event handling route to a Flask server or Blueprint.
    
    Parameters:
    - server: Flask/Blueprint/LocalProxy - Server instance to bind route to
    
    Returns:
    None
    """

Signature Verification

Verifies incoming request signatures using HMAC-SHA256 to ensure requests are from Slack.

def verify_signature(self, timestamp: str, signature: str) -> bool:
    """
    Verify the request signature using the app's signing secret.
    
    Parameters:
    - timestamp: str - Request timestamp from X-Slack-Request-Timestamp header
    - signature: str - Request signature from X-Slack-Signature header
    
    Returns:
    bool - True if signature is valid, False otherwise
    """

Package Information

Generates user-agent information for HTTP response headers.

def get_package_info(self) -> str:
    """
    Collect package version and system information for user-agent.
    
    Returns:
    str - Formatted user-agent string containing client, Python, and system versions
    """

SlackServer Attributes

The SlackServer instance (accessible via adapter.server) provides access to internal state and configuration.

signing_secret: str
    """The signing secret used for HMAC signature verification."""

emitter: SlackEventAdapter  
    """Reference to the parent SlackEventAdapter instance."""

endpoint: str
    """The URL endpoint configured for receiving Slack events."""

package_info: str
    """User-agent string containing package version and system information."""

Request Processing

The SlackServer automatically handles several aspects of Slack Events API requests:

URL Verification Challenge

When Slack sends a challenge request to verify your endpoint:

{
  "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"
}

The server automatically responds with the challenge value to complete verification.

Event Processing

For actual events, the server:

  1. Validates the request timestamp (must be within 5 minutes)
  2. Verifies the HMAC-SHA256 signature using your signing secret
  3. Parses the JSON event payload
  4. Emits the event to registered listeners
  5. Responds with HTTP 200 and custom headers

Error Responses

  • HTTP 403: Invalid timestamp or signature
  • HTTP 404: GET requests (should be POST)
  • HTTP 200: Successful event processing

Usage Examples

Flask Application Integration

import os
from flask import Flask
from slackeventsapi import SlackEventAdapter

# Create your Flask app
app = Flask(__name__)

# Add your existing routes
@app.route("/health")
def health_check():
    return {"status": "healthy"}

@app.route("/api/data")
def get_data():
    return {"data": "example"}

# Integrate Slack events
slack_events_adapter = SlackEventAdapter(
    signing_secret=os.environ["SLACK_SIGNING_SECRET"],
    endpoint="/api/slack/events",  # Custom endpoint
    server=app  # Bind to existing app
)

@slack_events_adapter.on("message")
def handle_message(event_data):
    event = event_data["event"]
    print(f"Message: {event.get('text', '')}")

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

Blueprint Integration

import os
from flask import Blueprint
from slackeventsapi import SlackEventAdapter

# Create a Blueprint
slack_bp = Blueprint('slack', __name__, url_prefix='/slack')

# Add routes to the Blueprint
@slack_bp.route('/status')
def slack_status():
    return {"slack": "active"}

# Bind Slack events to the Blueprint
slack_events_adapter = SlackEventAdapter(
    signing_secret=os.environ["SLACK_SIGNING_SECRET"],
    endpoint="/events",  # Will be /slack/events due to Blueprint prefix
    server=slack_bp
)

@slack_events_adapter.on("reaction_added")
def handle_reaction(event_data):
    event = event_data["event"]
    print(f"Reaction: {event['reaction']}")

# Register Blueprint with main app
from flask import Flask
app = Flask(__name__)
app.register_blueprint(slack_bp)

Multiple Endpoints

import os
from flask import Flask
from slackeventsapi import SlackEventAdapter

app = Flask(__name__)

# Production events
prod_adapter = SlackEventAdapter(
    signing_secret=os.environ["SLACK_SIGNING_SECRET_PROD"],
    endpoint="/slack/prod/events",
    server=app
)

# Development events  
dev_adapter = SlackEventAdapter(
    signing_secret=os.environ["SLACK_SIGNING_SECRET_DEV"],
    endpoint="/slack/dev/events",
    server=app
)

@prod_adapter.on("message")
def handle_prod_message(event_data):
    print("Production message received")

@dev_adapter.on("message") 
def handle_dev_message(event_data):
    print("Development message received")

Custom Error Handling

import os
from flask import Flask
from slackeventsapi import SlackEventAdapter
from slackeventsapi.server import SlackEventAdapterException

app = Flask(__name__)

slack_events_adapter = SlackEventAdapter(
    signing_secret=os.environ["SLACK_SIGNING_SECRET"],
    endpoint="/slack/events",
    server=app
)

@slack_events_adapter.on("error")
def handle_slack_error(error):
    if isinstance(error, SlackEventAdapterException):
        error_msg = str(error)
        
        if "Invalid request signature" in error_msg:
            print("WARNING: Invalid signature - check signing secret")
            # Could log to monitoring service
            
        elif "Invalid request timestamp" in error_msg:
            print("WARNING: Old timestamp - possible replay attack or clock skew")
            # Could implement additional logging
            
    else:
        print(f"Unexpected error: {error}")

# Your app routes
@app.route("/")
def index():
    return "Slack Events API Integration"

if __name__ == "__main__":
    app.run(debug=True)

Accessing Server Attributes

import os
from flask import Flask
from slackeventsapi import SlackEventAdapter

app = Flask(__name__)

# Create adapter
slack_events_adapter = SlackEventAdapter(
    signing_secret=os.environ["SLACK_SIGNING_SECRET"],
    endpoint="/slack/events",
    server=app
)

# Access server attributes for monitoring or debugging
print(f"Server endpoint: {slack_events_adapter.server.endpoint}")
print(f"Package info: {slack_events_adapter.server.package_info}")
print(f"Signing secret configured: {'Yes' if slack_events_adapter.server.signing_secret else 'No'}")

@app.route("/status")
def status():
    return {
        "endpoint": slack_events_adapter.server.endpoint,
        "package_info": slack_events_adapter.server.package_info
    }

if __name__ == "__main__":
    app.run()

Security Features

Automatic Signature Verification

All incoming requests are automatically verified using HMAC-SHA256 with your signing secret. Invalid signatures result in HTTP 403 responses and "error" event emission.

Timestamp Validation

Requests older than 5 minutes are rejected to prevent replay attacks. This protects against malicious actors replaying captured requests.

Headers Added to Responses

The server adds X-Slack-Powered-By headers to successful responses containing package version information for debugging and monitoring.

Install with Tessl CLI

npx tessl i tessl/pypi-slackeventsapi

docs

event-adapter.md

event-handling.md

index.md

server-integration.md

tile.json