Advertisement
jcomeau_ictx

moonphase cron job for Facebook page The Moon

Oct 11th, 2015
186
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2. '''
  3. create webpage of moonphase
  4.  
  5. update Facebook "The Moon" page when it's a major phase
  6. '''
  7. import sys, os, math, ephem, netrc, urllib, urllib2, logging, httplib
  8. from datetime import datetime
  9. logging.basicConfig(level = logging.DEBUG)
  10. IMAGE_PATTERN = 'moons/m%03d.gif'  # relative to images/
  11. FACEBOOK = 'graph.facebook.com'
  12. NETRC = netrc.netrc()
  13. THE_MOON_ID, APP, KEY = NETRC.authenticators(FACEBOOK)
  14. MOONPAGE = 'http://unixshell.jcomeau.com/luna/index.html'
  15. DOCUMENT_ROOT = os.getenv('DOCUMENT_ROOT', '/var/www/jcomeau/luna')
  16. GRAPH = 'https://%s' % FACEBOOK
  17. TIMESTAMP = datetime.utcnow()
  18. MESSAGE = {
  19.     0: 'Beginning a new cycle!',
  20.     90: 'First quarter happening now!',
  21.     180: 'Full moon happening now!',
  22.     270: 'Last quarter happening now!',
  23. }
  24.  
  25. def update_image():
  26.     '''
  27.    update symlink images/phase.gif
  28.  
  29.    use trig function guessed at by observing how new and full moons seem
  30.    to last several days, whereas first and last quarter zoom by quickly
  31.    '''
  32.     os.chdir(DOCUMENT_ROOT)
  33.     utcnow = ephem.Date(TIMESTAMP)
  34.     last_new_moon = ephem.previous_new_moon(utcnow)
  35.     next_new_moon = ephem.next_new_moon(utcnow)
  36.     lunar_cycle = next_new_moon - last_new_moon
  37.     full_moon_offset = lunar_cycle / 2
  38.     current_phase = utcnow - last_new_moon
  39.     if current_phase >= full_moon_offset:
  40.         degrees, image = image_url((math.cos(
  41.             (current_phase / lunar_cycle) * 2 * math.pi) + 3) * 90)
  42.     else:
  43.         degrees, image = image_url((-math.cos(
  44.             (current_phase / lunar_cycle) * 2 * math.pi) + 1) * 90)
  45.     try:
  46.         old_image = os.readlink('images/phase.gif')
  47.     except OSError:
  48.         old_image = ''
  49.     if old_image != image:
  50.         try:
  51.             os.unlink('images/phase.gif')
  52.         except OSError:
  53.             pass
  54.         os.symlink(image, 'images/phase.gif')
  55.     if degrees in [0, 90, 180, 270, 360]:
  56.         update_facebook_page(degrees, text = MESSAGE(degrees % 360))
  57.  
  58. def init_https():
  59.     '''
  60.    enable debugging of HTTPS connection if run from command-line
  61.    '''
  62.     handler = urllib2.HTTPSHandler(debuglevel = sys.stdin.isatty())
  63.     opener = urllib2.build_opener(handler)
  64.     urllib2.install_opener(opener)
  65.  
  66. def update_facebook_page(degrees, link = MOONPAGE, text = 'My current phase'):
  67.     '''
  68.    make a POST to The Moon page
  69.  
  70.    notifying followers of major phase
  71.    '''
  72.     init_https()
  73.     arguments = {
  74.         'link': '%s?cachebreaker=%s' % (link, TIMESTAMP),
  75.         'message': text,
  76.         'access_token': KEY,
  77.     }
  78.     if not text:
  79.         arguments.pop('message')
  80.     logging.debug('notifying followers of %d phase' % degrees)
  81.     response = urllib2.urlopen('%s/%s/feed' % (GRAPH, THE_MOON_ID),
  82.         urllib.urlencode(arguments))
  83.     page = response.read()
  84.     logging.debug(page)
  85.  
  86. def image_url(number):
  87.     '''
  88.    images are only in multiples of 2 degrees, such as moons/m002.gif,
  89.    moons/m356.gif, so round accordingly and construct relative URL
  90.    '''
  91.     rounded = int((number / 2) + .5) * 2
  92.     return rounded, IMAGE_PATTERN % rounded
  93.  
  94. if __name__ == '__main__':
  95.     update_image()
Advertisement
RAW Paste Data Copied
Advertisement