Package zinnia :: Package xmlrpc :: Module pingback
[hide private]

Source Code for Module zinnia.xmlrpc.pingback

  1  """XML-RPC methods of Zinnia Pingback""" 
  2  from urllib2 import urlopen 
  3  from urllib2 import URLError 
  4  from urllib2 import HTTPError 
  5  from urlparse import urlsplit 
  6   
  7  from django.utils.html import strip_tags 
  8  from django.contrib.sites.models import Site 
  9  from django.core.urlresolvers import Resolver404 
 10  from django.core.urlresolvers import get_resolver 
 11  from django.contrib.comments.models import Comment 
 12  from django.utils.translation import ugettext as _ 
 13  from django.contrib.contenttypes.models import ContentType 
 14   
 15  from zinnia.models import Entry 
 16  from zinnia.settings import PINGBACK_CONTENT_LENGTH 
 17  from BeautifulSoup import BeautifulSoup 
 18  from django_xmlrpc.decorators import xmlrpc_func 
 19   
 20  UNDEFINED_ERROR = 0 
 21  SOURCE_DOES_NOT_EXIST = 16 
 22  SOURCE_DOES_NOT_LINK = 17 
 23  TARGET_DOES_NOT_EXIST = 32 
 24  TARGET_IS_NOT_PINGABLE = 33 
 25  PINGBACK_ALREADY_REGISTERED = 48 
26 27 28 -def generate_pingback_content(soup, target, max_length, trunc_char='...'):
29 """Generate a description text for the pingback""" 30 link = soup.find('a', href=target) 31 32 content = strip_tags(unicode(link.findParent())) 33 index = content.index(link.string) 34 35 if len(content) > max_length: 36 middle = max_length / 2 37 start = index - middle 38 end = index + middle 39 40 if start <= 0: 41 end -= start 42 extract = content[0:end] 43 else: 44 extract = '%s%s' % (trunc_char, content[start:end]) 45 46 if end < len(content): 47 extract += trunc_char 48 return extract 49 50 return content
51
52 53 @xmlrpc_func(returns='string', args=['string', 'string']) 54 -def pingback_ping(source, target):
55 """pingback.ping(sourceURI, targetURI) => 'Pingback message' 56 57 Notifies the server that a link has been added to sourceURI, pointing to targetURI. 58 59 See: http://hixie.ch/specs/pingback/pingback-1.0""" 60 try: 61 if source == target: 62 return UNDEFINED_ERROR 63 64 site = Site.objects.get_current() 65 try: 66 document = ''.join(urlopen(source).readlines()) 67 except (HTTPError, URLError): 68 return SOURCE_DOES_NOT_EXIST 69 70 if not target in document: 71 return SOURCE_DOES_NOT_LINK 72 73 scheme, netloc, path, query, fragment = urlsplit(target) 74 if netloc != site.domain: 75 return TARGET_DOES_NOT_EXIST 76 77 resolver = get_resolver(None) 78 try: 79 resolver.resolve(path) 80 except Resolver404: 81 return TARGET_DOES_NOT_EXIST 82 83 try: 84 entry_slug = [bit for bit in path.split('/') if bit][-1] 85 entry = Entry.published.get(slug=entry_slug) 86 if not entry.pingback_enabled: 87 return TARGET_IS_NOT_PINGABLE 88 except (Entry.DoesNotExist, IndexError): 89 return TARGET_IS_NOT_PINGABLE 90 91 soup = BeautifulSoup(document) 92 title = soup.find('title') 93 title = title and strip_tags(title) or _('No title') 94 description = generate_pingback_content(soup, target, 95 PINGBACK_CONTENT_LENGTH) 96 97 comment, created = Comment.objects.get_or_create( 98 content_type=ContentType.objects.get_for_model(Entry), 99 object_pk=entry.pk, user_url=source, site=site, 100 defaults={'comment': description, 'user_name': title}) 101 if created: 102 user = entry.authors.all()[0] 103 comment.flags.create(user=user, flag='pingback') 104 return 'Pingback from %s to %s registered.' % (source, target) 105 return PINGBACK_ALREADY_REGISTERED 106 except: 107 return UNDEFINED_ERROR
108
109 110 @xmlrpc_func(returns='string[]', args=['string']) 111 -def pingback_extensions_get_pingbacks(target):
112 """pingback.extensions.getPingbacks(url) => '[url, url, ...]' 113 114 Returns an array of URLs that link to the specified url. 115 116 See: http://www.aquarionics.com/misc/archives/blogite/0198.html""" 117 site = Site.objects.get_current() 118 119 scheme, netloc, path, query, fragment = urlsplit(target) 120 if netloc != site.domain: 121 return TARGET_DOES_NOT_EXIST 122 123 resolver = get_resolver(None) 124 try: 125 resolver.resolve(path) 126 except Resolver404: 127 return TARGET_DOES_NOT_EXIST 128 129 try: 130 entry_slug = [bit for bit in path.split('/') if bit][-1] 131 entry = Entry.published.get(slug=entry_slug) 132 except (Entry.DoesNotExist, IndexError): 133 return TARGET_IS_NOT_PINGABLE 134 135 return [pingback.user_url for pingback in entry.pingbacks]
136