flickr.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. """
  2. Flickr Tag
  3. ----------
  4. This implements a Liquid-style flickr tag for Pelican.
  5. IMPORTANT: You have to create a API key to access the flickr api.
  6. You can do this `here <https://www.flickr.com/services/apps/create/apply>`_.
  7. Add the created key to your config under FLICKR_API_KEY.
  8. Syntax
  9. ------
  10. {% flickr image_id [small|medium|large] ["alt text"|'alt text'] %}
  11. Example
  12. --------
  13. {% flickr 18841055371 large "Fichte"}
  14. Output
  15. ------
  16. <a href="https://www.flickr.com/photos/marvinxsteadfast/18841055371/"><img src="https://farm6.staticflickr.com/5552/18841055371_17ac287217_b.jpg" alt="Fichte"></a>
  17. """
  18. import json
  19. import re
  20. try:
  21. from urllib.request import urlopen
  22. from urllib.parse import urlencode
  23. except ImportError:
  24. from urllib import urlopen, urlencode
  25. from .mdx_liquid_tags import LiquidTags
  26. SYNTAX = '''{% flickr image_id [small|medium|large] ["alt text"|'alt text'] %}'''
  27. PARSE_SYNTAX = re.compile(('''(?P<photo_id>\S+)'''
  28. '''(?:\s+(?P<size>large|medium|small))?'''
  29. '''(?:\s+(['"]{0,1})(?P<alt>.+)(\\3))?'''))
  30. def get_info(photo_id, api_key):
  31. ''' Get photo informations from flickr api. '''
  32. query = urlencode({
  33. 'method': 'flickr.photos.getInfo',
  34. 'api_key': api_key,
  35. 'photo_id': photo_id,
  36. 'format': 'json',
  37. 'nojsoncallback': '1'
  38. })
  39. r = urlopen('https://api.flickr.com/services/rest/?' + query)
  40. info = json.loads(r.read().decode('utf-8'))
  41. if info['stat'] == 'fail':
  42. raise ValueError(info['message'])
  43. return info
  44. def source_url(farm, server, id, secret, size):
  45. ''' Url for direct jpg use. '''
  46. if size == 'small':
  47. img_size = 'n'
  48. elif size == 'medium':
  49. img_size = 'c'
  50. elif size == 'large':
  51. img_size = 'b'
  52. return 'https://farm{}.staticflickr.com/{}/{}_{}_{}.jpg'.format(
  53. farm, server, id, secret, img_size)
  54. def generate_html(attrs, api_key):
  55. ''' Returns html code. '''
  56. # getting flickr api data
  57. flickr_data = get_info(attrs['photo_id'], api_key)
  58. # if size is not defined it will use large as image size
  59. if 'size' not in attrs.keys():
  60. attrs['size'] = 'large'
  61. # if no alt is defined it will use the flickr image title
  62. if 'alt' not in attrs.keys():
  63. attrs['alt'] = flickr_data['photo']['title']['_content']
  64. # return final html code
  65. return '<a href="{}"><img src="{}" alt="{}"></a>'.format(
  66. flickr_data['photo']['urls']['url'][0]['_content'],
  67. source_url(flickr_data['photo']['farm'],
  68. flickr_data['photo']['server'],
  69. attrs['photo_id'],
  70. flickr_data['photo']['secret'],
  71. attrs['size']),
  72. attrs['alt'])
  73. @LiquidTags.register('flickr')
  74. def flickr(preprocessor, tag, markup):
  75. # getting flickr api key out of config
  76. api_key = preprocessor.configs.getConfig('FLICKR_API_KEY')
  77. # parse markup and extract data
  78. attrs = None
  79. match = PARSE_SYNTAX.search(markup)
  80. if match:
  81. attrs = dict(
  82. [(key, value.strip())
  83. for (key, value) in match.groupdict().items() if value])
  84. else:
  85. raise ValueError('Error processing input. '
  86. 'Expected syntax: {}'.format(SYNTAX))
  87. return generate_html(attrs, api_key)
  88. # ---------------------------------------------------
  89. # This import allows image tag to be a Pelican plugin
  90. from liquid_tags import register