summaryrefslogtreecommitdiff
path: root/addons/website_twitter/models
diff options
context:
space:
mode:
authorBarad Mahendra <mba@tinyerp.com>2014-04-10 19:46:22 +0200
committerOlivier Dony <odo@openerp.com>2014-04-10 19:46:22 +0200
commit0152bea512d868cbb0d9adf33cdbf98bc2030a0f (patch)
tree6553ccef3cc7a9a0814ad8441c24e4f98df6a7f4 /addons/website_twitter/models
parent7c75b5e004ef2e1c836ad2cc788a701a687a6440 (diff)
[MERGE] [ADD] website_twitter: add twitter scroller snippet
bzr revid: odo@openerp.com-20140410174622-j2waid38nk3fqitt
Diffstat (limited to 'addons/website_twitter/models')
-rw-r--r--addons/website_twitter/models/__init__.py3
-rw-r--r--addons/website_twitter/models/twitter.py115
-rw-r--r--addons/website_twitter/models/twitter_config.py42
3 files changed, 160 insertions, 0 deletions
diff --git a/addons/website_twitter/models/__init__.py b/addons/website_twitter/models/__init__.py
new file mode 100644
index 00000000000..8c34d4f968e
--- /dev/null
+++ b/addons/website_twitter/models/__init__.py
@@ -0,0 +1,3 @@
+import twitter
+import twitter_config
+
diff --git a/addons/website_twitter/models/twitter.py b/addons/website_twitter/models/twitter.py
new file mode 100644
index 00000000000..7c1c417040b
--- /dev/null
+++ b/addons/website_twitter/models/twitter.py
@@ -0,0 +1,115 @@
+from urllib2 import urlopen, Request, HTTPError
+
+import base64
+import json
+import logging
+import werkzeug
+
+from openerp.osv import fields, osv
+
+API_ENDPOINT = 'https://api.twitter.com'
+API_VERSION = '1.1'
+REQUEST_TOKEN_URL = '%s/oauth2/token' % API_ENDPOINT
+REQUEST_FAVORITE_LIST_URL = '%s/%s/favorites/list.json' % (API_ENDPOINT, API_VERSION)
+URLOPEN_TIMEOUT = 10
+
+_logger = logging.getLogger(__name__)
+
+class TwitterClient(osv.osv):
+ _inherit = "website"
+
+ _columns = {
+ 'twitter_api_key': fields.char('Twitter API key', help="Twitter API Key"),
+ 'twitter_api_secret': fields.char('Twitter API secret', help="Twitter API Secret"),
+ 'twitter_screen_name': fields.char('Get favorites from this screen name'),
+ }
+
+ def _request(self, website, url, params=None):
+ """Send an authenticated request to the Twitter API."""
+ access_token = self._get_access_token(website)
+ if params:
+ params = werkzeug.url_encode(params)
+ url = url + '?' + params
+ try:
+ request = Request(url)
+ request.add_header('Authorization', 'Bearer %s' % access_token)
+ return json.load(urlopen(request, timeout=URLOPEN_TIMEOUT))
+ except HTTPError, e:
+ _logger.debug("Twitter API request failed with code: %r, msg: %r, content: %r",
+ e.code, e.msg, e.fp.read())
+ raise
+
+ def _refresh_favorite_tweets(self, cr, uid, context=None):
+ ''' called by cron job '''
+ website = self.pool['website']
+ ids = self.pool['website'].search(cr, uid, [('twitter_api_key', '!=', False),
+ ('twitter_api_secret', '!=', False),
+ ('twitter_screen_name', '!=', False)],
+ context=context)
+ _logger.debug("Refreshing tweets for website IDs: %r", ids)
+ website.fetch_favorite_tweets(cr, uid, ids, context=context)
+
+ def fetch_favorite_tweets(self, cr, uid, ids, context=None):
+ website_tweets = self.pool['website.twitter.tweet']
+ tweet_ids = []
+ for website in self.browse(cr, uid, ids, context=context):
+ if not all((website.twitter_api_key, website.twitter_api_secret,
+ website.twitter_screen_name)):
+ _logger.debug("Skip fetching favorite tweets for unconfigured website %s",
+ website)
+ continue
+ params = {'screen_name': website.twitter_screen_name}
+ last_tweet = website_tweets.search_read(
+ cr, uid, [('website_id', '=', website.id),
+ ('screen_name', '=', website.twitter_screen_name)],
+ ['tweet_id'],
+ limit=1, order='tweet_id desc', context=context)
+ if last_tweet:
+ params['since_id'] = int(last_tweet[0]['tweet_id'])
+ _logger.debug("Fetching favorite tweets using params %r", params)
+ response = self._request(website, REQUEST_FAVORITE_LIST_URL, params=params)
+ for tweet_dict in response:
+ tweet_id = tweet_dict['id'] # unsigned 64-bit snowflake ID
+ tweet_ids = website_tweets.search(cr, uid, [('tweet_id', '=', tweet_id)])
+ if not tweet_ids:
+ new_tweet = website_tweets.create(
+ cr, uid,
+ {
+ 'website_id': website.id,
+ 'tweet': json.dumps(tweet_dict),
+ 'tweet_id': tweet_id, # stored in NUMERIC PG field
+ 'screen_name': website.twitter_screen_name,
+ },
+ context=context)
+ _logger.debug("Found new favorite: %r, %r", tweet_id, tweet_dict)
+ tweet_ids.append(new_tweet)
+ return tweet_ids
+
+ def _get_access_token(self, website):
+ """Obtain a bearer token."""
+ bearer_token_cred = '%s:%s' % (website.twitter_api_key, website.twitter_api_secret)
+ encoded_cred = base64.b64encode(bearer_token_cred)
+ request = Request(REQUEST_TOKEN_URL)
+ request.add_header('Content-Type',
+ 'application/x-www-form-urlencoded;charset=UTF-8')
+ request.add_header('Authorization',
+ 'Basic %s' % encoded_cred)
+ request.add_data('grant_type=client_credentials')
+ data = json.load(urlopen(request, timeout=URLOPEN_TIMEOUT))
+ access_token = data['access_token']
+ return access_token
+
+class WebsiteTwitterTweet(osv.osv):
+ _name = "website.twitter.tweet"
+ _description = "Twitter Tweets"
+ _columns = {
+ 'website_id': fields.many2one('website', string="Website"),
+ 'screen_name': fields.char("Screen Name"),
+ 'tweet': fields.text('Tweets'),
+
+ # Twitter IDs are 64-bit unsigned ints, so we need to store them in
+ # unlimited precision NUMERIC columns, which can be done with a
+ # float field. Used digits=(0,0) to indicate unlimited.
+ # Using VARCHAR would work too but would have sorting problems.
+ 'tweet_id': fields.float("Tweet ID", digits=(0,0)), # Twitter
+ }
diff --git a/addons/website_twitter/models/twitter_config.py b/addons/website_twitter/models/twitter_config.py
new file mode 100644
index 00000000000..3330a5b0424
--- /dev/null
+++ b/addons/website_twitter/models/twitter_config.py
@@ -0,0 +1,42 @@
+import logging
+
+from openerp.osv import fields, osv
+from openerp.tools.translate import _
+
+_logger = logging.getLogger(__name__)
+
+class twitter_config_settings(osv.osv_memory):
+ _inherit = 'website.config.settings'
+
+ _columns = {
+ 'twitter_api_key': fields.related(
+ 'website_id', 'twitter_api_key', type="char",
+ string='Twitter API Key',
+ help="Twitter API key you can get it from https://apps.twitter.com/app/new"),
+ 'twitter_api_secret': fields.related(
+ 'website_id', 'twitter_api_secret', type="char",
+ string='Twitter API secret',
+ help="Twitter API secret you can get it from https://apps.twitter.com/app/new"),
+ 'twitter_tutorial': fields.dummy(
+ type="boolean", string="Show me how to obtain the Twitter API Key and Secret"),
+ 'twitter_screen_name': fields.related(
+ 'website_id', 'twitter_screen_name',
+ type="char", string='Get favorites from this screen name',
+ help="Screen Name of the Twitter Account from which you want to load favorites."
+ "It does not have to match the API Key/Secret."),
+ }
+
+ def _check_twitter_authorization(self, cr, uid, config_id, context=None):
+ website_obj = self.pool['website']
+ website_config = self.browse(cr, uid, config_id, context=context)
+ try:
+ website_obj.fetch_favorite_tweets(cr, uid, [website_config.website_id.id], context=context)
+ except Exception:
+ _logger.warning('Failed to verify twitter API authorization', exc_info=True)
+ raise osv.except_osv(_('Twitter authorization error!'), _('Please double-check your Twitter API Key and Secret'))
+
+ def create(self, cr, uid, vals, context=None):
+ res_id = super(twitter_config_settings, self).create(cr, uid, vals, context=context)
+ if vals.get('twitter_api_key') and vals.get('twitter_api_secret'):
+ self._check_twitter_authorization(cr, uid, res_id, context=context)
+ return res_id \ No newline at end of file