Skip to content

Commit

Permalink
Install dj_notify service on admin machines
Browse files Browse the repository at this point in the history
The dj_notify python scripts acts as a Slack webhook receiver, which
forwards the notifications to the desktop notifications and plays an
alert sound to notify everyone nearby.
  • Loading branch information
Kevinjil committed Oct 13, 2024
1 parent 66a0c2b commit 5f049ef
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 0 deletions.
2 changes: 2 additions & 0 deletions provision-contest/ansible/admin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
tags: clusterssh
- role: phpstorm
tags: phpstorm
- role: dj_notify
tags: dj_notify
- role: prometheus_target_all
tags: prometheus_target_all
when: GRAFANA_MONITORING
Expand Down
3 changes: 3 additions & 0 deletions provision-contest/ansible/roles/dj_notify/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ALSA_DEVICE: alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink
NOTIFICATION_SOUND: /usr/share/sounds/sound-icons/trumpet-12.wav
NOTIFICATION_SOUND_VOLUME: 35536
87 changes: 87 additions & 0 deletions provision-contest/ansible/roles/dj_notify/files/dj_notify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
import subprocess
import gi
import os
import webbrowser
import subprocess
import traceback
gi.require_version('Notify', '0.7')
from gi.repository import Notify

HOSTNAME = "0.0.0.0"
PORT = 9999
ALSA_DEVICE = os.environ['ALSA_DEVICE']
NOTIFICATION_SOUND = os.environ['NOTIFICATION_SOUND']
NOTIFICATION_SOUND_VOLUME = int(os.environ['NOTIFICATION_SOUND_VOLUME'])


def on_notification_closed(notification):
print(f"Notification {notification.id} closed.")


def on_link_click(notification, action, link):
webbrowser.open(link)


def filter_notification(title, body, link):
return not title.startswith("Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException")


class NotifyServer(BaseHTTPRequestHandler):
def create_notification(self, title, body, link):
notification = Notify.Notification.new(title, body)
notification.connect("closed", on_notification_closed)
notification.add_action(
"action_click",
"View in browser",
on_link_click,
link
)
notification.show()


def notification_sound(self, sound):
# Use Popen to launch a non-blocking background process
subprocess.Popen(["paplay", "--volume", str(NOTIFICATION_SOUND_VOLUME), "--device", ALSA_DEVICE, sound])


def do_POST(self):
length = int(self.headers.get('Content-Length'))
body = self.rfile.read(length)
content = json.loads(body)
print(json.dumps(content, indent=2))

att = content['attachments'][0]
title = att['title']
link = att['title_link']
body = att['text']

if filter_notification(title, body, link):
try:
self.create_notification(title, body, link)
except Exception:
print(traceback.format_exc())
try:
self.notification_sound(NOTIFICATION_SOUND)
except Exception:
print(traceback.format_exc())

self.send_response(200)
self.send_header("Content-Type", "text/plain")
self.end_headers()

self.wfile.write(bytes("ok", "utf-8"))


Notify.init("DOMjudge notifications")
server = HTTPServer((HOSTNAME, PORT), NotifyServer)

try:
server.serve_forever()
except KeyboardInterrupt:
pass

# Clean up
server.server_close()
Notify.uninit()
7 changes: 7 additions & 0 deletions provision-contest/ansible/roles/dj_notify/handlers/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
- name: Restart dj_notify
systemd:
name: dj_notify
enabled: true
state: restarted
daemon_reload: true
17 changes: 17 additions & 0 deletions provision-contest/ansible/roles/dj_notify/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
# These tasks install the DOMjudge Notify script

- name: Install dj_notify
copy:
src: "dj_notify.py"
dest: "/home/domjudge/bin/dj_notify.py"
owner: domjudge
group: domjudge
mode: 0755
notify: Restart dj_notify

- name: Copy dj_notify systemd unit file
template:
src: "dj_notify.service.j2"
dest: "/etc/systemd/system/dj_notify.service"
notify: Restart dj_notify
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[Unit]
Description="DOMjudge Notify"
After=network.target

[Service]
Type=simple

Environment=ALSA_DEVICE={{ ALSA_DEVICE }}
Environment=NOTIFICATION_SOUND={{ NOTIFICATION_SOUND }}
Environment=DISPLAY=:0
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1001/bus
Environment=PULSE_SERVER=/run/user/1001/pulse/native
WorkingDirectory=/home/domjudge
ExecStart=/usr/bin/python3 -u /home/domjudge/bin/dj_notify.py
User=domjudge

Restart=always
RestartSec=3

[Install]
WantedBy=graphical.target
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
GLITCHTIP_PORT: 8000
GLITCHTIP_TOKEN:
GLITCHTIP_WEBHOOK_DOMAIN: domjudge-ccsadmin2
20 changes: 20 additions & 0 deletions provision-contest/ansible/roles/glitchtip/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,26 @@
body_format: json
loop: "{{ ['setup-phase'] + groups['domserver'] }}"

- name: Create project dj_notify webhook
when: glitchtip_proj.json | community.general.json_query("[?name=='{{ item }}']") == []
ansible.builtin.uri:
method: POST
return_content: yes
url: "http://localhost:{{ GLITCHTIP_PORT }}/api/0/projects/domjudge/{{ item }}/alerts/"
status_code: 201
headers:
Authorization: "Bearer {{ GLITCHTIP_TOKEN }}"
body:
name: "dj_notify"
alertRecipients:
- recipientType: "webhook"
url: "http://{{ GLITCHTIP_WEBHOOK_DOMAIN }}:9999/"
timespanMinutes: 1
quantity: 1
uptime: true
body_format: json
loop: "{{ ['setup-phase'] + groups['domserver'] }}"

- name: Check for existing monitors
ansible.builtin.uri:
method: GET
Expand Down

0 comments on commit 5f049ef

Please sign in to comment.