Virus World Map ncurses application
| 183 | |
| 184 | |
| 185 | class MapApp(object): |
| 186 | """ Virus World Map ncurses application """ |
| 187 | def __init__(self, api): |
| 188 | self.api = api |
| 189 | self.data = None |
| 190 | self.last_fetch = 0 |
| 191 | self.sleep = 10 # tenths of seconds, for curses.halfdelay() |
| 192 | self.polling_interval = 60 |
| 193 | |
| 194 | def fetch_data(self, epoch_now, force_refresh=False): |
| 195 | """ (Re)fetch data from JSON stream """ |
| 196 | refresh = False |
| 197 | if force_refresh or self.data is None: |
| 198 | refresh = True |
| 199 | else: |
| 200 | if self.last_fetch + self.polling_interval <= epoch_now: |
| 201 | refresh = True |
| 202 | |
| 203 | if refresh: |
| 204 | try: |
| 205 | # Grab 20 banners from the main stream |
| 206 | banners = [] |
| 207 | for banner in self.api.stream.banners(): |
| 208 | if 'location' in banner and banner['location']['latitude']: |
| 209 | banners.append(banner) |
| 210 | if len(banners) >= 20: |
| 211 | break |
| 212 | self.data = banners |
| 213 | self.last_fetch = epoch_now |
| 214 | except APIError: |
| 215 | raise |
| 216 | return refresh |
| 217 | |
| 218 | def run(self, scr): |
| 219 | """ Initialize and run the application """ |
| 220 | m = AsciiMap() |
| 221 | curses.halfdelay(self.sleep) |
| 222 | while True: |
| 223 | now = int(time.time()) |
| 224 | refresh = self.fetch_data(now) |
| 225 | m.set_data(self.data) |
| 226 | try: |
| 227 | m.draw(scr) |
| 228 | except curses.error: |
| 229 | raise Exception('Terminal window too small') |
| 230 | scr.addstr(0, 1, 'Shodan Radar', curses.A_BOLD) |
| 231 | scr.addstr(0, 40, time.strftime("%c UTC", time.gmtime(now)).rjust(37), curses.A_BOLD) |
| 232 | |
| 233 | # Key Input |
| 234 | # q - Quit |
| 235 | event = scr.getch() |
| 236 | if event == ord('q'): |
| 237 | break |
| 238 | |
| 239 | # redraw window (to fix encoding/rendering bugs and to hide other messages to same tty) |
| 240 | # user pressed 'r' or new data was fetched |
| 241 | if refresh: |
| 242 | m.window.redrawwin() |