Skip to content

Instantly share code, notes, and snippets.

@n00rm
Last active April 25, 2026 23:56
Show Gist options
  • Select an option

  • Save n00rm/32f1334b1dd2efc40122fee36551ef17 to your computer and use it in GitHub Desktop.

Select an option

Save n00rm/32f1334b1dd2efc40122fee36551ef17 to your computer and use it in GitHub Desktop.
Discord Checkmk Notification Script
#!/usr/bin/env python3
# Notify via Discord
import os
import requests
import sys
USERNAME = "check_mk"
AVATARURL = "https://checkmk.com/favicon-96x96.png"
COLORS = {
"CRITICAL": "15597568",
"DOWN": "15597568",
"WARNING": "16768256",
"OK": "52224",
"UP": "52224",
"UNKNOWN": "13421772",
"UNREACHABLE": "13421772",
}
def discord_msg(context):
"""Build the message for discord"""
facts = []
if context.get('WHAT', None) == "SERVICE":
state = context["SERVICESTATE"]
color = COLORS.get(state)
subtitle = "Service Notification"
facts.append({"name": "Service:", "value": context["SERVICEDESC"]})
output = context["SERVICEOUTPUT"] if context["SERVICEOUTPUT"] else ""
else:
state = context["HOSTSTATE"]
color = COLORS.get(state)
subtitle = "Host Notification"
output = context["HOSTOUTPUT"] if context["HOSTOUTPUT"] else ""
facts.extend([
{
"name": "Host:",
"value": context["HOSTNAME"]
},
{
"name": "State:",
"value": state
}
])
return {
"username": USERNAME,
"avatar_url": AVATARURL,
"embeds": [
{
"title": subtitle,
"color": color,
"fields": facts,
"footer": {
"text": output
}
}
]
}
def collect_context():
return {
var[7:]: value
for (var, value) in os.environ.items()
if var.startswith("NOTIFY_")
}
def post_request(message_constructor, success_code=204):
context = collect_context()
url = context.get("PARAMETERS")
r = requests.post(url=url, json=message_constructor(context))
if r.status_code == success_code:
sys.exit(0)
else:
sys.stderr.write(
"Failed to send notification. Status: %i, Response: %s\n" % (r.status_code, r.text))
sys.exit(2)
if __name__ == "__main__":
post_request(discord_msg)
@Krankenkasse

Copy link
Copy Markdown

Perfekt, dankeschön!

@Hornochs

Copy link
Copy Markdown

Heyho :)
Danke dir erstmal für dein Skript! Bringt mich weiter :) Jedoch hab ich gemerkt, dass das System die selbe Notification zwei mal abschickt. Hast du eine Idee was es sein könnte?

LG
Horstie

@n00rm

n00rm commented Jun 15, 2021

Copy link
Copy Markdown
Author

Hi,
der Skript darf nur mit einem Benutzer aufgerufen werden. Bitte benutze den automation user dafür. Das sollte dein Problem lösen. 😉

@Hornochs

Copy link
Copy Markdown

Hehe, wie bereits im CheckMK Forum geschrieben, hast vollkommen recht 😄 Hier war ein Noob mal wieder am Werk

@Hornochs

Copy link
Copy Markdown

Hey there,

Sure it does. You must setup on CheckMK when he should notify snd over which way :)

@livi6191

livi6191 commented Jan 24, 2022

Copy link
Copy Markdown

Hey Guys,

Edit, managed to get it working but getting the following error now:

cat notify.log
2022-01-24 02:00:59,353 [20] [cmk.base.notify] ----------------------------------------------------------------------
2022-01-24 02:00:59,353 [20] [cmk.base.notify] Got raw notification (UNKNOWN) context with 0 variables
2022-01-24 02:00:59,353 [20] [cmk.base.events] Error on completing raw context: 'HOSTNAME'
2022-01-24 02:00:59,354 [40] [cmk.base.notify] ERROR:
Traceback (most recent call last):
File "/omd/sites/ad/lib/python3/cmk/base/notify.py", line 355, in locally_deliver_raw_context
return notify_rulebased(raw_context, analyse=analyse)
File "/omd/sites/ad/lib/python3/cmk/base/notify.py", line 474, in notify_rulebased
why_not = rbn_match_rule(rule, raw_context)
File "/omd/sites/ad/lib/python3/cmk/base/notify.py", line 804, in rbn_match_rule
return events.apply_matchers([
File "/omd/sites/ad/lib/python3/cmk/base/events.py", line 414, in apply_matchers
result = matcher(rule, context)
File "/omd/sites/ad/lib/python3/cmk/base/events.py", line 421, in event_match_rule
return apply_matchers([
File "/omd/sites/ad/lib/python3/cmk/base/events.py", line 414, in apply_matchers
result = matcher(rule, context)
File "/omd/sites/ad/lib/python3/cmk/base/events.py", line 675, in event_match_exclude_hosts
if context["HOSTNAME"] in rule.get("match_exclude_hosts", []):
KeyError: 'HOSTNAME'

Thanks

@n00rm

n00rm commented Jan 24, 2022

Copy link
Copy Markdown
Author

Hi,

I answered your forum post to you problem.
Have a look and let me know if it helps you -> https://forum.checkmk.com/t/check-mk-discord-notification/29311/4?u=norm

Kind Regards
Norm

@qhgh

qhgh commented May 9, 2023

Copy link
Copy Markdown

Hi Norm,

Is there any way to have this script use the webhook with the 'role mention role id' so it can @ tag people?

I assume maybe somewhere here?

def post_request(message_constructor, success_code=204):
    context = collect_context()

    url = context.get("PARAMETERS")
    r = requests.post(url=url, json=message_constructor(context))

Thanks,
C

@n00rm

n00rm commented May 12, 2023

Copy link
Copy Markdown
Author

Hi @qhgh

yes it should be pretty easy to add that function.
You can use the Enviroment Variables to get that info to the script.
https://docs.checkmk.com/latest/en/notifications.html#_environment_variables

You could use the Pager ID as a mention Role ID or create multiple notification rule with the mention id as a parameter and use the NOTIFY_PARAMETER_2 variable.


#!/usr/bin/env python3
# Notify via Discord

import os
import requests
import sys

USERNAME = "check_mk"
AVATARURL = "https://checkmk.com/favicon-96x96.png"

COLORS = {
    "CRITICAL": "15597568",
    "DOWN": "15597568",
    "WARNING": "16768256",
    "OK": "52224",
    "UP": "52224",
    "UNKNOWN": "13421772",
    "UNREACHABLE": "13421772",
}

# Add the role mention ID here
# you could also use Variables from here https://docs.checkmk.com/latest/en/notifications.html#_environment_variables
ROLE_MENTION_ID = "your_role_id"

def discord_msg(context):
    """Build the message for discord"""
    facts = []
    if context.get('WHAT', None) == "SERVICE":
        state = context["SERVICESTATE"]
        color = COLORS.get(state)
        subtitle = "Service Notification"
        facts.append({"name": "Service:", "value": context["SERVICEDESC"]})
        output = context["SERVICEOUTPUT"] if context["SERVICEOUTPUT"] else ""
    else:
        state = context["HOSTSTATE"]
        color = COLORS.get(state)
        subtitle = "Host Notification"
        output = context["HOSTOUTPUT"] if context["HOSTOUTPUT"] else ""

    facts.extend([
        {
            "name": "Host:",
            "value": context["HOSTNAME"]
        },
        {
            "name": "State:",
            "value": state
        }
    ])

    mention = f"<@&{ROLE_MENTION_ID}>"
    
    return {
        "username": USERNAME,
        "avatar_url": AVATARURL,
        "content": mention,  # Add the role mention here
        "embeds": [
        {
            "title": subtitle,
            "color": color,
            "fields": facts,
            "footer": {
               "text": output
           }
        }
        ]
    }

# Rest of the code...


Hope this helps.

@qhgh

qhgh commented May 12, 2023

Copy link
Copy Markdown

Thanks very much n00m!

I gave it a try but it errors:

2023-05-12 14:19:11   * notifying discord via xnewdiscord.py, parameters: https://discord.com/api/webhooks/example, bulk: no
2023-05-12 14:19:11      executing /omd/sites/dc1/local/share/check_mk/notifications/xnewdiscord.py
2023-05-12 14:19:11      Output:   File "/omd/sites/dc1/local/share/check_mk/notifications/xnewdiscord.py", line 92
2023-05-12 14:19:11      Output:     post_request(discord_msg).
2023-05-12 14:19:11      Output:                              ^
2023-05-12 14:19:11      Output: SyntaxError: invalid syntax
2023-05-12 14:19:11      Plugin exited with code 1

I have the file like so:

#!/usr/bin/env python3
# n00m Notify via Discord

import os
import requests
import sys

USERNAME = "check_mk"
AVATARURL = "https://checkmk.com/favicon-96x96.png"

COLORS = {
    "CRITICAL": "15597568",
    "DOWN": "15597568",
    "WARNING": "16768256",
    "OK": "52224",
    "UP": "52224",
    "UNKNOWN": "13421772",
    "UNREACHABLE": "13421772",
}

# Add the role mention ID here
# you could also use Variables from here https://docs.checkmk.com/latest/en/notifications.html#_environment_variables
ROLE_MENTION_ID = "123example123"

def discord_msg(context):
    """Build the message for discord"""
    facts = []
    if context.get('WHAT', None) == "SERVICE":
        state = context["SERVICESTATE"]
        color = COLORS.get(state)
        subtitle = "Service Notification"
        facts.append({"name": "Service:", "value": context["SERVICEDESC"]})
        output = context["SERVICEOUTPUT"] if context["SERVICEOUTPUT"] else ""
    else:
        state = context["HOSTSTATE"]
        color = COLORS.get(state)
        subtitle = "Host Notification"
        output = context["HOSTOUTPUT"] if context["HOSTOUTPUT"] else ""

    facts.extend([
        {
            "name": "Host:",
            "value": context["HOSTNAME"]
        },
        {
            "name": "State:",
            "value": state
        }
    ])

    mention = f"<@&{ROLE_MENTION_ID}>"

    return {
        "username": USERNAME,
        "avatar_url": AVATARURL,
        "content": mention,  # Add the role mention here
        "embeds": [
        {
            "title": subtitle,
            "color": color,
            "fields": facts,
            "footer": {
               "text": output
           }
        }
        ]
    }

# Rest of the code..

def collect_context():
    return {
        var[7:]: value
        for (var, value) in os.environ.items()
        if var.startswith("NOTIFY_")
    }

def post_request(message_constructor, success_code=204):
    context = collect_context()

    url = context.get("PARAMETERS")
    r = requests.post(url=url, json=message_constructor(context))

    if r.status_code == success_code:
        sys.exit(0)
    else:
        sys.stderr.write(
            "Failed to send notification. Status: %i, Response: %s\n" % (r.status_code, r.text))
        sys.exit(2)

if __name__ == "__main__":
    post_request(discord_msg).

Did I get that right?
Thanks!
C

@muzza-sys

Copy link
Copy Markdown

Thanks very much n00m!

I gave it a try but it errors:

2023-05-12 14:19:11   * notifying discord via xnewdiscord.py, parameters: https://discord.com/api/webhooks/example, bulk: no
2023-05-12 14:19:11      executing /omd/sites/dc1/local/share/check_mk/notifications/xnewdiscord.py
2023-05-12 14:19:11      Output:   File "/omd/sites/dc1/local/share/check_mk/notifications/xnewdiscord.py", line 92
2023-05-12 14:19:11      Output:     post_request(discord_msg).
2023-05-12 14:19:11      Output:                              ^
2023-05-12 14:19:11      Output: SyntaxError: invalid syntax
2023-05-12 14:19:11      Plugin exited with code 1

I have the file like so:

#!/usr/bin/env python3
# n00m Notify via Discord

import os
import requests
import sys

USERNAME = "check_mk"
AVATARURL = "https://checkmk.com/favicon-96x96.png"

COLORS = {
    "CRITICAL": "15597568",
    "DOWN": "15597568",
    "WARNING": "16768256",
    "OK": "52224",
    "UP": "52224",
    "UNKNOWN": "13421772",
    "UNREACHABLE": "13421772",
}

# Add the role mention ID here
# you could also use Variables from here https://docs.checkmk.com/latest/en/notifications.html#_environment_variables
ROLE_MENTION_ID = "123example123"

def discord_msg(context):
    """Build the message for discord"""
    facts = []
    if context.get('WHAT', None) == "SERVICE":
        state = context["SERVICESTATE"]
        color = COLORS.get(state)
        subtitle = "Service Notification"
        facts.append({"name": "Service:", "value": context["SERVICEDESC"]})
        output = context["SERVICEOUTPUT"] if context["SERVICEOUTPUT"] else ""
    else:
        state = context["HOSTSTATE"]
        color = COLORS.get(state)
        subtitle = "Host Notification"
        output = context["HOSTOUTPUT"] if context["HOSTOUTPUT"] else ""

    facts.extend([
        {
            "name": "Host:",
            "value": context["HOSTNAME"]
        },
        {
            "name": "State:",
            "value": state
        }
    ])

    mention = f"<@&{ROLE_MENTION_ID}>"

    return {
        "username": USERNAME,
        "avatar_url": AVATARURL,
        "content": mention,  # Add the role mention here
        "embeds": [
        {
            "title": subtitle,
            "color": color,
            "fields": facts,
            "footer": {
               "text": output
           }
        }
        ]
    }

# Rest of the code..

def collect_context():
    return {
        var[7:]: value
        for (var, value) in os.environ.items()
        if var.startswith("NOTIFY_")
    }

def post_request(message_constructor, success_code=204):
    context = collect_context()

    url = context.get("PARAMETERS")
    r = requests.post(url=url, json=message_constructor(context))

    if r.status_code == success_code:
        sys.exit(0)
    else:
        sys.stderr.write(
            "Failed to send notification. Status: %i, Response: %s\n" % (r.status_code, r.text))
        sys.exit(2)

if __name__ == "__main__":
    post_request(discord_msg).

Did I get that right? Thanks! C

You have a full stop at the end of the code, please remove

@qhgh

qhgh commented May 12, 2023

Copy link
Copy Markdown

Doh!

@Glowsome

Glowsome commented Aug 30, 2023

Copy link
Copy Markdown

Would it be possible to make a switch so notifications become more condensed ?
Meaning the discord message becomes more lean and displays as following:
Service Notification: (carriage return here) Service: service name (carriage return here) Host: Hostname (carriage return here) State: State_here (carriage return here) Detail: detail msg here (carriage return here)

Why : when you have a large amount of hosts it is preferable to see the messages in a more condensed way (saves scrolling).

Hope to hear back from you :)

@Glowsome

Copy link
Copy Markdown

Also one thing i did change in the script was the value of AVATARURL.
For some reason it never took hold, and got the default 'Wumpus' avatar witth the notifications.

After some digging i changed it to : "https://checkmk.com/android-chrome-192x192.png" - which works and shows the logo of CMK as avatar.

@fschlag

fschlag commented Feb 2, 2024

Copy link
Copy Markdown

Inspired by your plugin I also extended it a lot for my homelab an pushed all changes to a dedicated repo in case someone else wants to use it: https://github.com/fschlag/cmk_discord

@n00rm

n00rm commented Feb 5, 2024

Copy link
Copy Markdown
Author

Inspired by your plugin I also extended it a lot for my homelab an pushed all changes to a dedicated repo in case someone else wants to use it: https://github.com/fschlag/cmk_discord

Thanks @fschlag! Looks good and future development should and will be done in your project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment