climate 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #!/usr/bin/env python2
  2. #
  3. # Displays the current radar from weather underground in your CLI
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. from __future__ import print_function
  18. import ConfigParser
  19. import glob
  20. import os
  21. import subprocess
  22. import sys
  23. import tempfile
  24. import time
  25. from distutils import spawn
  26. from urllib2 import urlopen
  27. BASE_URL = 'http://api.wunderground.com/api/'
  28. gif_image = ''
  29. def get_config():
  30. config_file = os.path.join(os.environ['HOME'], '.config', 'climate.conf')
  31. if not os.path.isfile(config_file):
  32. print('[ERROR] NO CONFIG FILE at: %s' % config_file)
  33. sys.exit(1)
  34. cfg = {}
  35. config = ConfigParser.SafeConfigParser()
  36. config.read(config_file)
  37. for k, v in config.items('general'):
  38. cfg[k] = v
  39. return cfg
  40. def rgb_to_tput(rgb):
  41. # Math taken from console_colors.md
  42. # Copyright: heptal
  43. # <https://gist.github.com/heptal/6052573>
  44. return sum(p*q for p, q in zip([36, 6, 1], [int(min(int(c), 254)/42.5)
  45. for c in rgb.split(',')]))+16
  46. def esc(*args):
  47. return '\x1b[%sm' % ';'.join(str(arg) for arg in args)
  48. def get_convert():
  49. convert = spawn.find_executable('gm')
  50. if convert:
  51. convert = [convert, 'convert']
  52. else:
  53. convert = [spawn.find_executable('convert')]
  54. if not convert:
  55. print('[ERROR] ImageMagick or GraphicsMagick must be installed')
  56. cleanup()
  57. sys.exit(1)
  58. return convert
  59. def show_image(image):
  60. output = subprocess.check_output(get_convert() + [image, 'txt:-'])
  61. all = []
  62. for line in output.splitlines():
  63. if line.startswith('#'):
  64. continue
  65. outlines = line.split(':')
  66. coordinates = outlines[0]
  67. rgb = outlines[1].split(')')[0].strip()[1:]
  68. buf = '\x1b[7m'
  69. if coordinates.startswith('0'):
  70. buf += '\n'
  71. color = rgb_to_tput(rgb)
  72. buf += '{} '.format(esc(38, 5, color))
  73. all.append(buf)
  74. sys.stdout.write('\x1b[H\x1b[J\x1b[?25l\x1b[30m')
  75. sys.stdout.write(''.join(all))
  76. def split_gif(gif):
  77. fn = os.path.basename(gif)
  78. dn = os.path.dirname(gif)
  79. subprocess.check_call(get_convert() + ['-coalesce', '+adjoin', gif,
  80. os.path.join(dn, '{}%05d-climate.jpg'.format(fn))])
  81. while True:
  82. for image in glob.glob(os.path.join(dn, '*-climate.jpg')):
  83. show_image(image)
  84. time.sleep(0.5)
  85. def grab_gif(cfg):
  86. global gif_image
  87. cols = subprocess.check_output(['tput', 'cols']).strip()
  88. lines = subprocess.check_output(['tput', 'lines']).strip()
  89. url = [BASE_URL,
  90. cfg['api_key'],
  91. '/animatedradar/image.gif?',
  92. 'centerlat={}&'.format(cfg.get('latitude')),
  93. 'centerlon={}&'.format(cfg.get('longitude')),
  94. 'radius={}&'.format(cfg.get('radius', 100)),
  95. 'width={}&'.format(cols),
  96. 'height={}&'.format(lines),
  97. 'newmaps=1&',
  98. 'rainsnow=1&',
  99. 'timelabel=1&',
  100. 'timelabel.x=1&',
  101. 'timelabel.y=10&',
  102. 'reproj.automerc=1&',
  103. 'num=8']
  104. img = urlopen(''.join(url))
  105. radar_gif = tempfile.NamedTemporaryFile(delete=False)
  106. with open(radar_gif.name, 'w') as f:
  107. f.write(img.read())
  108. gif_image = radar_gif.name
  109. return radar_gif.name
  110. def cleanup():
  111. global gif_image
  112. if os.path.isfile(gif_image):
  113. dn = os.path.dirname(gif_image)
  114. for image in glob.glob(os.path.join(dn, '*-climate.jpg')):
  115. os.remove(image)
  116. os.remove(gif_image)
  117. gif_image = ''
  118. sys.stdout.write('\x1b[34h\x1b[?25h\x1b[0m\x1b[H\x1b[J')
  119. def main():
  120. cfg = get_config()
  121. try:
  122. split_gif(grab_gif(cfg))
  123. except KeyboardInterrupt:
  124. cleanup()
  125. sys.exit(130)
  126. if __name__ == '__main__':
  127. main()