From b2c9a785470c463fb64e078df5e04e9a82ecc070 Mon Sep 17 00:00:00 2001 From: Wojciech Polak Date: Thu, 9 Jan 2014 19:58:09 +0100 Subject: Change project's folder layout. --- .gitignore | 7 +- TODO | 5 - __init__.py | 0 apis/__init__.py | 53 -- apis/delicious.py | 31 -- apis/digg.py | 28 - apis/fb.py | 150 ----- apis/flickr.py | 105 ---- apis/friendfeed.py | 157 ------ apis/greader.py | 31 -- apis/identica.py | 43 -- apis/lastfm.py | 40 -- apis/mail.py | 111 ---- apis/picasaweb.py | 34 -- apis/selfposts.py | 240 -------- apis/stumbleupon.py | 31 -- apis/twitter.py | 153 ------ apis/vimeo.py | 184 ------- apis/webfeed.py | 181 ------ apis/yelp.py | 41 -- apis/youtube.py | 67 --- bookmarklet/__init__.py | 0 bookmarklet/templates/bookmarklet.js | 397 -------------- bookmarklet/templates/frame.html | 319 ----------- bookmarklet/urls.py | 23 - bookmarklet/views.py | 52 -- filters/__init__.py | 20 - filters/expand.py | 301 ---------- filters/truncate.py | 37 -- filters/twyntax.py | 47 -- gauth/__init__.py | 0 gauth/admin.py | 24 - gauth/forms.py | 32 -- gauth/gls_oauth.py | 149 ----- gauth/gls_openid.py | 87 --- gauth/models.py | 60 -- gauth/templates/login.html | 37 -- gauth/templates/openid.html | 32 -- gauth/urls.py | 24 - gauth/views.py | 230 -------- glifestream/__init__.py | 0 glifestream/apis/__init__.py | 53 ++ glifestream/apis/delicious.py | 31 ++ glifestream/apis/digg.py | 28 + glifestream/apis/fb.py | 150 +++++ glifestream/apis/flickr.py | 105 ++++ glifestream/apis/friendfeed.py | 157 ++++++ glifestream/apis/greader.py | 31 ++ glifestream/apis/identica.py | 43 ++ glifestream/apis/lastfm.py | 40 ++ glifestream/apis/mail.py | 111 ++++ glifestream/apis/picasaweb.py | 34 ++ glifestream/apis/selfposts.py | 240 ++++++++ glifestream/apis/stumbleupon.py | 31 ++ glifestream/apis/twitter.py | 153 ++++++ glifestream/apis/vimeo.py | 184 +++++++ glifestream/apis/webfeed.py | 181 ++++++ glifestream/apis/yelp.py | 41 ++ glifestream/apis/youtube.py | 67 +++ glifestream/bookmarklet/__init__.py | 0 glifestream/bookmarklet/templates/bookmarklet.js | 397 ++++++++++++++ glifestream/bookmarklet/templates/frame.html | 319 +++++++++++ glifestream/bookmarklet/urls.py | 23 + glifestream/bookmarklet/views.py | 52 ++ glifestream/filters/__init__.py | 20 + glifestream/filters/expand.py | 301 ++++++++++ glifestream/filters/truncate.py | 37 ++ glifestream/filters/twyntax.py | 47 ++ glifestream/gauth/__init__.py | 0 glifestream/gauth/admin.py | 24 + glifestream/gauth/forms.py | 32 ++ glifestream/gauth/gls_oauth.py | 149 +++++ glifestream/gauth/gls_openid.py | 87 +++ glifestream/gauth/models.py | 60 ++ glifestream/gauth/templates/login.html | 37 ++ glifestream/gauth/templates/openid.html | 32 ++ glifestream/gauth/urls.py | 24 + glifestream/gauth/views.py | 230 ++++++++ glifestream/settings-sample.py | 191 +++++++ glifestream/stream/__init__.py | 19 + glifestream/stream/admin.py | 109 ++++ glifestream/stream/fixtures/initial_data.json | 38 ++ glifestream/stream/media.py | 197 +++++++ glifestream/stream/models.py | 191 +++++++ glifestream/stream/pshb.py | 223 ++++++++ glifestream/stream/templatetags/__init__.py | 0 glifestream/stream/templatetags/gls_filters.py | 164 ++++++ glifestream/stream/templatetags/media.py | 68 +++ glifestream/stream/views.py | 616 +++++++++++++++++++++ glifestream/templates/404.html | 5 + glifestream/templates/500.html | 5 + glifestream/templates/base.html | 74 +++ glifestream/templates/i18n.html | 17 + glifestream/templates/stream-pure.html | 56 ++ glifestream/templates/stream.atom | 45 ++ glifestream/templates/stream.html | 129 +++++ glifestream/templates/stream.json | 29 + glifestream/urls.py | 75 +++ glifestream/usettings/__init__.py | 0 glifestream/usettings/templates/lists.html | 30 + glifestream/usettings/templates/oauth.html | 81 +++ glifestream/usettings/templates/oid.html | 27 + glifestream/usettings/templates/opml.xml | 11 + glifestream/usettings/templates/pshb.html | 43 ++ glifestream/usettings/templates/services.html | 52 ++ glifestream/usettings/templates/settings.html | 15 + glifestream/usettings/templates/tools.html | 7 + glifestream/usettings/urls.py | 35 ++ glifestream/usettings/views.py | 664 +++++++++++++++++++++++ glifestream/utils/__init__.py | 22 + glifestream/utils/common.py | 23 + glifestream/utils/html.py | 46 ++ glifestream/utils/httpclient.py | 168 ++++++ glifestream/utils/oembed.py | 44 ++ glifestream/utils/slugify.py | 37 ++ glifestream/utils/time.py | 62 +++ glifestream/wsgi.py | 24 + manage.py | 17 +- settings-sample.py | 180 ------ stream/__init__.py | 19 - stream/admin.py | 109 ---- stream/fixtures/initial_data.json | 38 -- stream/media.py | 197 ------- stream/models.py | 191 ------- stream/pshb.py | 223 -------- stream/templatetags/__init__.py | 0 stream/templatetags/gls_filters.py | 164 ------ stream/templatetags/media.py | 68 --- stream/views.py | 616 --------------------- templates/404.html | 5 - templates/500.html | 5 - templates/base.html | 74 --- templates/i18n.html | 17 - templates/stream-pure.html | 56 -- templates/stream.atom | 45 -- templates/stream.html | 129 ----- templates/stream.json | 29 - urls.py | 75 --- usettings/__init__.py | 0 usettings/templates/lists.html | 30 - usettings/templates/oauth.html | 81 --- usettings/templates/oid.html | 27 - usettings/templates/opml.xml | 11 - usettings/templates/pshb.html | 43 -- usettings/templates/services.html | 52 -- usettings/templates/settings.html | 15 - usettings/templates/tools.html | 7 - usettings/urls.py | 35 -- usettings/views.py | 664 ----------------------- utils/__init__.py | 22 - utils/common.py | 23 - utils/html.py | 46 -- utils/httpclient.py | 168 ------ utils/oembed.py | 44 -- utils/slugify.py | 37 -- utils/time.py | 62 --- worker.py | 9 +- wsgi.py | 24 - 158 files changed, 7208 insertions(+), 7205 deletions(-) delete mode 100644 TODO delete mode 100644 __init__.py delete mode 100644 apis/__init__.py delete mode 100644 apis/delicious.py delete mode 100644 apis/digg.py delete mode 100644 apis/fb.py delete mode 100644 apis/flickr.py delete mode 100644 apis/friendfeed.py delete mode 100644 apis/greader.py delete mode 100644 apis/identica.py delete mode 100644 apis/lastfm.py delete mode 100644 apis/mail.py delete mode 100644 apis/picasaweb.py delete mode 100644 apis/selfposts.py delete mode 100644 apis/stumbleupon.py delete mode 100644 apis/twitter.py delete mode 100644 apis/vimeo.py delete mode 100644 apis/webfeed.py delete mode 100644 apis/yelp.py delete mode 100644 apis/youtube.py delete mode 100644 bookmarklet/__init__.py delete mode 100644 bookmarklet/templates/bookmarklet.js delete mode 100644 bookmarklet/templates/frame.html delete mode 100644 bookmarklet/urls.py delete mode 100644 bookmarklet/views.py delete mode 100644 filters/__init__.py delete mode 100644 filters/expand.py delete mode 100644 filters/truncate.py delete mode 100644 filters/twyntax.py delete mode 100644 gauth/__init__.py delete mode 100644 gauth/admin.py delete mode 100644 gauth/forms.py delete mode 100644 gauth/gls_oauth.py delete mode 100644 gauth/gls_openid.py delete mode 100644 gauth/models.py delete mode 100644 gauth/templates/login.html delete mode 100644 gauth/templates/openid.html delete mode 100644 gauth/urls.py delete mode 100644 gauth/views.py create mode 100644 glifestream/__init__.py create mode 100644 glifestream/apis/__init__.py create mode 100644 glifestream/apis/delicious.py create mode 100644 glifestream/apis/digg.py create mode 100644 glifestream/apis/fb.py create mode 100644 glifestream/apis/flickr.py create mode 100644 glifestream/apis/friendfeed.py create mode 100644 glifestream/apis/greader.py create mode 100644 glifestream/apis/identica.py create mode 100644 glifestream/apis/lastfm.py create mode 100644 glifestream/apis/mail.py create mode 100644 glifestream/apis/picasaweb.py create mode 100644 glifestream/apis/selfposts.py create mode 100644 glifestream/apis/stumbleupon.py create mode 100644 glifestream/apis/twitter.py create mode 100644 glifestream/apis/vimeo.py create mode 100644 glifestream/apis/webfeed.py create mode 100644 glifestream/apis/yelp.py create mode 100644 glifestream/apis/youtube.py create mode 100644 glifestream/bookmarklet/__init__.py create mode 100644 glifestream/bookmarklet/templates/bookmarklet.js create mode 100644 glifestream/bookmarklet/templates/frame.html create mode 100644 glifestream/bookmarklet/urls.py create mode 100644 glifestream/bookmarklet/views.py create mode 100644 glifestream/filters/__init__.py create mode 100644 glifestream/filters/expand.py create mode 100644 glifestream/filters/truncate.py create mode 100644 glifestream/filters/twyntax.py create mode 100644 glifestream/gauth/__init__.py create mode 100644 glifestream/gauth/admin.py create mode 100644 glifestream/gauth/forms.py create mode 100644 glifestream/gauth/gls_oauth.py create mode 100644 glifestream/gauth/gls_openid.py create mode 100644 glifestream/gauth/models.py create mode 100644 glifestream/gauth/templates/login.html create mode 100644 glifestream/gauth/templates/openid.html create mode 100644 glifestream/gauth/urls.py create mode 100644 glifestream/gauth/views.py create mode 100644 glifestream/settings-sample.py create mode 100644 glifestream/stream/__init__.py create mode 100644 glifestream/stream/admin.py create mode 100644 glifestream/stream/fixtures/initial_data.json create mode 100644 glifestream/stream/media.py create mode 100644 glifestream/stream/models.py create mode 100644 glifestream/stream/pshb.py create mode 100644 glifestream/stream/templatetags/__init__.py create mode 100644 glifestream/stream/templatetags/gls_filters.py create mode 100644 glifestream/stream/templatetags/media.py create mode 100644 glifestream/stream/views.py create mode 100644 glifestream/templates/404.html create mode 100644 glifestream/templates/500.html create mode 100644 glifestream/templates/base.html create mode 100644 glifestream/templates/i18n.html create mode 100644 glifestream/templates/stream-pure.html create mode 100644 glifestream/templates/stream.atom create mode 100644 glifestream/templates/stream.html create mode 100644 glifestream/templates/stream.json create mode 100644 glifestream/urls.py create mode 100644 glifestream/usettings/__init__.py create mode 100644 glifestream/usettings/templates/lists.html create mode 100644 glifestream/usettings/templates/oauth.html create mode 100644 glifestream/usettings/templates/oid.html create mode 100644 glifestream/usettings/templates/opml.xml create mode 100644 glifestream/usettings/templates/pshb.html create mode 100644 glifestream/usettings/templates/services.html create mode 100644 glifestream/usettings/templates/settings.html create mode 100644 glifestream/usettings/templates/tools.html create mode 100644 glifestream/usettings/urls.py create mode 100644 glifestream/usettings/views.py create mode 100644 glifestream/utils/__init__.py create mode 100644 glifestream/utils/common.py create mode 100644 glifestream/utils/html.py create mode 100644 glifestream/utils/httpclient.py create mode 100644 glifestream/utils/oembed.py create mode 100644 glifestream/utils/slugify.py create mode 100644 glifestream/utils/time.py create mode 100644 glifestream/wsgi.py delete mode 100644 settings-sample.py delete mode 100644 stream/__init__.py delete mode 100644 stream/admin.py delete mode 100644 stream/fixtures/initial_data.json delete mode 100644 stream/media.py delete mode 100644 stream/models.py delete mode 100644 stream/pshb.py delete mode 100644 stream/templatetags/__init__.py delete mode 100644 stream/templatetags/gls_filters.py delete mode 100644 stream/templatetags/media.py delete mode 100644 stream/views.py delete mode 100644 templates/404.html delete mode 100644 templates/500.html delete mode 100644 templates/base.html delete mode 100644 templates/i18n.html delete mode 100644 templates/stream-pure.html delete mode 100644 templates/stream.atom delete mode 100644 templates/stream.html delete mode 100644 templates/stream.json delete mode 100644 urls.py delete mode 100644 usettings/__init__.py delete mode 100644 usettings/templates/lists.html delete mode 100644 usettings/templates/oauth.html delete mode 100644 usettings/templates/oid.html delete mode 100644 usettings/templates/opml.xml delete mode 100644 usettings/templates/pshb.html delete mode 100644 usettings/templates/services.html delete mode 100644 usettings/templates/settings.html delete mode 100644 usettings/templates/tools.html delete mode 100644 usettings/urls.py delete mode 100644 usettings/views.py delete mode 100644 utils/__init__.py delete mode 100644 utils/common.py delete mode 100644 utils/html.py delete mode 100644 utils/httpclient.py delete mode 100644 utils/oembed.py delete mode 100644 utils/slugify.py delete mode 100644 utils/time.py delete mode 100644 wsgi.py diff --git a/.gitignore b/.gitignore index 7359720..55b794e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ +*~ *.pyc *.pyo *.mo -*~ +bin/ +include/ +lib/ settings.py static/thumbs static/upload -templates/user-* +glifestream/templates/user-* diff --git a/TODO b/TODO deleted file mode 100644 index ef193b1..0000000 --- a/TODO +++ /dev/null @@ -1,5 +0,0 @@ -TO DO: - -* Comments (internal, Salmon Protocol). - -Help us by contributing new solutions and code! diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/apis/__init__.py b/apis/__init__.py deleted file mode 100644 index 9f97186..0000000 --- a/apis/__init__.py +++ /dev/null @@ -1,53 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010, 2011 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -__all__ = ( - 'delicious', - 'digg', - 'fb', - 'flickr', - 'friendfeed', - 'greader', - 'identica', - 'lastfm', - 'mail', - 'picasaweb', - 'selfposts', - 'stumbleupon', - 'twitter', - 'vimeo', - 'webfeed', - 'yelp', - 'youtube', -) - -API_LIST = ( - ('selfposts', 'Self Posts'), - ('webfeed', 'Webfeed'), - ('twitter', 'Twitter'), - ('fb', 'Facebook'), - ('friendfeed', 'FriendFeed'), - ('identica', 'Identi.ca'), - ('greader', 'Google Reader'), - ('youtube', 'YouTube'), - ('vimeo', 'Vimeo'), - ('delicious', 'Delicious'), - ('digg', 'Digg'), - ('stumbleupon', 'StumbleUpon'), - ('flickr', 'Flickr'), - ('picasaweb', 'Picasa Web'), - ('lastfm', 'Last.fm'), - ('yelp', 'Yelp'), -) diff --git a/apis/delicious.py b/apis/delicious.py deleted file mode 100644 index 3fc98c3..0000000 --- a/apis/delicious.py +++ /dev/null @@ -1,31 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -from django.utils.translation import ugettext as _ -import webfeed - - -class API (webfeed.API): - name = 'Delicious API v2' - limit_sec = 3600 - - def get_urls(self): - return ('http://feeds.delicious.com/v2/rss/%s?count=20' % - self.service.url,) - - -def filter_title(entry): - return _('Bookmarked %s') % ('%s' % - (entry.link, entry.title)) diff --git a/apis/digg.py b/apis/digg.py deleted file mode 100644 index 61da7ce..0000000 --- a/apis/digg.py +++ /dev/null @@ -1,28 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -import webfeed - - -class API (webfeed.API): - name = 'Digg API' - limit_sec = 300 - - def get_urls(self): - return ('http://digg.com/users/%s/history.rss' % self.service.url,) - - -def filter_title(entry): - return '%s' % (entry.link, entry.title) diff --git a/apis/fb.py b/apis/fb.py deleted file mode 100644 index f0cea78..0000000 --- a/apis/fb.py +++ /dev/null @@ -1,150 +0,0 @@ -# gLifestream Copyright (C) 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -from django.conf import settings -from django.utils.html import strip_tags, strip_entities -from django.template.defaultfilters import urlizetrunc -from glifestream.filters import expand, truncate -from glifestream.utils.time import from_rfc3339, mtime, now -from glifestream.stream.models import Entry -from glifestream.stream import media - -try: - import facebook - if not hasattr(facebook, 'GraphAPI'): - facebook = None -except ImportError: - facebook = None - - -class API: - name = 'Facebook API' - limit_sec = 600 - - def __init__(self, service, verbose=0, force_overwrite=False): - self.service = service - self.verbose = verbose - self.force_overwrite = force_overwrite - if self.verbose: - print '%s: %s' % (self.name, self.service) - - def get_urls(self): - return () - - def run(self): - if not facebook: - print "ImportError: facebook. Install Facebook's python-sdk." - return - - try: - args = {} - if not self.service.last_checked: - args['limit'] = 250 - - graph = facebook.GraphAPI(self.service.creds) - if not self.service.url: - self.stream = graph.get_connections('me', 'home', **args) - else: - self.stream = graph.get_connections(self.service.url, 'feed', - **args) - self.service.last_checked = now() - self.service.save() - self.process() - except Exception, e: - if self.verbose: - import sys - import traceback - print '%s (%d) Exception: %s' % (self.service.api, - self.service.id, e) - traceback.print_exc(file=sys.stdout) - - def process(self): - for ent in self.stream['data']: - guid = 'tag:facebook.com,2004:post/%s' % ent['id'] - if self.verbose: - print "ID: %s" % guid - - if 'updated_time' in ent: - t = from_rfc3339(ent['updated_time']) - else: - t = from_rfc3339(ent['created_time']) - - try: - e = Entry.objects.get(service=self.service, guid=guid) - if not self.force_overwrite and \ - e.date_updated and mtime(t.timetuple()) <= e.date_updated: - continue - if e.protected: - continue - except Entry.DoesNotExist: - e = Entry(service=self.service, guid=guid) - - e.guid = guid - e.link = ent['actions'][0]['link'] - - if 'from' in ent: - frm = ent['from'] - image_url = 'http://graph.facebook.com/%s/picture' % frm['id'] - e.link_image = media.save_image(image_url, direct_image=False) - e.author_name = frm['name'] - - e.date_published = from_rfc3339(ent['created_time']) - e.date_updated = t - - content = '' - if 'message' in ent: - content = expand.shorts(ent['message']) - content = '

' + urlizetrunc(content, 45) + '

' - - name = '' - if 'name' in ent: - name = ent['name'] - content += '

' + ent['name'] + '

' - - if 'picture' in ent and 'link' in ent: - content += '

' - content += '' \ - 'thumbnail ' \ - % (ent['link'], media.save_image(ent['picture'], - downscale=True)) - - if 'description' in ent: - content += '

%s
' % \ - ent['description'] - elif 'caption' in ent and name != ent['caption']: - content += '
%s
' % \ - ent['caption'] - - content += '

' - else: - if 'description' in ent: - content += '
%s
' % \ - ent['description'] - elif 'caption' in ent and name != ent['caption']: - content += '
%s
' % \ - ent['caption'] - - e.content = content - if 'message' in ent: - e.title = truncate.smart(strip_tags(ent['message']), - max_length=48) - if e.title == '': - e.title = strip_entities(strip_tags(content))[0:128] - - try: - e.save() - media.extract_and_register(e) - except: - pass diff --git a/apis/flickr.py b/apis/flickr.py deleted file mode 100644 index 4651313..0000000 --- a/apis/flickr.py +++ /dev/null @@ -1,105 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -from itertools import groupby -from django.utils.translation import ugettext as _ -from glifestream.utils.time import mtime, now -from glifestream.stream.models import Entry -from glifestream.stream import media -import webfeed - - -class API (webfeed.API): - name = 'Flickr API' - limit_sec = 600 - - def get_urls(self): - if self.service.url.startswith('http://'): - return (self.service.url,) - else: - return ('http://api.flickr.com/services/feeds/photos_public.gne?id=%s&format=rss_200' % - self.service.url,) - - def process(self): - for key, group in groupby(self.fp.entries, lambda x: x.updated[0:19]): - mblob = media.mrss_init() - lgroup = 0 - content = '

\n' - first = True - for ent in group: - lgroup += 1 - if first: - firstent = ent - first = False - if self.verbose: - print "ID: %s" % ent.id - - if 'media_thumbnail' in ent: - tn = ent.media_thumbnail[0] - if self.service.public: - tn['url'] = media.save_image(tn['url']) - content += """ thumbnail\n""" % ( - ent.link, tn['url'], tn['width'], tn['height']) - - if 'media_content' in ent: - mblob['content'].append(ent.media_content) - - ent = firstent - content += '

' - guid = 'tag:flickr.com,2004:/photo/%s' % ent.id - - try: - e = Entry.objects.get(service=self.service, guid=ent.id) - if not self.force_overwrite and 'updated_parsed' in ent: - if e.date_updated and \ - mtime(ent.updated_parsed) <= e.date_updated: - continue - if e.protected: - continue - except Entry.DoesNotExist: - e = Entry(service=self.service, guid=ent.id) - - e.mblob = media.mrss_gen_json(mblob) - if lgroup > 1: - e.idata = 'grouped' - - e.link = self.service.link - e.title = 'Posted Photos' - e.content = content - - if 'published_parsed' in ent: - e.date_published = mtime(ent.published_parsed) - elif 'updated_parsed' in ent: - e.date_published = mtime(ent.updated_parsed) - if 'updated_parsed' in ent: - e.date_updated = mtime(ent.updated_parsed) - - if 'image' in self.fp.feed: - e.link_image = media.save_image(self.fp.feed.image.href) - else: - for link in ent.links: - if link.rel == 'image': - e.link_image = media.save_image(link.href) - try: - e.save() - except: - pass - - -def filter_title(entry): - if entry.idata == 'grouped': - return _('Posted Photos') - else: - return _('Posted a Photo') diff --git a/apis/friendfeed.py b/apis/friendfeed.py deleted file mode 100644 index 8156cbd..0000000 --- a/apis/friendfeed.py +++ /dev/null @@ -1,157 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -import re -import datetime -from django.utils.html import strip_tags, strip_entities -from glifestream.filters import truncate -from glifestream.utils import httpclient -from glifestream.utils.time import mtime, now -from glifestream.utils.html import bytes_to_human -from glifestream.stream.models import Entry -from glifestream.stream import media - -try: - import json -except ImportError: - import simplejson as json - -OAUTH_REQUEST_TOKEN_URL = 'https://friendfeed.com/account/oauth/request_token' -OAUTH_AUTHORIZE_URL = 'https://friendfeed.com/account/oauth/authorize' -OAUTH_ACCESS_TOKEN_URL = 'https://friendfeed.com/account/oauth/access_token' - - -class API: - name = 'FriendFeed API v2' - limit_sec = 180 - - def __init__(self, service, verbose=0, force_overwrite=False): - self.service = service - self.verbose = verbose - self.force_overwrite = force_overwrite - if self.verbose: - print '%s: %s' % (self.name, self.service) - - def get_urls(self): - if self.service.url: - return ('http://friendfeed.com/%s?format=atom' % self.service.url,) - return () - - def run(self): - if not self.service.url: - self.service.link = 'http://friendfeed.com/' - self.fetch('/v2/feed/home?fof=1&num=50') - elif not self.service.last_checked: - self.service.link = 'http://friendfeed.com/%s' % self.service.url - self.fetch('/v2/feed/%s?num=250' % self.service.url) - else: - self.fetch('/v2/feed/%s' % self.service.url) - - def fetch(self, url): - try: - hs = httpclient.gen_auth_hs(self.service, - 'http://friendfeed-api.com' + url) - r = httpclient.get('friendfeed-api.com', url, headers=hs) - if r.status == 200: - self.json = json.loads(r.data.decode('utf_8')) - self.service.last_checked = now() - self.service.save() - self.process() - elif self.verbose: - print '%s (%d) HTTP: %s' % (self.service.api, - self.service.id, r.reason) - except Exception, e: - if self.verbose: - import sys - import traceback - print '%s (%d) Exception: %s' % (self.service.api, - self.service.id, e) - traceback.print_exc(file=sys.stdout) - - def process(self): - for ent in self.json['entries']: - id = ent['id'][2:] - uuid = '%s-%s-%s-%s-%s' % (id[0:8], id[8:12], id[12:16], - id[16:20], id[20:]) - guid = 'tag:friendfeed.com,2007:%s' % uuid - if self.verbose: - print "ID: %s" % guid - - t = datetime.datetime.strptime(ent['date'], '%Y-%m-%dT%H:%M:%SZ') - try: - e = Entry.objects.get(service=self.service, guid=guid) - if not self.force_overwrite and \ - e.date_updated and mtime(t.timetuple()) <= e.date_updated: - continue - if e.protected: - continue - except Entry.DoesNotExist: - e = Entry(service=self.service, guid=guid) - - e.guid = guid - e.title = truncate.smart( - strip_entities(strip_tags(ent['body'])), - max_length=40) - e.link = ent['url'] - image_url = 'http://friendfeed-api.com/v2/picture/%s' % ent[ - 'from']['id'] - e.link_image = media.save_image(image_url, direct_image=False) - - e.date_published = t - e.date_updated = t - e.author_name = ent['from']['name'] - - content = ent['body'] - if 'thumbnails' in ent: - content += '

' - for t in ent['thumbnails']: - if self.service.public: - t['url'] = media.save_image(t['url']) - if 'width' in t and 'height' in t: - iwh = ' width="%d" height="%d"' % (t['width'], - t['height']) - else: - iwh = '' - - if 'friendfeed.com/e/' in t['link'] and \ - ('youtube.com' in t['url'] or 'ytimg.com' in t['url']): - m = re.search(r'/vi/([\-\w]+)/', t['url']) - yid = m.groups()[0] if m else None - if yid: - t['link'] = 'http://www.youtube.com/watch?v=%s' % yid - - content += 'thumbnail ' % ( - t['link'], t['url'], iwh) - content += '

' - - if 'files' in ent: - content += '
    \n' - for f in ent['files']: - if 'friendfeed-media' in f['url']: - content += '
  • %s' % ( - f['url'], f['name']) - if 'size' in f: - content += ' %s' % bytes_to_human( - f['size']) - content += '
  • \n' - content += '
\n' - - e.content = content - - try: - e.save() - media.extract_and_register(e) - except: - pass diff --git a/apis/greader.py b/apis/greader.py deleted file mode 100644 index 4f4be48..0000000 --- a/apis/greader.py +++ /dev/null @@ -1,31 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -from django.utils.translation import ugettext as _ -import webfeed - - -class API (webfeed.API): - name = 'Google Reader API' - limit_sec = 600 - - def get_urls(self): - return ('http://www.google.com/reader/public/atom/user/%s/state/com.google/broadcast' % - self.service.url,) - - -def filter_title(entry): - return _('Shared %s') % ('%s' % - (entry.link, entry.title)) diff --git a/apis/identica.py b/apis/identica.py deleted file mode 100644 index f404bb4..0000000 --- a/apis/identica.py +++ /dev/null @@ -1,43 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -from glifestream.filters import expand, truncate, twyntax -from glifestream.stream import media -import webfeed - - -class API (webfeed.API): - name = 'Identi.ca API' - limit_sec = 180 - - def get_urls(self): - if not self.service.url and self.service.creds: - return ('http://identi.ca/api/statuses/friends_timeline.rss?count=50',) - else: - if not self.service.last_checked: - return ('http://identi.ca/api/statuses/user_timeline/%s.rss?count=200' % - self.service.url,) - else: - return ('http://identi.ca/api/statuses/user_timeline/%s.rss' % - self.service.url,) - - def custom_process(self, e, ent): - e.title = 'Tweet: %s' % truncate.smart(ent.title) - e.content = expand.all(ent.summary) - e.custom_mblob = media.mrss_scan(e.content) - - -def filter_content(entry): - return twyntax.parse(entry.content, type='identica') diff --git a/apis/lastfm.py b/apis/lastfm.py deleted file mode 100644 index 35104ad..0000000 --- a/apis/lastfm.py +++ /dev/null @@ -1,40 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -from django.utils.translation import ugettext as _ -import urllib -import webfeed - - -class API (webfeed.API): - name = 'Last.fm API' - limit_sec = 180 - - def get_urls(self): - return ('http://ws.audioscrobbler.com/1.0/user/%s/recenttracks.rss' % - self.service.url, - 'http://ws.audioscrobbler.com/2.0/user/%s/lovedtracks.rss' % - self.service.url) - - -def filter_title(entry): - return _('Listened to %s') % ('%s' % - (entry.link, entry.title)) - - -def filter_content(entry): - return _('Artist: %s') % ('%s' % - (entry.content, - urllib.unquote_plus(entry.content[25:]))) diff --git a/apis/mail.py b/apis/mail.py deleted file mode 100644 index 627ba3d..0000000 --- a/apis/mail.py +++ /dev/null @@ -1,111 +0,0 @@ -# gLifestream Copyright (C) 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -import os -import re -import email -from email.header import decode_header, make_header -from django.conf import settings -from django.core.files.uploadedfile import TemporaryUploadedFile -from django.utils.datastructures import MultiValueDict -from glifestream.apis import selfposts -from glifestream.stream.models import Service - - -class API: - name = 'Email API' - - def __init__(self): - pass - - def get_urls(self): - return () - - def run(self): - pass - - def share(self, msgfile): - msg = email.message_from_file(msgfile) - args = {} - files = [] - - check = getattr(settings, 'EMAIL2POST_CHECK', {}) - for lhs in check: - v = unicode(make_header(decode_header(msg.get(lhs, '')))) - if not check[lhs] in v: - return 77 # EX_NOPERM - - if msg.is_multipart(): - for part in msg.walk(): - attach = False - t = part.get_content_type() - - if t == 'text/plain': - if part.get_filename(None): - attach = True - else: - args['content'] = part.get_payload(decode=True) - - if attach or \ - t.startswith ('image/') or \ - t.startswith ('audio/') or \ - t.startswith ('video/') or \ - t.startswith('application/'): - payload = part.get_payload(decode=True) - os.umask(0) - tmp = TemporaryUploadedFile( - name=part.get_filename('attachment'), - content_type=t, - size=len(payload), - charset=None) - tmp.write(payload) - tmp.seek(0) - os.chmod(tmp.file.name, 0644) - files.append(tmp) - else: - args['content'] = msg.get_payload(decode=True) - - subject = msg.get('Subject', None) - if subject: - hdr = make_header(decode_header(subject)) - args['title'] = unicode(hdr) - - # Mail subject may contain @foo, a selfposts' class name for which - # this message is post to. - m = re.search(r'(\A|\s)@(\w[\w\-]+)', args['title']) - if m: - cls = m.groups()[1] - args['title'] = re.sub(r'(\A|\s)@(\w[\w\-]+)', '', args['title']) - s = Service.objects.filter(cls=cls, api='selfposts').values('id') - if len(s): - args['id'] = s[0]['id'] - - # Mail subject may contain "!draft" literal. - if '!draft' in args['title']: - args['title'] = args['title'].replace('!draft', '').strip() - args['draft'] = True - - # Mail subject may contain "!friends-only" literal. - if '!friends-only' in args['title']: - args['title'] = args['title'].replace( - '!friends-only', '').strip() - args['friends_only'] = True - - if len(files): - args['files'] = MultiValueDict() - args['files'].setlist('docs', files) - - selfposts.API(None).share(args) - return 0 # EX_OK diff --git a/apis/picasaweb.py b/apis/picasaweb.py deleted file mode 100644 index fc75edf..0000000 --- a/apis/picasaweb.py +++ /dev/null @@ -1,34 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -from glifestream.stream import media -import webfeed - - -class API (webfeed.API): - name = 'PicasaWeb API' - limit_sec = 600 - - def get_urls(self): - return ('http://picasaweb.google.com/data/feed/base/user/%s?alt=rss&kind=album&access=public' % - self.service.url,) - - def custom_process(self, e, ent): - if 'media_thumbnail' in ent and len(ent.media_thumbnail): - tn = ent.media_thumbnail[0] - if self.service.public: - tn['url'] = media.save_image(tn['url']) - e.content = """

thumbnail

\n""" % ( - ent.link, tn['url'], tn['width'], tn['height']) diff --git a/apis/selfposts.py b/apis/selfposts.py deleted file mode 100644 index 710737f..0000000 --- a/apis/selfposts.py +++ /dev/null @@ -1,240 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -from django.conf import settings -from django.template.defaultfilters import urlizetrunc, title as df_title -from django.utils.html import strip_tags -from django.utils.datastructures import MultiValueDict -from django.utils.encoding import smart_unicode -from glifestream.utils.time import mtime, utcnow -from glifestream.utils.html import strip_script, bytes_to_human -from glifestream.stream.models import Service, Entry, Media -from glifestream.stream import media -from glifestream.filters import expand, truncate - -try: - import markdown -except ImportError: - markdown = None - - -class API: - name = 'Selfposts API' - - def __init__(self, service, verbose=0, force_overwrite=False): - self.service = service - self.verbose = verbose - - def get_urls(self): - return () - - def run(self): - pass - - def share(self, args={}): - content = args.get('content', '') - sid = args.get('sid', None) - title = args.get('title', None) - link = args.get('link', None) - images = args.get('images', None) - files = args.get('files', MultiValueDict()) - source = args.get('source', '') - user = args.get('user', None) - - un = utcnow() - guid = '%s/entry/%s' % (settings.FEED_TAGURI, - un.strftime('%Y-%m-%dT%H:%M:%SZ')) - if sid: - s = Service.objects.get(id=sid, api='selfposts') - else: - s = Service.objects.filter(api='selfposts').order_by('id')[0] - e = Entry(service=s, guid=guid) - - e.link = link if link else settings.BASE_URL + '/' - e.date_published = un - e.date_updated = un - e.draft = int(args.get('draft', False)) - e.friends_only = int(args.get('friends_only', False)) - - if user and user.first_name and user.last_name: - e.author_name = user.first_name + ' ' + user.last_name - - content = smart_unicode(content) - - editor_syntax = getattr(settings, 'EDITOR_SYNTAX', 'markdown') - if source == 'bookmarklet': - editor_syntax = 'html' - - if editor_syntax == 'markdown' and markdown: - e.content = expand.all(markdown.markdown(content)) - else: - e.content = expand.all(content.replace('\n', '
')) - e.content = urlizetrunc(e.content, 45) - - e.content = strip_script(e.content) - e.content = expand.imgloc(e.content) - e.content = smart_unicode(e.content) - - if images: - thumbs = '\n

\n' - for img in images: - img = media.save_image(img, force=True, downscale=True) - thumbs += """ thumbnail\n""" % ( - e.link, img) - thumbs += '

\n' - e.content += thumbs - - if title: - e.title = smart_unicode(title) - else: - e.title = truncate.smart(strip_tags(e.content)).strip() - if e.title == '': - e.title = truncate.smart(strip_tags(content)).strip() - - mblob = media.mrss_scan(e.content) - e.mblob = media.mrss_gen_json(mblob) - - try: - e.save() - - pictures = [] - docs = [] - - for f in files.getlist('docs'): - md = Media(entry=e) - md.file.save(f.name, f) - md.save() - if f.content_type.startswith('image/'): - pictures.append((md, f)) - else: - docs.append((md, f)) - - if len(pictures): - thumbs = '\n

\n' - for o in pictures: - thumb, orig = media.downsave_uploaded_image(o[0].file) - thumbs += ' thumbnail\n' % ( - orig, thumb) - mrss = {'url': orig, 'medium': 'image', - 'fileSize': o[1].size} - if orig.lower().endswith('.jpg'): - mrss['type'] = 'image/jpeg' - mblob['content'].append([mrss]) - thumbs += '

\n' - e.content += thumbs - - if len(docs): - doc = '\n
    \n' - for o in docs: - target = '[GLS-UPLOAD]/%s' % o[ - 0].file.name.replace('upload/', '') - doc += '
  • %s ' % (target, o[1].name) - doc += '%s
  • \n' % \ - bytes_to_human(o[1].size) - - mrss = {'url': target, 'fileSize': o[1].size} - target = target.lower() - if target.endswith('.mp3'): - mrss['medium'] = 'audio' - mrss['type'] = 'audio/mpeg' - elif target.endswith('.ogg'): - mrss['medium'] = 'audio' - mrss['type'] = 'audio/ogg' - elif target.endswith('.avi'): - mrss['medium'] = 'video' - mrss['type'] = 'video/avi' - elif target.endswith('.pdf'): - mrss['medium'] = 'document' - mrss['type'] = 'application/pdf' - else: - mrss['medium'] = 'document' - mblob['content'].append([mrss]) - - doc += '
\n' - e.content += doc - - e.mblob = media.mrss_gen_json(mblob) - if len(pictures) or len(docs): - e.save() - - media.extract_and_register(e) - return e - except: - pass - - def reshare(self, entry, args={}): - sid = args.get('sid', None) - as_me = int(args.get('as_me', False)) - user = args.get('user', None) - - un = utcnow() - guid = '%s/entry/%s' % (settings.FEED_TAGURI, - un.strftime('%Y-%m-%dT%H:%M:%SZ')) - if sid: - s = Service.objects.get(id=sid, api='selfposts') - else: - s = Service.objects.filter(api='selfposts').order_by('id')[0] - e = Entry(service=s, guid=guid) - - e.date_published = un - e.date_updated = un - - if as_me: - if user and user.first_name and user.last_name: - e.author_name = user.first_name + ' ' + user.last_name - else: - e.author_name = '' - e.author_email = '' - e.author_uri = '' - if entry.service.api == 'greader': - e.link = entry.link - else: - e.link = settings.BASE_URL + '/' - if entry.service.api == 'twitter': - entry.content = entry.content.split(': ', 1)[1] - else: - e.author_name = entry.author_name - e.author_email = entry.author_email - e.author_uri = entry.author_uri - e.link = entry.link - - e.geolat = entry.geolat - e.geolng = entry.geolng - e.mblob = entry.mblob - - e.title = entry.title - if entry.service.api == 'greader': - e.content = '%s' % ( - e.link, e.title) - elif entry.service.api in ('youtube', 'vimeo'): - e.content = '

%s

%s' % (df_title(e.title), entry.content) - else: - e.content = urlizetrunc(entry.content, 45) - - try: - media.transform_to_local(e) - media.extract_and_register(e) - e.save() - return e - except: - pass - - -def filter_title(entry): - return entry.title - - -def filter_content(entry): - return entry.content diff --git a/apis/stumbleupon.py b/apis/stumbleupon.py deleted file mode 100644 index b6711a4..0000000 --- a/apis/stumbleupon.py +++ /dev/null @@ -1,31 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -import webfeed - - -class API (webfeed.API): - name = 'StumbleUpon API' - limit_sec = 600 - - def get_urls(self): - return ('http://rss.stumbleupon.com/user/%s/favorites' % - self.service.url, - 'http://rss.stumbleupon.com/user/%s/reviews' % - self.service.url) - - -def filter_title(entry): - return '%s' % (entry.link, entry.title) diff --git a/apis/twitter.py b/apis/twitter.py deleted file mode 100644 index 23326cc..0000000 --- a/apis/twitter.py +++ /dev/null @@ -1,153 +0,0 @@ -# gLifestream Copyright (C) 2009, 2010, 2012, 2013 Wojciech Polak -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . - -import datetime -from django.utils.html import strip_tags, strip_entities -from glifestream.filters import expand, truncate, twyntax -from glifestream.utils import httpclient -from glifestream.utils.time import mtime, now -from glifestream.stream.models import Entry -from glifestream.stream import media - -try: - import json -except ImportError: - import simplejson as json - -OAUTH_REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token' -OAUTH_AUTHORIZE_URL = 'https://api.twitter.com/oauth/authorize' -OAUTH_ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token' - - -class API: - name = 'Twitter API v1.1' - limit_sec = 120 - - def __init__(self, service, verbose=0, force_overwrite=False): - self.service = service - self.verbose = verbose - self.force_overwrite = force_overwrite - if self.verbose: - print '%s: %s' % (self.name, self.service) - - def get_urls(self): - if not self.service.creds: - return () - if not self.service.url: - return ('/1.1/statuses/home_timeline.json?count=50',) - else: - if not self.service.last_checked: - return ('/1.1/statuses/user_timeline.json?screen_name=%s&count=200' % - self.service.url,) - else: - return ('/1.1/statuses/user_timeline.json?screen_name=%s' % - self.service.url,) - - def run(self): - for url in self.get_urls(): - try: - self.fetch(url) - except: - pass - - def fetch(self, url): - try: - hs = httpclient.gen_auth_hs(self.service, - 'https://api.twitter.com' + url) - r = httpclient.get('api.twitter.com', url, headers=hs, https=True) - if r.status == 200: - self.json = json.loads(r.data.decode('utf_8')) - self.service.last_checked = now() - self.service.save() - self.process() - elif self.verbose: - print '%s (%d) HTTP: %s' % (self.service.api, - self.service.id, r.reason) - except Exception, e: - if self.verbose: - import sys - import traceback - print '%s (%d) Exception: %s' % (self.service.api, - self.service.id, e) - traceback.print_exc(file=sys.stdout) - - def process(self): - for ent in self.json: - guid = 'tag:twitter.com,2007:http://twitter.com/%s/statuses/%s' % \ - (ent['user']['screen_name'], ent['id']) - if self.verbose: - print "ID: %s" % guid - - t = datetime.datetime.strptime(ent['created_at'], - '%a %b %d %H:%M:%S +0000 %Y') - try: - e = Entry.objects.get(service=self.service, guid=guid) - if not self.force_overwrite and \ - e.date_updated and mtime(t.timetuple()) <= e.date_updated: - continue - if e.protected: - continue - except Entry.DoesNotExist: - e = Entry(service=self.service, guid=guid) - - e.guid = guid - e.title = 'Tweet: %s' % truncate.smart( - strip_entities(strip_tags(ent['text'])), max_length=40) - e.title = e.title.replace('#', '').replace('@', '') - - e.link = 'https://twitter.com/%s/status/%s' % \ - (ent['user']['screen_name'], ent['id']) - image_url = ent['user']['profile_image_url_https'] - e.link_image = media.save_image(image_url, direct_image=False) - - e.date_published = t - e.date_updated = t - e.author_name = ent['user']['name'] - e.content = 'Tweet: %s' % expand.all(ent['text']) - - if 'entities' in ent and 'media' in ent['entities']: - content = '

' - for t in ent['entities']['media']: - if t['type'] == 'photo': - tsize = 'thumb' - if 'media_url_https' in t: - image_url = '%s:%s' % (t['media_url_https'], tsize) - large_url = '%s:large' % t['media_url_https'] - else: - image_url = '%s:%s' % (t['media_url'], tsize) - large_url = t['media_url'] - link = t['expanded_url'] - if self.service.public: - image_url = media.save_image(image_url) - if 'sizes' in t and tsize in t['sizes']: - sizes = t['sizes'][tsize] - iwh = ' width="%d" height="%d"' % (sizes['w'], - sizes['h']) - else: - iwh = '' - content += 'thumbnail ' % ( -