[MIG] website_twitter: migration to new api

This commit is contained in:
Rohan Patel
2016-04-07 14:18:05 +02:00
committed by David Monjoie
parent 12bd44fd96
commit c3ff15b147
11 changed files with 129 additions and 130 deletions
+4 -1
View File
@@ -1,2 +1,5 @@
import models
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import controllers
import models
+3 -2
View File
@@ -1,3 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Twitter Roller',
'category': 'Website',
@@ -16,7 +19,5 @@ Display best tweets
'views/website_twitter_settings_views.xml',
'views/website_twitter_snippet_templates.xml'
],
'demo': [],
'qweb': [],
'installable': True,
}
@@ -1 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import main
+13 -12
View File
@@ -1,8 +1,11 @@
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.tools.translate import _
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import json
from odoo import _
from odoo.addons.web import http
from odoo.addons.web.http import request
class Twitter(http.Controller):
@http.route(['/twitter_reload'], type='json', auth="user", website=True)
@@ -14,8 +17,7 @@ class Twitter(http.Controller):
key = request.website.twitter_api_key
secret = request.website.twitter_api_secret
screen_name = request.website.twitter_screen_name
cr, uid = request.cr, request.uid
debug = request.registry['res.users'].has_group(cr, uid, 'base.group_website_publisher')
debug = request.env['res.users'].has_group('base.group_website_publisher')
if not key or not secret:
if debug:
return {"error": _("Please set the Twitter API Key and Secret in the Website Settings.")}
@@ -25,12 +27,11 @@ class Twitter(http.Controller):
return {"error": _("Please set a Twitter screen name to load favorites from, "
"in the Website Settings (it does not have to be yours)")}
return []
twitter_tweets = request.registry['website.twitter.tweet']
tweets = twitter_tweets.search_read(
cr, uid,
[('website_id','=', request.website.id),
('screen_name','=', screen_name)],
['tweet'], limit=int(limit), order="tweet_id desc", context=request.context)
TwitterTweets = request.env['website.twitter.tweet']
tweets = TwitterTweets.search(
[('website_id', '=', request.website.id),
('screen_name', '=', screen_name)],
limit=int(limit), order="tweet_id desc")
if len(tweets) < 12:
if debug:
return {"error": _("Twitter user @%(username)s has less than 12 favorite tweets. "
@@ -38,4 +39,4 @@ class Twitter(http.Controller):
{'username': screen_name}}
else:
return []
return [json.loads(tweet['tweet']) for tweet in tweets]
return tweets.mapped(lambda t: json.loads(t.tweet))
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<record id="ir_cron_twitter_actions" model="ir.cron">
<field name="name">Fetch new Twitter favorites</field>
<field name="interval_number">2</field>
@@ -11,6 +11,6 @@
<field name="function">_refresh_favorite_tweets</field>
<field name="args">()</field>
</record>
</data>
</openerp>
</odoo>
@@ -1,3 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import website_twitter
import website_twitter_config
import website_twitter_tweet
@@ -1,13 +1,12 @@
# -*- coding: utf-8 -*-
from urllib2 import urlopen, Request, HTTPError
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import base64
import json
import logging
import werkzeug
from openerp.osv import fields, osv
from urllib2 import urlopen, Request, HTTPError
from odoo import api, fields, models
API_ENDPOINT = 'https://api.twitter.com'
API_VERSION = '1.1'
@@ -17,15 +16,15 @@ 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'),
}
class WebsiteTwitter(models.Model):
_inherit = 'website'
twitter_api_key = fields.Char(string='Twitter API key', help='Twitter API Key')
twitter_api_secret = fields.Char(string='Twitter API secret', help='Twitter API Secret')
twitter_screen_name = fields.Char(string='Get favorites from this screen name')
@api.model
def _request(self, website, url, params=None):
"""Send an authenticated request to the Twitter API."""
access_token = self._get_access_token(website)
@@ -41,50 +40,44 @@ class TwitterClient(osv.osv):
e.code, e.msg, e.fp.read())
raise
def _refresh_favorite_tweets(self, cr, uid, context=None):
@api.model
def _refresh_favorite_tweets(self):
''' 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)
website = self.env['website'].search([('twitter_api_key', '!=', False),
('twitter_api_secret', '!=', False),
('twitter_screen_name', '!=', False)])
_logger.debug("Refreshing tweets for website IDs: %r", website.ids)
website.fetch_favorite_tweets()
def fetch_favorite_tweets(self, cr, uid, ids, context=None):
website_tweets = self.pool['website.twitter.tweet']
@api.multi
def fetch_favorite_tweets(self):
WebsiteTweets = self.env['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)
for website in self:
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)
last_tweet = WebsiteTweets.search([('website_id', '=', website.id),
('screen_name', '=', website.twitter_screen_name)],
limit=1, order='tweet_id desc')
if last_tweet:
params['since_id'] = int(last_tweet[0]['tweet_id'])
params['since_id'] = int(last_tweet.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)])
tweet_id = tweet_dict['id'] # unsigned 64-bit snowflake ID
tweet_ids = WebsiteTweets.search([('tweet_id', '=', tweet_id)]).ids
if not tweet_ids:
new_tweet = website_tweets.create(
cr, uid,
new_tweet = WebsiteTweets.create(
{
'website_id': website.id,
'tweet': json.dumps(tweet_dict),
'tweet_id': tweet_id, # stored in NUMERIC PG field
'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)
tweet_ids.append(new_tweet.id)
return tweet_ids
def _get_access_token(self, website):
@@ -1,62 +1,57 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
from urllib2 import URLError, HTTPError
from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp.exceptions import UserError
from odoo import api, fields, models, _
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
TWITTER_EXCEPTION = {
304: _('There was no new data to return.'),
400: _('The request was invalid or cannot be otherwise served. Requests without authentication are considered invalid and will yield this response.'),
401: _('Authentication credentials were missing or incorrect. Maybe screen name tweets are protected.'),
403: _('The request is understood, but it has been refused or access is not allowed. Please check your Twitter API Key and Secret.'),
429: _('Request cannot be served due to the applications rate limit having been exhausted for the resource.'),
500: _('Twitter seems broken. Please retry later. You may consider posting an issue on Twitter forums to get help.'),
502: _('Twitter is down or being upgraded.'),
503: _('The Twitter servers are up, but overloaded with requests. Try again later.'),
504: _('The Twitter servers are up, but the request could not be serviced due to some failure within our stack. Try again later.')
}
class twitter_config_settings(osv.TransientModel):
class WebsiteTwitterConfig(models.TransientModel):
_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."),
}
twitter_api_key = fields.Char(
related='website_id.twitter_api_key',
string='Twitter API Key',
help='Twitter API key you can get it from https://apps.twitter.com/app/new')
twitter_api_secret = fields.Char(
related='website_id.twitter_api_secret',
string='Twitter API secret',
help='Twitter API secret you can get it from https://apps.twitter.com/app/new')
twitter_tutorial = fields.Boolean(string='Show me how to obtain the Twitter API Key and Secret')
twitter_screen_name = fields.Char(
related='website_id.twitter_screen_name',
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 _get_twitter_exception_message(self, error_code, context=None):
TWITTER_EXCEPTION = {
304: _('There was no new data to return.'),
400: _('The request was invalid or cannot be otherwise served. Requests without authentication are considered invalid and will yield this response.'),
401: _('Authentication credentials were missing or incorrect. Maybe screen name tweets are protected.'),
403: _('The request is understood, but it has been refused or access is not allowed. Please check your Twitter API Key and Secret.'),
429: _('Request cannot be served due to the applications rate limit having been exhausted for the resource.'),
500: _('Twitter seems broken. Please retry later. You may consider posting an issue on Twitter forums to get help.'),
502: _('Twitter is down or being upgraded.'),
503: _('The Twitter servers are up, but overloaded with requests. Try again later.'),
504: _('The Twitter servers are up, but the request could not be serviced due to some failure within our stack. Try again later.')
}
def _get_twitter_exception_message(self, error_code):
if error_code in TWITTER_EXCEPTION:
return TWITTER_EXCEPTION[error_code]
else:
return _('HTTP Error: Something is misconfigured')
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)
def _check_twitter_authorization(self):
try:
website_obj.fetch_favorite_tweets(cr, uid, [website_config.website_id.id], context=context)
self.website_id.fetch_favorite_tweets()
except HTTPError, e:
_logger.info("%s - %s" % (e.code, e.reason), exc_info=True)
raise UserError("%s - %s" % (e.code, e.reason) + ':' + self._get_twitter_exception_message(e.code, context))
raise UserError("%s - %s" % (e.code, e.reason) + ':' + self._get_twitter_exception_message(e.code))
except URLError, e:
_logger.info(_('We failed to reach a twitter server.'), exc_info=True)
raise UserError(_('Internet connection refused') + ' ' + _('We failed to reach a twitter server.'))
@@ -64,14 +59,16 @@ class twitter_config_settings(osv.TransientModel):
_logger.info(_('Please double-check your Twitter API Key and Secret!'), exc_info=True)
raise UserError(_('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)
@api.model
def create(self, vals):
TwitterConfig = super(WebsiteTwitterConfig, self).create(vals)
if vals.get('twitter_api_key') or vals.get('twitter_api_secret') or vals.get('twitter_screen_name'):
self._check_twitter_authorization(cr, uid, res_id, context=context)
return res_id
TwitterConfig._check_twitter_authorization()
return TwitterConfig
def write(self, cr, uid, ids, vals, context=None):
res_id = super(twitter_config_settings, self).write(cr, uid, ids, vals, context=context)
@api.multi
def write(self, vals):
TwitterConfig = super(WebsiteTwitterConfig, self).write(vals)
if vals.get('twitter_api_key') or vals.get('twitter_api_secret') or vals.get('twitter_screen_name'):
self._check_twitter_authorization(cr, uid, ids, context=context)
return res_id
self._check_twitter_authorization()
return TwitterConfig
@@ -1,20 +1,18 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from openerp.osv import fields, osv
from odoo import fields, models
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'),
class WebsiteTwitterTweet(models.Model):
_name = 'website.twitter.tweet'
# 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
}
website_id = fields.Many2one('website', string='Website')
screen_name = fields.Char(string='Screen Name')
tweet = fields.Text(string='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(string='Tweet ID', digits=(0, 0)) # Twitter
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<record id="view_website_config_settings" model="ir.ui.view">
<field name="name">Twitter settings</field>
<field name="model">website.config.settings</field>
@@ -52,5 +52,5 @@
</xpath>
</field>
</record>
</data>
</openerp>
</odoo>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="website_twitter_snippet" name="Twitter snippet" inherit_id="website.snippets">
<odoo>
<template id="website_twitter_snippet" inherit_id="website.snippets" name="Twitter snippet">
<xpath expr="//div[@id='snippet_feature']/div[@class='o_panel_body']" position="inside">
<div>
<div class="oe_snippet_thumbnail">
@@ -14,7 +14,7 @@
</div>
</xpath>
</template>
<template id="website_twitter_options" name="Twitter Options" inherit_id="website.snippet_options">
<template id="website_twitter_options" inherit_id="website.snippet_options" name="Twitter Options">
<xpath expr="//div" position="after">
<div data-js='twitter'
data-selector=".twitter"
@@ -33,5 +33,5 @@
<script type="text/javascript" src="/website_twitter/static/src/js/website.twitter.editor.js"/>
</xpath>
</template>
</data>
</openerp>
</odoo>