This article will teach you how to post Unifi Protect alerts to Discord using Webhook [name=John @ 崑山科技大學 光達實驗室 KSU Eilidar Lab][time=Thursday, September 26, 2024]
Because I want to receive notifications on my computer without using an Android emulator to install and run the Unifi Protect app.
I spent all night researching this because my friend, who is ten times smarter than I am, keeps calling me "dumb," "lazy," and "useless" :D
I hope this information provides what you need and saves you some sleep!
We need to set up a "UniFi Protect to Discord webhook data conversion server" on a computer using Python to reroute the alert data to Discord.
- In Discord, navigate to your
Server Settings
->Apps
->Integrations
->Webhooks
, and click onNew Webhook
- Change the profile picture, name, and the channel where you want to post your message by selecting the appropriate channel
- Copy the webhook URL by clicking on
Copy Webhook URL
- Create a Python file and name it whatever you prefer
- Open the Python file with your favorite text editor
- Copy and paste the code below into the file
from flask import Flask, request, jsonify
import requests
from datetime import datetime
app = Flask(__name__)
# Replace this with your Discord webhook URL
DISCORD_WEBHOOK_URL = 'YOUR_WEBHOOK_URL'
# Device ID to device name mapping
# Left column is the MAC adders of the device, and the right column is the name you want to convert it to.
DEVICE_NAME_MAPPING = {
'CAMERA_MAC_ADDERS': 'CAMERA_NAME',
'CAMERA_MAC_ADDERS': 'CAMERA_NAME',
'CAMERA_MAC_ADDERS': 'CAMERA_NAME'
}
@app.route('/data', methods=['POST'])
def data():
if request.is_json:
data = request.get_json()
# Extract necessary fields from the received data
if 'alarm' in data:
alarm = data['alarm']
triggers = alarm.get('triggers', [])
# Access the timestamp from the root of the JSON (not inside the alarm object)
timestamp = data.get('timestamp', None)
# Convert timestamp to human-readable format
readable_timestamp = convert_timestamp(timestamp)
# Prepare data to send to the create_discord_embed function
for trigger in triggers:
key = trigger.get('key', 'Unknown trigger')
device = trigger.get('device', 'Unknown device')
device_name = DEVICE_NAME_MAPPING.get(device, device)
# Call create_discord_embed with the key, device, and readable timestamp
discord_message = create_discord_embed(key, device_name, readable_timestamp)
# Send the embed to Discord
response = post_to_discord(discord_message)
return jsonify({"message": "JSON received and posted to Discord"}), 200
else:
return jsonify({"error": "Invalid JSON structure"}), 400
else:
return jsonify({"error": "Request must be JSON"}), 400
def post_to_discord(embed_message):
# Send the embed to Discord webhook
response = requests.post(DISCORD_WEBHOOK_URL, json=embed_message)
if response.status_code == 204:
return "Success"
else:
return f"Failed to post to Discord. Status code: {response.status_code}"
def create_discord_embed(trigger, device, timestamp):
# Create an embed for Discord
embed = {
"embeds": [
{
"title": "Alert Triggered :camera_with_flash: ",
"color": 16711680, # Red color
"fields": [
{
"name": "Trigger",
"value": trigger,
"inline": True
},
{
"name": "Device",
"value": device,
"inline": True
},
{
"name": "Timestamp",
"value": timestamp,
"inline": False
}
],
"footer": {
"text": "Unifi Protect",
"icon_url": "https://pbs.twimg.com/profile_images/1610157462321254402/tMCv8T-y_400x400.png" # Replace with your own icon URL
},
"timestamp": datetime.utcnow().isoformat() # Adds current time in ISO format for Discord
}
]
}
return embed
def convert_timestamp(timestamp):
# Convert the timestamp to a human-readable format
if timestamp:
try:
# Convert from milliseconds to seconds and format
dt_object = datetime.utcfromtimestamp(timestamp / 1000)
return dt_object.strftime('%Y-%m-%d %H:%M:%S UTC')
except Exception as e:
return "Invalid timestamp"
return "No timestamp available"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
-
Edit
DISCORD_WEBHOOK_URL
at line 8 to include the Discord webhook link that you obtained in step one -
Edit
DEVICE_NAME_MAPPING
at line 12; the left column should contain your camera's MAC address without the colons (:), and the right column should be the name you want it to display. You can add as many entries as you like -
Change the
port
at line 107 to any available port that is not being used by another process -
Start the server with Python using the following command:
python3 ./<your python file name>.py
- Go to your UniFi Protect Alarm panel
- Create an alarm and give it a name
- Select what you want the alarm to send to the webhook
- Change the action from
Send Notification
toWebhook
- Select
Custom Webhook
- Enter the IP address of the computer hosting the Python server created in step two into the
Delivery URL
input field like this:http://<your_ip>:<your_port>/data
- Check
Advanced Settings
and change the method toPOST
- Test it out, and you're all done!
- Email: [email protected]
- Discord: noobienoodle89