You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

233 lines
6.9 KiB

#!/usr/bin/env python3
"""
Test script for PlugNMeet webhook endpoint.
Usage:
python scripts/test_webhook.py [event_type]
Event types:
- room_finished
- participant_joined
- participant_left
- end_recording
"""
import sys
import os
import json
import hmac
import hashlib
import requests
from datetime import datetime
# Django setup
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
import django
django.setup()
from django.conf import settings
def calculate_signature(payload: str, secret: str) -> str:
"""Calculate HMAC SHA256 signature."""
return hmac.new(
secret.encode('utf-8'),
payload.encode('utf-8'),
hashlib.sha256
).hexdigest()
def get_webhook_url() -> str:
"""Get webhook URL from settings or use default."""
base_url = getattr(settings, 'BASE_URL', 'http://localhost:8000')
return f"{base_url}/api/course/plugnmeet/webhook/"
def get_test_payload(event_type: str) -> dict:
"""Generate test payload for given event type."""
timestamp = int(datetime.now().timestamp())
payloads = {
'room_finished': {
"event": "room_finished",
"id": "550e8400-e29b-41d4-a716-446655440000",
"createdAt": timestamp,
"room": {
"sid": "room-123456",
"identity": "test-room-20240101120000",
"name": "Test Class",
"maxParticipants": 100,
"creationTime": timestamp - 3600,
"metadata": "{}",
"numParticipants": 0,
"duration": 3600
}
},
'participant_joined': {
"event": "participant_joined",
"id": "660e8400-e29b-41d4-a716-446655440001",
"createdAt": timestamp,
"room": {
"sid": "room-123456",
"identity": "test-room-20240101120000",
"name": "Test Class"
},
"participant": {
"sid": "participant-user-1",
"identity": "1",
"state": "ACTIVE",
"name": "Test User",
"metadata": '{"is_admin": false}',
"permission": {
"canPublish": True,
"canPublishData": True,
"canSubscribe": True
},
"tracks": [],
"joinedAt": timestamp
}
},
'participant_left': {
"event": "participant_left",
"id": "770e8400-e29b-41d4-a716-446655440002",
"createdAt": timestamp,
"room": {
"sid": "room-123456",
"identity": "test-room-20240101120000",
"name": "Test Class"
},
"participant": {
"sid": "participant-user-1",
"identity": "1",
"state": "DISCONNECTED",
"name": "Test User",
"metadata": '{"is_admin": false}',
"permission": {
"canPublish": True,
"canPublishData": True,
"canSubscribe": True
},
"tracks": [],
"joinedAt": timestamp - 1800,
"duration": 1800
}
},
'end_recording': {
"event": "end_recording",
"id": "880e8400-e29b-41d4-a716-446655440003",
"createdAt": timestamp,
"room": {
"sid": "room-123456",
"identity": "test-room-20240101120000",
"name": "Test Class"
},
"recording_info": {
"recordingId": "rec-123456",
"roomId": "test-room-20240101120000",
"recordingType": "COMPOSITE",
"fileName": "test-room-20240101120000.mp4",
"duration": 3600,
"status": "FINISHED"
}
}
}
return payloads.get(event_type)
def send_webhook(event_type: str, dry_run: bool = False):
"""Send webhook request to the endpoint."""
# Get configuration
webhook_url = get_webhook_url()
api_secret = getattr(settings, 'PLUGNMEET_API_SECRET', '')
if not api_secret:
print("❌ Error: PLUGNMEET_API_SECRET not configured in settings")
return False
# Get test payload
payload = get_test_payload(event_type)
if not payload:
print(f"❌ Error: Unknown event type '{event_type}'")
print("Available event types: room_finished, participant_joined, participant_left, end_recording")
return False
# Convert payload to JSON string
payload_json = json.dumps(payload, ensure_ascii=False)
# Calculate signature
signature = calculate_signature(payload_json, api_secret)
# Print test information
print("\n" + "="*80)
print(f"🧪 Testing PlugNMeet Webhook: {event_type}")
print("="*80)
print(f"\n📍 URL: {webhook_url}")
print(f"\n📦 Payload:")
print(json.dumps(payload, indent=2, ensure_ascii=False))
print(f"\n🔐 Signature: {signature[:20]}...")
if dry_run:
print("\n⚠️ DRY RUN - Not sending actual request")
return True
# Send request
try:
headers = {
'Content-Type': 'application/webhook+json',
'Hash-Token': signature,
}
print("\n📤 Sending request...")
response = requests.post(
webhook_url,
data=payload_json.encode('utf-8'),
headers=headers,
timeout=10
)
print(f"\n✅ Response Status: {response.status_code}")
print(f"📄 Response Body:")
try:
print(json.dumps(response.json(), indent=2, ensure_ascii=False))
except:
print(response.text)
if response.status_code == 200:
print("\n✅ Webhook test successful!")
return True
else:
print(f"\n❌ Webhook test failed with status {response.status_code}")
return False
except requests.exceptions.RequestException as e:
print(f"\n❌ Error sending request: {e}")
return False
finally:
print("\n" + "="*80 + "\n")
def main():
"""Main function."""
if len(sys.argv) < 2:
print("Usage: python scripts/test_webhook.py [event_type]")
print("\nAvailable event types:")
print(" - room_finished")
print(" - participant_joined")
print(" - participant_left")
print(" - end_recording")
print("\nOptions:")
print(" --dry-run Show payload without sending request")
sys.exit(1)
event_type = sys.argv[1]
dry_run = '--dry-run' in sys.argv
success = send_webhook(event_type, dry_run=dry_run)
sys.exit(0 if success else 1)
if __name__ == '__main__':
main()