libwatchduty 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. libwatchduty-0.1.0/.gitignore +81 -0
  2. libwatchduty-0.1.0/PKG-INFO +223 -0
  3. libwatchduty-0.1.0/README.md +207 -0
  4. libwatchduty-0.1.0/docs/screenshots/README.md +11 -0
  5. libwatchduty-0.1.0/pyproject.toml +45 -0
  6. libwatchduty-0.1.0/src/libwatchduty/__init__.py +9 -0
  7. libwatchduty-0.1.0/src/libwatchduty/__main__.py +5 -0
  8. libwatchduty-0.1.0/src/libwatchduty/aircraft.py +148 -0
  9. libwatchduty-0.1.0/src/libwatchduty/cli.py +1638 -0
  10. libwatchduty-0.1.0/src/libwatchduty/client.py +544 -0
  11. libwatchduty-0.1.0/src/libwatchduty/colors.py +99 -0
  12. libwatchduty-0.1.0/src/libwatchduty/geo_landmarks.py +193 -0
  13. libwatchduty-0.1.0/src/libwatchduty/images.py +198 -0
  14. libwatchduty-0.1.0/src/libwatchduty/install_mapscii.py +73 -0
  15. libwatchduty-0.1.0/src/libwatchduty/location.py +209 -0
  16. libwatchduty-0.1.0/src/libwatchduty/stills.py +184 -0
  17. libwatchduty-0.1.0/src/libwatchduty/tables.py +455 -0
  18. libwatchduty-0.1.0/src/libwatchduty/tui.py +4855 -0
  19. libwatchduty-0.1.0/vendor/mapscii/node_modules/.bin/mapscii +1 -0
  20. libwatchduty-0.1.0/vendor/mapscii/node_modules/.bin/pbf +1 -0
  21. libwatchduty-0.1.0/vendor/mapscii/node_modules/.package-lock.json +258 -0
  22. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/point-geometry/.travis.yml +8 -0
  23. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/point-geometry/HISTORY.md +5 -0
  24. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/point-geometry/LICENSE +13 -0
  25. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/point-geometry/README.md +364 -0
  26. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/point-geometry/index.js +312 -0
  27. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/point-geometry/package.json +33 -0
  28. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/point-geometry/test.js +139 -0
  29. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/.eslintrc +3 -0
  30. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/.travis.yml +7 -0
  31. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/CHANGELOG.md +41 -0
  32. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/LICENSE.txt +28 -0
  33. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/README.md +104 -0
  34. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/fixtures.js +157 -0
  35. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/index.js +3 -0
  36. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/package.json +33 -0
  37. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/proto/vector_tile.proto +88 -0
  38. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/bench.js +36 -0
  39. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/12-1143-1497.vector.pbf +0 -0
  40. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/14-8801-5371.vector.pbf +0 -0
  41. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/lots-of-tags.vector.pbf +0 -0
  42. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/multi-line.pbf +4 -0
  43. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/multi-point.pbf +2 -0
  44. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/multi-polygon.pbf +0 -0
  45. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/multipolygon-with-closepath.pbf +0 -0
  46. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/multipolygon.pbf +0 -0
  47. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/polygon-with-inner.pbf +0 -0
  48. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/singleton-multi-line.pbf +3 -0
  49. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/singleton-multi-point.pbf +2 -0
  50. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/singleton-multi-polygon.pbf +0 -0
  51. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/stacked-multipolygon.pbf +0 -0
  52. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/zero-line.pbf +0 -0
  53. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/zero-point.pbf +0 -0
  54. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/fixtures/zero-polygon.pbf +0 -0
  55. libwatchduty-0.1.0/vendor/mapscii/node_modules/@mapbox/vector-tile/test/parse.test.js +225 -0
  56. libwatchduty-0.1.0/vendor/mapscii/node_modules/ansi-regex/index.d.ts +37 -0
  57. libwatchduty-0.1.0/vendor/mapscii/node_modules/ansi-regex/index.js +10 -0
  58. libwatchduty-0.1.0/vendor/mapscii/node_modules/ansi-regex/license +9 -0
  59. libwatchduty-0.1.0/vendor/mapscii/node_modules/ansi-regex/package.json +55 -0
  60. libwatchduty-0.1.0/vendor/mapscii/node_modules/ansi-regex/readme.md +78 -0
  61. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/LICENSE +21 -0
  62. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/README.md +57 -0
  63. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/changelog.md +1 -0
  64. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/browser/bluebird.core.js +3914 -0
  65. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/browser/bluebird.core.min.js +31 -0
  66. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/browser/bluebird.js +5778 -0
  67. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/browser/bluebird.min.js +31 -0
  68. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/any.js +21 -0
  69. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/assert.js +55 -0
  70. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/async.js +120 -0
  71. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/bind.js +67 -0
  72. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/bluebird.js +11 -0
  73. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/call_get.js +123 -0
  74. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/cancel.js +129 -0
  75. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/catch_filter.js +42 -0
  76. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/context.js +69 -0
  77. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/debuggability.js +1009 -0
  78. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/direct_resolve.js +46 -0
  79. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/each.js +30 -0
  80. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/errors.js +116 -0
  81. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/es5.js +80 -0
  82. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/filter.js +12 -0
  83. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/finally.js +146 -0
  84. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/generators.js +223 -0
  85. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/join.js +165 -0
  86. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/map.js +175 -0
  87. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/method.js +55 -0
  88. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/nodeback.js +51 -0
  89. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/nodeify.js +58 -0
  90. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/promise.js +819 -0
  91. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/promise_array.js +186 -0
  92. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/promisify.js +314 -0
  93. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/props.js +118 -0
  94. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/queue.js +73 -0
  95. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/race.js +49 -0
  96. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/reduce.js +183 -0
  97. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/schedule.js +62 -0
  98. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/settle.js +47 -0
  99. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/some.js +148 -0
  100. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/synchronous_inspection.js +103 -0
  101. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/thenables.js +86 -0
  102. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/timers.js +93 -0
  103. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/using.js +226 -0
  104. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/js/release/util.js +421 -0
  105. libwatchduty-0.1.0/vendor/mapscii/node_modules/bluebird/package.json +78 -0
  106. libwatchduty-0.1.0/vendor/mapscii/node_modules/bresenham/.npmignore +25 -0
  107. libwatchduty-0.1.0/vendor/mapscii/node_modules/bresenham/.travis.yml +7 -0
  108. libwatchduty-0.1.0/vendor/mapscii/node_modules/bresenham/LICENSE +21 -0
  109. libwatchduty-0.1.0/vendor/mapscii/node_modules/bresenham/README.md +44 -0
  110. libwatchduty-0.1.0/vendor/mapscii/node_modules/bresenham/example.js +3 -0
  111. libwatchduty-0.1.0/vendor/mapscii/node_modules/bresenham/generator.js +28 -0
  112. libwatchduty-0.1.0/vendor/mapscii/node_modules/bresenham/index.js +33 -0
  113. libwatchduty-0.1.0/vendor/mapscii/node_modules/bresenham/package.json +29 -0
  114. libwatchduty-0.1.0/vendor/mapscii/node_modules/bresenham/test/index.js +64 -0
  115. libwatchduty-0.1.0/vendor/mapscii/node_modules/earcut/LICENSE +15 -0
  116. libwatchduty-0.1.0/vendor/mapscii/node_modules/earcut/README.md +255 -0
  117. libwatchduty-0.1.0/vendor/mapscii/node_modules/earcut/package.json +43 -0
  118. libwatchduty-0.1.0/vendor/mapscii/node_modules/earcut/src/earcut.js +681 -0
  119. libwatchduty-0.1.0/vendor/mapscii/node_modules/emoji-regex/LICENSE-MIT.txt +20 -0
  120. libwatchduty-0.1.0/vendor/mapscii/node_modules/emoji-regex/README.md +73 -0
  121. libwatchduty-0.1.0/vendor/mapscii/node_modules/emoji-regex/es2015/index.js +6 -0
  122. libwatchduty-0.1.0/vendor/mapscii/node_modules/emoji-regex/es2015/text.js +6 -0
  123. libwatchduty-0.1.0/vendor/mapscii/node_modules/emoji-regex/index.d.ts +23 -0
  124. libwatchduty-0.1.0/vendor/mapscii/node_modules/emoji-regex/index.js +6 -0
  125. libwatchduty-0.1.0/vendor/mapscii/node_modules/emoji-regex/package.json +50 -0
  126. libwatchduty-0.1.0/vendor/mapscii/node_modules/emoji-regex/text.js +6 -0
  127. libwatchduty-0.1.0/vendor/mapscii/node_modules/ieee754/LICENSE +11 -0
  128. libwatchduty-0.1.0/vendor/mapscii/node_modules/ieee754/README.md +51 -0
  129. libwatchduty-0.1.0/vendor/mapscii/node_modules/ieee754/index.d.ts +10 -0
  130. libwatchduty-0.1.0/vendor/mapscii/node_modules/ieee754/index.js +85 -0
  131. libwatchduty-0.1.0/vendor/mapscii/node_modules/ieee754/package.json +52 -0
  132. libwatchduty-0.1.0/vendor/mapscii/node_modules/is-fullwidth-code-point/index.d.ts +17 -0
  133. libwatchduty-0.1.0/vendor/mapscii/node_modules/is-fullwidth-code-point/index.js +50 -0
  134. libwatchduty-0.1.0/vendor/mapscii/node_modules/is-fullwidth-code-point/license +9 -0
  135. libwatchduty-0.1.0/vendor/mapscii/node_modules/is-fullwidth-code-point/package.json +42 -0
  136. libwatchduty-0.1.0/vendor/mapscii/node_modules/is-fullwidth-code-point/readme.md +39 -0
  137. libwatchduty-0.1.0/vendor/mapscii/node_modules/keypress/README.md +101 -0
  138. libwatchduty-0.1.0/vendor/mapscii/node_modules/keypress/index.js +408 -0
  139. libwatchduty-0.1.0/vendor/mapscii/node_modules/keypress/package.json +20 -0
  140. libwatchduty-0.1.0/vendor/mapscii/node_modules/keypress/test.js +28 -0
  141. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/.eslintrc.js +36 -0
  142. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/.github/ISSUE_TEMPLATE/BugReport.md +26 -0
  143. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/.github/ISSUE_TEMPLATE/FeatureRequest.md +22 -0
  144. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/.github/ISSUE_TEMPLATE/Question.md +14 -0
  145. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/.github/ISSUE_TEMPLATE/Support.md +15 -0
  146. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/.travis.yml +9 -0
  147. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/AUTHORS +7 -0
  148. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/LICENSE +22 -0
  149. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/README.md +144 -0
  150. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/bin/mapscii.sh +6 -0
  151. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/main.js +55 -0
  152. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/package.json +49 -0
  153. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/snap/snapcraft.yaml +19 -0
  154. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/BrailleBuffer.js +211 -0
  155. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/Canvas.js +202 -0
  156. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/LabelBuffer.js +57 -0
  157. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/Mapscii.js +322 -0
  158. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/Renderer.js +340 -0
  159. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/Styler.js +133 -0
  160. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/Tile.js +167 -0
  161. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/TileSource.js +177 -0
  162. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/TileSource.spec.js +12 -0
  163. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/config.js +52 -0
  164. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/utils.js +103 -0
  165. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/src/utils.spec.js +47 -0
  166. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/styles/bright.json +2191 -0
  167. libwatchduty-0.1.0/vendor/mapscii/node_modules/mapscii/styles/dark.json +1560 -0
  168. libwatchduty-0.1.0/vendor/mapscii/node_modules/node-fetch/LICENSE.md +22 -0
  169. libwatchduty-0.1.0/vendor/mapscii/node_modules/node-fetch/README.md +634 -0
  170. libwatchduty-0.1.0/vendor/mapscii/node_modules/node-fetch/browser.js +25 -0
  171. libwatchduty-0.1.0/vendor/mapscii/node_modules/node-fetch/package.json +89 -0
  172. libwatchduty-0.1.0/vendor/mapscii/node_modules/pbf/LICENSE +27 -0
  173. libwatchduty-0.1.0/vendor/mapscii/node_modules/pbf/README.md +453 -0
  174. libwatchduty-0.1.0/vendor/mapscii/node_modules/pbf/bin/pbf +19 -0
  175. libwatchduty-0.1.0/vendor/mapscii/node_modules/pbf/compile.js +435 -0
  176. libwatchduty-0.1.0/vendor/mapscii/node_modules/pbf/index.js +642 -0
  177. libwatchduty-0.1.0/vendor/mapscii/node_modules/pbf/package.json +81 -0
  178. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/.travis.yml +7 -0
  179. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/LICENSE +21 -0
  180. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/README.md +122 -0
  181. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/example.js +11 -0
  182. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/example.proto +13 -0
  183. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/index.js +6 -0
  184. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/package.json +31 -0
  185. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/parse.js +769 -0
  186. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/stringify.js +206 -0
  187. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/basic.json +90 -0
  188. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/basic.proto +11 -0
  189. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/comments.json +99 -0
  190. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/comments.proto +19 -0
  191. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/complex.json +125 -0
  192. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/complex.proto +30 -0
  193. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/enum.json +42 -0
  194. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/enum.proto +8 -0
  195. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/escaped-quotes.json +32 -0
  196. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/escaped-quotes.proto +3 -0
  197. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/extend.json +167 -0
  198. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/extend.proto +19 -0
  199. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/import.json +30 -0
  200. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/import.proto +6 -0
  201. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/map.json +33 -0
  202. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/map.proto +3 -0
  203. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/no-tags.proto +8 -0
  204. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/oneof.json +41 -0
  205. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/oneof.proto +6 -0
  206. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/option.json +364 -0
  207. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/option.proto +72 -0
  208. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/options.json +47 -0
  209. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/options.proto +8 -0
  210. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/pheromon-trajectories.proto +8 -0
  211. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/reserved.json +55 -0
  212. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/reserved.proto +17 -0
  213. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/search.json +30 -0
  214. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/search.proto +5 -0
  215. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/service.json +108 -0
  216. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/service.proto +30 -0
  217. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/valid-packed.proto +35 -0
  218. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/version.json +90 -0
  219. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/fixtures/version.proto +13 -0
  220. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/test/index.js +157 -0
  221. libwatchduty-0.1.0/vendor/mapscii/node_modules/protocol-buffers-schema/tokenize.js +56 -0
  222. libwatchduty-0.1.0/vendor/mapscii/node_modules/quickselect/LICENSE +15 -0
  223. libwatchduty-0.1.0/vendor/mapscii/node_modules/quickselect/README.md +28 -0
  224. libwatchduty-0.1.0/vendor/mapscii/node_modules/quickselect/index.js +54 -0
  225. libwatchduty-0.1.0/vendor/mapscii/node_modules/quickselect/package.json +43 -0
  226. libwatchduty-0.1.0/vendor/mapscii/node_modules/quickselect/quickselect.js +63 -0
  227. libwatchduty-0.1.0/vendor/mapscii/node_modules/rbush/LICENSE +21 -0
  228. libwatchduty-0.1.0/vendor/mapscii/node_modules/rbush/README.md +218 -0
  229. libwatchduty-0.1.0/vendor/mapscii/node_modules/rbush/index.js +512 -0
  230. libwatchduty-0.1.0/vendor/mapscii/node_modules/rbush/package.json +56 -0
  231. libwatchduty-0.1.0/vendor/mapscii/node_modules/rbush/rbush.js +574 -0
  232. libwatchduty-0.1.0/vendor/mapscii/node_modules/rbush/rbush.min.js +1 -0
  233. libwatchduty-0.1.0/vendor/mapscii/node_modules/resolve-protobuf-schema/.travis.yml +3 -0
  234. libwatchduty-0.1.0/vendor/mapscii/node_modules/resolve-protobuf-schema/LICENSE +21 -0
  235. libwatchduty-0.1.0/vendor/mapscii/node_modules/resolve-protobuf-schema/README.md +49 -0
  236. libwatchduty-0.1.0/vendor/mapscii/node_modules/resolve-protobuf-schema/index.js +50 -0
  237. libwatchduty-0.1.0/vendor/mapscii/node_modules/resolve-protobuf-schema/package.json +25 -0
  238. libwatchduty-0.1.0/vendor/mapscii/node_modules/resolve-protobuf-schema/test/a.proto +5 -0
  239. libwatchduty-0.1.0/vendor/mapscii/node_modules/resolve-protobuf-schema/test/b.proto +5 -0
  240. libwatchduty-0.1.0/vendor/mapscii/node_modules/resolve-protobuf-schema/test/c.proto +3 -0
  241. libwatchduty-0.1.0/vendor/mapscii/node_modules/resolve-protobuf-schema/test/index.js +49 -0
  242. libwatchduty-0.1.0/vendor/mapscii/node_modules/simplify-js/LICENSE +22 -0
  243. libwatchduty-0.1.0/vendor/mapscii/node_modules/simplify-js/README.md +19 -0
  244. libwatchduty-0.1.0/vendor/mapscii/node_modules/simplify-js/index.d.ts +9 -0
  245. libwatchduty-0.1.0/vendor/mapscii/node_modules/simplify-js/package.json +38 -0
  246. libwatchduty-0.1.0/vendor/mapscii/node_modules/simplify-js/simplify.js +123 -0
  247. libwatchduty-0.1.0/vendor/mapscii/node_modules/string-width/index.d.ts +29 -0
  248. libwatchduty-0.1.0/vendor/mapscii/node_modules/string-width/index.js +47 -0
  249. libwatchduty-0.1.0/vendor/mapscii/node_modules/string-width/license +9 -0
  250. libwatchduty-0.1.0/vendor/mapscii/node_modules/string-width/package.json +56 -0
  251. libwatchduty-0.1.0/vendor/mapscii/node_modules/string-width/readme.md +50 -0
  252. libwatchduty-0.1.0/vendor/mapscii/node_modules/strip-ansi/index.d.ts +17 -0
  253. libwatchduty-0.1.0/vendor/mapscii/node_modules/strip-ansi/index.js +4 -0
  254. libwatchduty-0.1.0/vendor/mapscii/node_modules/strip-ansi/license +9 -0
  255. libwatchduty-0.1.0/vendor/mapscii/node_modules/strip-ansi/package.json +54 -0
  256. libwatchduty-0.1.0/vendor/mapscii/node_modules/strip-ansi/readme.md +46 -0
  257. libwatchduty-0.1.0/vendor/mapscii/node_modules/term-mouse/History.md +5 -0
  258. libwatchduty-0.1.0/vendor/mapscii/node_modules/term-mouse/LICENSE +20 -0
  259. libwatchduty-0.1.0/vendor/mapscii/node_modules/term-mouse/README.md +54 -0
  260. libwatchduty-0.1.0/vendor/mapscii/node_modules/term-mouse/index.js +204 -0
  261. libwatchduty-0.1.0/vendor/mapscii/node_modules/term-mouse/package.json +10 -0
  262. libwatchduty-0.1.0/vendor/mapscii/node_modules/term-mouse/test.js +12 -0
  263. libwatchduty-0.1.0/vendor/mapscii/node_modules/tr46/.npmignore +4 -0
  264. libwatchduty-0.1.0/vendor/mapscii/node_modules/tr46/index.js +193 -0
  265. libwatchduty-0.1.0/vendor/mapscii/node_modules/tr46/package.json +31 -0
  266. libwatchduty-0.1.0/vendor/mapscii/node_modules/userhome/LICENSE-MIT +22 -0
  267. libwatchduty-0.1.0/vendor/mapscii/node_modules/userhome/README.md +27 -0
  268. libwatchduty-0.1.0/vendor/mapscii/node_modules/userhome/index.js +14 -0
  269. libwatchduty-0.1.0/vendor/mapscii/node_modules/userhome/package.json +35 -0
  270. libwatchduty-0.1.0/vendor/mapscii/node_modules/userhome/test.js +19 -0
  271. libwatchduty-0.1.0/vendor/mapscii/node_modules/webidl-conversions/LICENSE.md +12 -0
  272. libwatchduty-0.1.0/vendor/mapscii/node_modules/webidl-conversions/README.md +53 -0
  273. libwatchduty-0.1.0/vendor/mapscii/node_modules/webidl-conversions/package.json +23 -0
  274. libwatchduty-0.1.0/vendor/mapscii/node_modules/whatwg-url/LICENSE.txt +21 -0
  275. libwatchduty-0.1.0/vendor/mapscii/node_modules/whatwg-url/README.md +67 -0
  276. libwatchduty-0.1.0/vendor/mapscii/node_modules/whatwg-url/package.json +32 -0
  277. libwatchduty-0.1.0/vendor/mapscii/node_modules/x256/.travis.yml +6 -0
  278. libwatchduty-0.1.0/vendor/mapscii/node_modules/x256/colors.json +256 -0
  279. libwatchduty-0.1.0/vendor/mapscii/node_modules/x256/example/charm.js +5 -0
  280. libwatchduty-0.1.0/vendor/mapscii/node_modules/x256/example/ix.js +3 -0
  281. libwatchduty-0.1.0/vendor/mapscii/node_modules/x256/example/raw.js +3 -0
  282. libwatchduty-0.1.0/vendor/mapscii/node_modules/x256/index.js +35 -0
  283. libwatchduty-0.1.0/vendor/mapscii/node_modules/x256/package.json +53 -0
  284. libwatchduty-0.1.0/vendor/mapscii/node_modules/x256/readme.markdown +83 -0
  285. libwatchduty-0.1.0/vendor/mapscii/node_modules/x256/test/id.js +36 -0
  286. libwatchduty-0.1.0/vendor/mapscii/package-lock.json +265 -0
  287. libwatchduty-0.1.0/vendor/mapscii/package.json +9 -0
@@ -0,0 +1,81 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+
7
+ # Distribution / packaging
8
+ .Python
9
+ build/
10
+ develop-eggs/
11
+ dist/
12
+ downloads/
13
+ eggs/
14
+ .eggs/
15
+ lib/
16
+ lib64/
17
+ parts/
18
+ sdist/
19
+ var/
20
+ wheels/
21
+ *.egg-info/
22
+ .installed.cfg
23
+ *.egg
24
+ MANIFEST
25
+
26
+ # Virtual environments
27
+ .venv/
28
+ venv/
29
+ ENV/
30
+ env/
31
+
32
+ # Environment / secrets
33
+ .env
34
+ .env.*
35
+ !.env.example
36
+
37
+ # Test / coverage
38
+ .pytest_cache/
39
+ .coverage
40
+ .coverage.*
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .cache
45
+ nosetests.xml
46
+ coverage.xml
47
+ *.cover
48
+ .hypothesis/
49
+
50
+ # Type checkers / linters
51
+ .mypy_cache/
52
+ .dmypy.json
53
+ .pyre/
54
+ .ruff_cache/
55
+
56
+ # IDE / editor
57
+ .idea/
58
+ .vscode/
59
+ *.swp
60
+ *.swo
61
+ .DS_Store
62
+
63
+ # Project-specific: HAR captures & API probes (may contain tokens, PII, coords)
64
+ *.har
65
+ watchduty*.json
66
+ probe_*.py
67
+
68
+ # Local scratch / private working data (HARs, dumps, etc.)
69
+ .local/
70
+
71
+ # Docs build artifacts
72
+ docs/screenshots/png/
73
+ docs/_build/
74
+
75
+ # Vendor bundle: ship node_modules but ignore caches/logs inside it
76
+ vendor/mapscii/node_modules/.cache/
77
+ vendor/**/node_modules/.cache/
78
+ vendor/**/*.log
79
+ npm-debug.log*
80
+ yarn-debug.log*
81
+ yarn-error.log*
@@ -0,0 +1,223 @@
1
+ Metadata-Version: 2.4
2
+ Name: libwatchduty
3
+ Version: 0.1.0
4
+ Summary: Unofficial Python client for app.watchduty.org fire/incident data
5
+ Author: Max
6
+ License: MIT
7
+ Requires-Python: >=3.9
8
+ Requires-Dist: requests>=2.31
9
+ Requires-Dist: tqdm>=4.65
10
+ Provides-Extra: test
11
+ Requires-Dist: pyte>=0.8; extra == 'test'
12
+ Requires-Dist: pytest>=7; extra == 'test'
13
+ Provides-Extra: tui
14
+ Requires-Dist: pyte>=0.8; extra == 'tui'
15
+ Description-Content-Type: text/markdown
16
+
17
+ # libwatchduty
18
+
19
+ > Unofficial Watch Duty wildfire dashboard — Python client for `api.watchduty.org` plus a threat-ranked terminal UI.
20
+
21
+ Reverse-engineered from the [app.watchduty.org](https://app.watchduty.org) browser app. **No affiliation with Watch Duty.** Read endpoints are public; user-scoped endpoints (saved places, profile) require login.
22
+
23
+ ---
24
+
25
+ ## Screenshot
26
+
27
+ Rendered against a seeded fixture state at 40×160. Full set under [`docs/screenshots/`](docs/screenshots/) (24×100, 40×160, 60×200 — one per detail tab).
28
+
29
+ ```text
30
+ ◉ watchduty │ filters wildfire,location,flooding,hazard │ ⌖ 37.77,-122.42 ≤500km (fixture) │ sort ▼ THREAT │ 4 of 5 │ refresh
31
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
32
+ THREAT D INCIDENT │#104994
33
+ DIST SIZE CONTAINMENT │▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
34
+ ────────────────────────────────────────────────────────────────│ PINE RIDGE FIRE ↗
35
+ ▰▰▰ ↗ #104994 Pine Ridge Fire [active] │ updates radio map evac
36
+ 12.4km 3,400 ac 28% ▰▰▱ │ · 14:02 IC: structure threat lifted east flank
37
+ ▰▰▱ ← #105110 Cedar Hollow Fire [active] │ · 13:41 CalFire: 28% containment, growth slowing
38
+ 61.0km 980 ac 45% ▰▱▱ │ · 12:55 evacuations expanded zone HUM-7B
39
+ ▰▱▱ ↑ #105316 Box Canyon Fire [active] │
40
+ 88.2km 140 ac 80% ▱▱▱ │
41
+ ▱▱▱ · #105410 Mariposa Prescribed Burn [planned] │
42
+ 24.9km 50 ac -- │
43
+ ```
44
+
45
+ > The screenshots are real ANSI dumps captured under `pyte`; if you want the exact escape-sequence colored versions used in the original capture, see [`docs/screenshots/ansi/`](docs/screenshots/ansi/).
46
+
47
+ ---
48
+
49
+ ## Features
50
+
51
+ - **Threat scoring** — composite per-fire score combining proximity, size, containment, growth rate, and wind speed/bearing; visible as a 3-segment `▰▱` bar in the list.
52
+ - **Live updates polling** — background worker thread re-fetches geo events and reports on a configurable interval (`--refresh`), with toast notifications when new reports arrive.
53
+ - **Radio embed** — Broadcastify scanner feeds for the county the selected fire sits in, online feeds grouped first, listener counts inline.
54
+ - **Inline cameras** — wildfire-detection camera stills rendered in-terminal on kitty / ghostty / iTerm2 (Kitty graphics protocol), with size and on/off toggles.
55
+ - **Embedded mapscii** — the Map tab embeds [mapscii](https://github.com/rastapasta/mapscii) inside the right pane via a pyte-backed PTY; full-screen handoff on `m`.
56
+ - **Compact list mode** — toggle between two-line "card" rows and a single-line dense view (`z`).
57
+ - **Threat-ranked sort** — default sort by threat when `--near` is set; cycles through threat / distance / acreage / updated (`t`, reverse with `T`).
58
+ - **Filter + search** — incremental `/`-filter across name/type, `n`/`N` to jump matches, `X` to clear.
59
+ - **Pure-Python deps** — `requests` + `tqdm` for the core; `pyte` only when the inline mapscii embed is wanted.
60
+ - **CLI for scripting** — `watchduty fires`, `event`, `reports`, `bundle`, `radio`, `cameras`, `stills`, `aircraft` — every list subcommand has `--json` for piping.
61
+ - **Auto-locate** — `--near auto` resolves to your approximate latitude/longitude via IP geolocation; otherwise pass `LAT,LNG`.
62
+ - **Camera still capture** — one-shot `stills capture` or a recurring `stills watch` timelapse loop.
63
+
64
+ ---
65
+
66
+ ## Install
67
+
68
+ ```bash
69
+ pip install libwatchduty # CLI + client
70
+ pip install libwatchduty[tui] # inline mapscii embed (pyte)\
71
+ ```
72
+
73
+ Python ≥ 3.9. The `tui` extra only adds [`pyte`](https://pypi.org/project/pyte/) for the embedded map — the dashboard itself runs without it (you get full-screen mapscii via `m` instead).
74
+
75
+ ---
76
+
77
+ ## Quick start
78
+
79
+ > The full walkthrough — install, first launch, keybindings cheat-sheet,
80
+ > `:` commands, scripting against the API — lives in
81
+ > **[`docs/QUICKSTART.md`](docs/QUICKSTART.md)**.
82
+
83
+ ```bash
84
+ pip install libwatchduty[tui]
85
+
86
+ watchduty tui --near auto --within 250 --refresh 60
87
+ watchduty fires --active
88
+ watchduty event 105316
89
+ watchduty reports 105316
90
+ ```
91
+
92
+ Bare `watchduty` (no subcommand) launches the TUI with sensible defaults — `--near auto --within 250 --refresh 60`. Set `WATCHDUTY_HOME=37.77,-122.42` (or `auto`) to skip the flag.
93
+
94
+ Python client:
95
+
96
+ ```python
97
+ from libwatchduty import WatchDutyClient
98
+
99
+ c = WatchDutyClient()
100
+ for ev in c.list_geo_events(types=["wildfire"]):
101
+ if ev["is_active"]:
102
+ print(ev["id"], ev["name"], ev["data"].get("acreage"), "ac")
103
+ ```
104
+
105
+ ---
106
+
107
+ ## TUI keybindings
108
+
109
+ Read off the live source in [`src/libwatchduty/tui.py`](src/libwatchduty/tui.py). Focus-aware bindings depend on whether the **list** (left) or **detail** (right) pane is active.
110
+
111
+ ### Navigation
112
+
113
+ | Key | Action |
114
+ |---|---|
115
+ | `j` / `↓` | Move selection down (list focus) **or** scroll detail one line (detail focus) |
116
+ | `k` / `↑` | Move selection up (list focus) **or** scroll detail up one line (detail focus) |
117
+ | `J` | Scroll detail pane down (always, regardless of focus) |
118
+ | `K` | Scroll detail pane up (always, regardless of focus) |
119
+ | `PgDn` | Scroll detail pane one page down |
120
+ | `PgUp` | Scroll detail pane one page up |
121
+ | `g g` | Jump to first fire (chord) |
122
+ | `G` | Jump to last fire |
123
+ | `Ctrl-D` | Half-page down (selection) |
124
+ | `Ctrl-U` | Half-page up (selection) |
125
+ | `h` | Focus list pane |
126
+ | `l` | Focus detail pane (loads reports for selected fire) |
127
+ | `←` | Previous detail tab; double-tap returns focus to list |
128
+ | `→` | Next detail tab |
129
+ | `Tab` | Cycle focus (list ↔ detail) — within detail, cycles tabs |
130
+ | `Shift-Tab` | Reverse tab cycle within detail |
131
+ | `Enter` | Open selected fire in detail pane |
132
+ | `Esc` / `Backspace` | Return focus to list |
133
+
134
+ ### Detail tabs
135
+
136
+ | Key | Tab |
137
+ |---|---|
138
+ | `1` / `u` | Updates (reports feed) |
139
+ | `2` / `R` | Radio (Broadcastify scanner feeds) |
140
+ | `3` / `c` | Map (embedded mapscii) |
141
+ | `4` / `e` | Evac (evacuation zones) |
142
+
143
+ ### Map & image controls
144
+
145
+ | Key | Action |
146
+ |---|---|
147
+ | `m` | Launch fullscreen mapscii at the selected fire |
148
+ | `+` / `=` | Zoom mapscii in (when map active) **or** bump inline-image size |
149
+ | `-` / `_` | Zoom mapscii out (when map active) **or** shrink inline-image size |
150
+ | `i` / `F` | Open selected fire's header image fullscreen (kitty/ghostty/iTerm2 only) |
151
+ | `p` | Toggle inline header camera image |
152
+
153
+ ### Filters, sort, refresh
154
+
155
+ | Key | Action |
156
+ |---|---|
157
+ | `/` | Open incremental name/type filter |
158
+ | `X` / `Ctrl-L` | Clear filter |
159
+ | `n` | Jump to next match |
160
+ | `N` | Jump to previous match |
161
+ | `:` | Open command prompt |
162
+ | `t` | Cycle sort key (threat → distance → acreage → updated) |
163
+ | `T` | Reverse sort direction |
164
+ | `[` | Shrink `--within` radius by 50 km |
165
+ | `]` | Grow `--within` radius by 50 km |
166
+ | `r` | Force refresh of fires + reports for selected event |
167
+ | `L` | Toggle LIVE mode (faster polling of reports for selected fire) |
168
+ | `z` | Toggle compact list (one line per fire vs. two-line card) |
169
+ | `?` | Help overlay |
170
+ | `q` | Quit |
171
+
172
+ ---
173
+
174
+ ## Threat scoring
175
+
176
+ Each fire gets a composite `[0, 100]` score that drives the default sort and the colored `▰▱` bar. The formula multiplies normalized factors so any near-zero input collapses the score (a 100k-acre fire at 600 km still scores low):
177
+
178
+ > **score = clamp(100 · proximity · (0.4 + 0.6·size) · uncontained · growth · wind · bearing, 0, 100)**
179
+
180
+ where `proximity = 1 − dist/within_km` (clamped to `[0,1]`), `size = log10(1+acres) / log10(1+1000)`, `uncontained = 1 − containment/100`, `growth = 1 + 0.5·growth_rate` (acreage delta over the rolling history window), `wind = 1 + 0.04·wind_mph`, and `bearing` scales `[0.5, 1.5]` based on how directly the wind blows from the fire toward you. Prescribed/planned burns are capped at 5. Tiers: `≥60` red, `≥20` amber, `<6` dim, else green.
181
+
182
+ ---
183
+
184
+ ## mapscii setup
185
+
186
+ The Map tab embeds [mapscii](https://github.com/rastapasta/mapscii) (an ASCII-art world map client). A pinned, working checkout is bundled under [`vendor/mapscii/`](vendor/mapscii/) and ships as wheel data — the TUI prefers `vendor/mapscii/node_modules/.bin/mapscii` over anything in `$PATH`.
187
+
188
+ If the bundled copy isn't usable (e.g. you installed from sdist without Node, or `node_modules` is missing), drop to the fallback installer:
189
+
190
+ ```bash
191
+ watchduty-install-mapscii
192
+ ```
193
+
194
+ This pulls and builds mapscii in a user-writable cache directory. Without mapscii at all, the Map tab degrades gracefully — you can still see the fire's lat/lng and jump to fullscreen rendering (`m`).
195
+
196
+ ---
197
+
198
+ ## Architecture
199
+
200
+ `client.py` owns the typed HTTP surface against `api.watchduty.org` (sessioned `requests`, paginated `iter_*` helpers, optional DRF token auth). The TUI's `run()` spins up a single background **worker thread** that drains a `queue.Queue` of typed request tuples (`REFRESH_FIRES`, `LOAD_REPORTS`, `LOAD_IMAGE`, …) and posts results onto an output queue. The main curses loop owns a `_TuiState` dataclass (fires list, reports cache, threat scores, focus + scroll positions, filter/sort state) — every keypress mutates `_TuiState`, every drained worker result mutates `_TuiState`, and the curses view is a pure render of that state. Result: input stays responsive while API calls run, with no async/asyncio anywhere.
201
+
202
+ ---
203
+
204
+ ## Testing
205
+
206
+ ```bash
207
+ pip install .[test,tui]
208
+ pytest tests/
209
+ ```
210
+
211
+ Tests use `pyte` to render the TUI inside a fake PTY and assert on the resulting frame, plus straight unit tests over `client.py` against canned fixtures.
212
+
213
+ ---
214
+
215
+ ## Contributing
216
+
217
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the development setup, lint/test loop, and how to regenerate screenshots. Release notes live in [CHANGELOG.md](CHANGELOG.md).
218
+
219
+ ---
220
+
221
+ ## License
222
+
223
+ MIT. See [LICENSE](LICENSE) if present; otherwise the `license = { text = "MIT" }` declaration in [`pyproject.toml`](pyproject.toml) is authoritative.
@@ -0,0 +1,207 @@
1
+ # libwatchduty
2
+
3
+ > Unofficial Watch Duty wildfire dashboard — Python client for `api.watchduty.org` plus a threat-ranked terminal UI.
4
+
5
+ Reverse-engineered from the [app.watchduty.org](https://app.watchduty.org) browser app. **No affiliation with Watch Duty.** Read endpoints are public; user-scoped endpoints (saved places, profile) require login.
6
+
7
+ ---
8
+
9
+ ## Screenshot
10
+
11
+ Rendered against a seeded fixture state at 40×160. Full set under [`docs/screenshots/`](docs/screenshots/) (24×100, 40×160, 60×200 — one per detail tab).
12
+
13
+ ```text
14
+ ◉ watchduty │ filters wildfire,location,flooding,hazard │ ⌖ 37.77,-122.42 ≤500km (fixture) │ sort ▼ THREAT │ 4 of 5 │ refresh
15
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
16
+ THREAT D INCIDENT │#104994
17
+ DIST SIZE CONTAINMENT │▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
18
+ ────────────────────────────────────────────────────────────────│ PINE RIDGE FIRE ↗
19
+ ▰▰▰ ↗ #104994 Pine Ridge Fire [active] │ updates radio map evac
20
+ 12.4km 3,400 ac 28% ▰▰▱ │ · 14:02 IC: structure threat lifted east flank
21
+ ▰▰▱ ← #105110 Cedar Hollow Fire [active] │ · 13:41 CalFire: 28% containment, growth slowing
22
+ 61.0km 980 ac 45% ▰▱▱ │ · 12:55 evacuations expanded zone HUM-7B
23
+ ▰▱▱ ↑ #105316 Box Canyon Fire [active] │
24
+ 88.2km 140 ac 80% ▱▱▱ │
25
+ ▱▱▱ · #105410 Mariposa Prescribed Burn [planned] │
26
+ 24.9km 50 ac -- │
27
+ ```
28
+
29
+ > The screenshots are real ANSI dumps captured under `pyte`; if you want the exact escape-sequence colored versions used in the original capture, see [`docs/screenshots/ansi/`](docs/screenshots/ansi/).
30
+
31
+ ---
32
+
33
+ ## Features
34
+
35
+ - **Threat scoring** — composite per-fire score combining proximity, size, containment, growth rate, and wind speed/bearing; visible as a 3-segment `▰▱` bar in the list.
36
+ - **Live updates polling** — background worker thread re-fetches geo events and reports on a configurable interval (`--refresh`), with toast notifications when new reports arrive.
37
+ - **Radio embed** — Broadcastify scanner feeds for the county the selected fire sits in, online feeds grouped first, listener counts inline.
38
+ - **Inline cameras** — wildfire-detection camera stills rendered in-terminal on kitty / ghostty / iTerm2 (Kitty graphics protocol), with size and on/off toggles.
39
+ - **Embedded mapscii** — the Map tab embeds [mapscii](https://github.com/rastapasta/mapscii) inside the right pane via a pyte-backed PTY; full-screen handoff on `m`.
40
+ - **Compact list mode** — toggle between two-line "card" rows and a single-line dense view (`z`).
41
+ - **Threat-ranked sort** — default sort by threat when `--near` is set; cycles through threat / distance / acreage / updated (`t`, reverse with `T`).
42
+ - **Filter + search** — incremental `/`-filter across name/type, `n`/`N` to jump matches, `X` to clear.
43
+ - **Pure-Python deps** — `requests` + `tqdm` for the core; `pyte` only when the inline mapscii embed is wanted.
44
+ - **CLI for scripting** — `watchduty fires`, `event`, `reports`, `bundle`, `radio`, `cameras`, `stills`, `aircraft` — every list subcommand has `--json` for piping.
45
+ - **Auto-locate** — `--near auto` resolves to your approximate latitude/longitude via IP geolocation; otherwise pass `LAT,LNG`.
46
+ - **Camera still capture** — one-shot `stills capture` or a recurring `stills watch` timelapse loop.
47
+
48
+ ---
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ pip install libwatchduty # CLI + client
54
+ pip install libwatchduty[tui] # inline mapscii embed (pyte)\
55
+ ```
56
+
57
+ Python ≥ 3.9. The `tui` extra only adds [`pyte`](https://pypi.org/project/pyte/) for the embedded map — the dashboard itself runs without it (you get full-screen mapscii via `m` instead).
58
+
59
+ ---
60
+
61
+ ## Quick start
62
+
63
+ > The full walkthrough — install, first launch, keybindings cheat-sheet,
64
+ > `:` commands, scripting against the API — lives in
65
+ > **[`docs/QUICKSTART.md`](docs/QUICKSTART.md)**.
66
+
67
+ ```bash
68
+ pip install libwatchduty[tui]
69
+
70
+ watchduty tui --near auto --within 250 --refresh 60
71
+ watchduty fires --active
72
+ watchduty event 105316
73
+ watchduty reports 105316
74
+ ```
75
+
76
+ Bare `watchduty` (no subcommand) launches the TUI with sensible defaults — `--near auto --within 250 --refresh 60`. Set `WATCHDUTY_HOME=37.77,-122.42` (or `auto`) to skip the flag.
77
+
78
+ Python client:
79
+
80
+ ```python
81
+ from libwatchduty import WatchDutyClient
82
+
83
+ c = WatchDutyClient()
84
+ for ev in c.list_geo_events(types=["wildfire"]):
85
+ if ev["is_active"]:
86
+ print(ev["id"], ev["name"], ev["data"].get("acreage"), "ac")
87
+ ```
88
+
89
+ ---
90
+
91
+ ## TUI keybindings
92
+
93
+ Read off the live source in [`src/libwatchduty/tui.py`](src/libwatchduty/tui.py). Focus-aware bindings depend on whether the **list** (left) or **detail** (right) pane is active.
94
+
95
+ ### Navigation
96
+
97
+ | Key | Action |
98
+ |---|---|
99
+ | `j` / `↓` | Move selection down (list focus) **or** scroll detail one line (detail focus) |
100
+ | `k` / `↑` | Move selection up (list focus) **or** scroll detail up one line (detail focus) |
101
+ | `J` | Scroll detail pane down (always, regardless of focus) |
102
+ | `K` | Scroll detail pane up (always, regardless of focus) |
103
+ | `PgDn` | Scroll detail pane one page down |
104
+ | `PgUp` | Scroll detail pane one page up |
105
+ | `g g` | Jump to first fire (chord) |
106
+ | `G` | Jump to last fire |
107
+ | `Ctrl-D` | Half-page down (selection) |
108
+ | `Ctrl-U` | Half-page up (selection) |
109
+ | `h` | Focus list pane |
110
+ | `l` | Focus detail pane (loads reports for selected fire) |
111
+ | `←` | Previous detail tab; double-tap returns focus to list |
112
+ | `→` | Next detail tab |
113
+ | `Tab` | Cycle focus (list ↔ detail) — within detail, cycles tabs |
114
+ | `Shift-Tab` | Reverse tab cycle within detail |
115
+ | `Enter` | Open selected fire in detail pane |
116
+ | `Esc` / `Backspace` | Return focus to list |
117
+
118
+ ### Detail tabs
119
+
120
+ | Key | Tab |
121
+ |---|---|
122
+ | `1` / `u` | Updates (reports feed) |
123
+ | `2` / `R` | Radio (Broadcastify scanner feeds) |
124
+ | `3` / `c` | Map (embedded mapscii) |
125
+ | `4` / `e` | Evac (evacuation zones) |
126
+
127
+ ### Map & image controls
128
+
129
+ | Key | Action |
130
+ |---|---|
131
+ | `m` | Launch fullscreen mapscii at the selected fire |
132
+ | `+` / `=` | Zoom mapscii in (when map active) **or** bump inline-image size |
133
+ | `-` / `_` | Zoom mapscii out (when map active) **or** shrink inline-image size |
134
+ | `i` / `F` | Open selected fire's header image fullscreen (kitty/ghostty/iTerm2 only) |
135
+ | `p` | Toggle inline header camera image |
136
+
137
+ ### Filters, sort, refresh
138
+
139
+ | Key | Action |
140
+ |---|---|
141
+ | `/` | Open incremental name/type filter |
142
+ | `X` / `Ctrl-L` | Clear filter |
143
+ | `n` | Jump to next match |
144
+ | `N` | Jump to previous match |
145
+ | `:` | Open command prompt |
146
+ | `t` | Cycle sort key (threat → distance → acreage → updated) |
147
+ | `T` | Reverse sort direction |
148
+ | `[` | Shrink `--within` radius by 50 km |
149
+ | `]` | Grow `--within` radius by 50 km |
150
+ | `r` | Force refresh of fires + reports for selected event |
151
+ | `L` | Toggle LIVE mode (faster polling of reports for selected fire) |
152
+ | `z` | Toggle compact list (one line per fire vs. two-line card) |
153
+ | `?` | Help overlay |
154
+ | `q` | Quit |
155
+
156
+ ---
157
+
158
+ ## Threat scoring
159
+
160
+ Each fire gets a composite `[0, 100]` score that drives the default sort and the colored `▰▱` bar. The formula multiplies normalized factors so any near-zero input collapses the score (a 100k-acre fire at 600 km still scores low):
161
+
162
+ > **score = clamp(100 · proximity · (0.4 + 0.6·size) · uncontained · growth · wind · bearing, 0, 100)**
163
+
164
+ where `proximity = 1 − dist/within_km` (clamped to `[0,1]`), `size = log10(1+acres) / log10(1+1000)`, `uncontained = 1 − containment/100`, `growth = 1 + 0.5·growth_rate` (acreage delta over the rolling history window), `wind = 1 + 0.04·wind_mph`, and `bearing` scales `[0.5, 1.5]` based on how directly the wind blows from the fire toward you. Prescribed/planned burns are capped at 5. Tiers: `≥60` red, `≥20` amber, `<6` dim, else green.
165
+
166
+ ---
167
+
168
+ ## mapscii setup
169
+
170
+ The Map tab embeds [mapscii](https://github.com/rastapasta/mapscii) (an ASCII-art world map client). A pinned, working checkout is bundled under [`vendor/mapscii/`](vendor/mapscii/) and ships as wheel data — the TUI prefers `vendor/mapscii/node_modules/.bin/mapscii` over anything in `$PATH`.
171
+
172
+ If the bundled copy isn't usable (e.g. you installed from sdist without Node, or `node_modules` is missing), drop to the fallback installer:
173
+
174
+ ```bash
175
+ watchduty-install-mapscii
176
+ ```
177
+
178
+ This pulls and builds mapscii in a user-writable cache directory. Without mapscii at all, the Map tab degrades gracefully — you can still see the fire's lat/lng and jump to fullscreen rendering (`m`).
179
+
180
+ ---
181
+
182
+ ## Architecture
183
+
184
+ `client.py` owns the typed HTTP surface against `api.watchduty.org` (sessioned `requests`, paginated `iter_*` helpers, optional DRF token auth). The TUI's `run()` spins up a single background **worker thread** that drains a `queue.Queue` of typed request tuples (`REFRESH_FIRES`, `LOAD_REPORTS`, `LOAD_IMAGE`, …) and posts results onto an output queue. The main curses loop owns a `_TuiState` dataclass (fires list, reports cache, threat scores, focus + scroll positions, filter/sort state) — every keypress mutates `_TuiState`, every drained worker result mutates `_TuiState`, and the curses view is a pure render of that state. Result: input stays responsive while API calls run, with no async/asyncio anywhere.
185
+
186
+ ---
187
+
188
+ ## Testing
189
+
190
+ ```bash
191
+ pip install .[test,tui]
192
+ pytest tests/
193
+ ```
194
+
195
+ Tests use `pyte` to render the TUI inside a fake PTY and assert on the resulting frame, plus straight unit tests over `client.py` against canned fixtures.
196
+
197
+ ---
198
+
199
+ ## Contributing
200
+
201
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the development setup, lint/test loop, and how to regenerate screenshots. Release notes live in [CHANGELOG.md](CHANGELOG.md).
202
+
203
+ ---
204
+
205
+ ## License
206
+
207
+ MIT. See [LICENSE](LICENSE) if present; otherwise the `license = { text = "MIT" }` declaration in [`pyproject.toml`](pyproject.toml) is authoritative.
@@ -0,0 +1,11 @@
1
+ # TUI screenshots
2
+
3
+ Reproducible screenshots of the `watchduty` TUI rendered in-process against a
4
+ synthetic, seeded `_TuiState` (no live API). Generated by
5
+ `scripts/capture_screenshots.py`, which forks a child under a PTY at each of
6
+ three predefined sizes (24x100, 40x160, 60x200), calls the `_draw_header` /
7
+ `_draw_list` / `_draw_detail` / `_draw_footer` functions once per detail tab
8
+ (updates, radio, map, evac), captures the resulting frame with `pyte`, and
9
+ writes a colored ANSI dump under `ansi/` plus an optional PNG under `png/`
10
+ (needs Pillow; skipped with a warning otherwise). To regenerate, run
11
+ `python -m scripts.capture_screenshots` from the repo root.
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "libwatchduty"
7
+ version = "0.1.0"
8
+ description = "Unofficial Python client for app.watchduty.org fire/incident data"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Max" }]
13
+ dependencies = ["requests>=2.31", "tqdm>=4.65"]
14
+
15
+ [project.optional-dependencies]
16
+ # Pure-Python VT100 emulator used by the TUI to embed mapscii inside the
17
+ # Map-tab rectangle. The dashboard still runs without it (mapscii falls
18
+ # back to fullscreen via `m`); install if you want the inline map.
19
+ tui = ["pyte>=0.8"]
20
+ test = ["pytest>=7", "pyte>=0.8"]
21
+
22
+ [project.scripts]
23
+ watchduty = "libwatchduty.cli:main"
24
+ watchduty-install-mapscii = "libwatchduty.install_mapscii:main"
25
+
26
+ [tool.pytest.ini_options]
27
+ testpaths = ["tests"]
28
+ addopts = "-ra"
29
+
30
+ [tool.hatch.build.targets.wheel]
31
+ packages = ["src/libwatchduty"]
32
+
33
+ # Ship the in-repo mapscii checkout (Node app, ~3 MB) as wheel data so
34
+ # the bundled binary is available after `pip install`. The TUI prefers
35
+ # vendor/mapscii/node_modules/.bin/mapscii before falling back to $PATH.
36
+ [tool.hatch.build.targets.wheel.shared-data]
37
+ "vendor/mapscii" = "share/libwatchduty/vendor/mapscii"
38
+
39
+ [tool.hatch.build.targets.sdist]
40
+ include = [
41
+ "src",
42
+ "vendor",
43
+ "README.md",
44
+ "pyproject.toml",
45
+ ]
@@ -0,0 +1,9 @@
1
+ """Watch Duty API client library.
2
+
3
+ Exports WatchDutyClient (HTTP client) and WatchDutyError (raised on non-2xx responses).
4
+ """
5
+
6
+ from .client import WatchDutyClient, WatchDutyError
7
+
8
+ __all__ = ["WatchDutyClient", "WatchDutyError"]
9
+ __version__ = "0.1.0"
@@ -0,0 +1,5 @@
1
+ """Entry point for `python -m libwatchduty` — dispatches to the watchduty CLI."""
2
+ from .cli import main
3
+ import sys
4
+
5
+ sys.exit(main())