|
| 1 | +import os |
| 2 | +import threading |
| 3 | +from subprocess import Popen, DEVNULL |
| 4 | +from time import sleep |
| 5 | +from typing import Any, Dict |
| 6 | + |
| 7 | +import requests as requests |
| 8 | +from devdeck_core.controls.deck_control import DeckControl |
| 9 | + |
| 10 | + |
| 11 | +class GithubNotificationsControl(DeckControl): |
| 12 | + def __init__(self, key_no: int, **kwargs) -> None: |
| 13 | + super().__init__(key_no, **kwargs) |
| 14 | + self.thread = None |
| 15 | + self.running = False |
| 16 | + self.last_url = None |
| 17 | + |
| 18 | + def initialize(self) -> None: |
| 19 | + self.thread = threading.Thread(target=self._update_loop) |
| 20 | + self.running = True |
| 21 | + self.thread.start() |
| 22 | + |
| 23 | + def pressed(self) -> None: |
| 24 | + if self.last_url is None: |
| 25 | + self._update_display() |
| 26 | + return |
| 27 | + |
| 28 | + browser = self.settings.get('browser') or 'firefox' |
| 29 | + Popen([browser, self.last_url], stdout=DEVNULL, stderr=DEVNULL) |
| 30 | + |
| 31 | + # Wait 5 seconds for the browser to load the page before refreshing the display. |
| 32 | + sleep(5) |
| 33 | + self._update_display() |
| 34 | + |
| 35 | + def get_notifications(self) -> Dict[str, Any]: |
| 36 | + assert self.settings['token'], 'Please specify your Github API token in `settings.yml`' |
| 37 | + headers = { |
| 38 | + 'Authorization': f"token {self.settings['token']}", |
| 39 | + 'User-Agent': 'devdeck', |
| 40 | + } |
| 41 | + return requests.get('https://api.github.com/notifications', headers=headers).json() |
| 42 | + |
| 43 | + def _update_display(self) -> None: |
| 44 | + notifications = self.get_notifications() |
| 45 | + count = len(notifications) |
| 46 | + alert_color = self.settings.get('color') or '#ff2b2b' |
| 47 | + color = alert_color if count > 0 else '#ffffff' |
| 48 | + |
| 49 | + self.last_url = notifications[0]['subject']['url'] \ |
| 50 | + .replace('api.', '').replace('repos/', '').replace('pulls/', 'pull/') \ |
| 51 | + if count > 0 else None |
| 52 | + |
| 53 | + with self.deck_context() as context: |
| 54 | + with context.renderer() as r: |
| 55 | + r.image(os.path.join(os.path.dirname(__file__), "../assets/font-awesome", 'github.png')) \ |
| 56 | + .width(240) \ |
| 57 | + .height(240) \ |
| 58 | + .center_horizontally() \ |
| 59 | + .y(225) \ |
| 60 | + .end() |
| 61 | + |
| 62 | + r.text(str(count)) \ |
| 63 | + .center_horizontally() \ |
| 64 | + .center_vertically(-175) \ |
| 65 | + .font_size(150) \ |
| 66 | + .color(color) \ |
| 67 | + .end() |
| 68 | + |
| 69 | + def _update_loop(self) -> None: |
| 70 | + while self.running is True: |
| 71 | + self._update_display() |
| 72 | + sleep(self.settings.get('refresh_seconds') or 60) |
| 73 | + |
| 74 | + def dispose(self) -> None: |
| 75 | + self.running = False |
| 76 | + if self.thread: |
| 77 | + self.thread.join() |
0 commit comments