2010-11-04 02:18:18 +03:00
|
|
|
# ***** BEGIN LICENSE BLOCK *****
|
|
|
|
# Version: MPL 1.1
|
|
|
|
#
|
|
|
|
# The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
# 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
# the License. You may obtain a copy of the License at
|
|
|
|
# http://www.mozilla.org/MPL/
|
|
|
|
#
|
|
|
|
# Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
# for the specific language governing rights and limitations under the
|
|
|
|
# License.
|
|
|
|
#
|
|
|
|
# The Original Code is Raindrop.
|
|
|
|
#
|
|
|
|
# The Initial Developer of the Original Code is
|
|
|
|
# Mozilla Messaging, Inc..
|
|
|
|
# Portions created by the Initial Developer are Copyright (C) 2009
|
|
|
|
# the Initial Developer. All Rights Reserved.
|
|
|
|
#
|
|
|
|
# Contributor(s):
|
|
|
|
#
|
|
|
|
|
2010-09-02 10:29:21 +04:00
|
|
|
import logging
|
|
|
|
import json
|
2010-10-15 02:23:16 +04:00
|
|
|
import copy
|
|
|
|
from urlparse import urlparse
|
2010-10-16 00:55:52 +04:00
|
|
|
from paste.deploy.converters import asbool
|
2011-02-23 04:23:43 +03:00
|
|
|
import hashlib
|
2010-09-02 10:29:21 +04:00
|
|
|
|
2011-03-31 23:09:24 +04:00
|
|
|
from pylons import request
|
2010-09-02 10:29:21 +04:00
|
|
|
|
2011-03-24 15:55:49 +03:00
|
|
|
from linkoauth import get_provider
|
2011-03-26 01:23:37 +03:00
|
|
|
from linkoauth.base import OAuthKeysException, ServiceUnavailableException
|
2011-03-24 15:55:49 +03:00
|
|
|
|
2010-09-02 10:29:21 +04:00
|
|
|
from linkdrop.lib.base import BaseController
|
2011-03-31 23:09:24 +04:00
|
|
|
from linkdrop.lib.helpers import json_exception_response, api_response
|
2011-04-21 08:22:08 +04:00
|
|
|
from linkdrop.lib.helpers import api_entry, api_arg, get_passthrough_headers
|
2010-10-05 01:44:15 +04:00
|
|
|
from linkdrop.lib import constants
|
2011-02-11 06:39:38 +03:00
|
|
|
from linkdrop.lib.metrics import metrics
|
2011-02-18 01:56:42 +03:00
|
|
|
from linkdrop.lib.shortener import shorten_link
|
2010-09-02 10:29:21 +04:00
|
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
class SendController(BaseController):
|
|
|
|
"""
|
|
|
|
Send
|
|
|
|
====
|
|
|
|
|
|
|
|
The 'send' namespace is used to send updates to our supported services.
|
|
|
|
|
|
|
|
"""
|
2011-04-13 05:19:45 +04:00
|
|
|
__api_controller__ = True # for docs
|
2010-09-02 10:29:21 +04:00
|
|
|
|
|
|
|
@api_response
|
|
|
|
@json_exception_response
|
2010-11-26 21:59:06 +03:00
|
|
|
@api_entry(
|
|
|
|
doc="""
|
|
|
|
send
|
|
|
|
----
|
|
|
|
|
|
|
|
Share a link through F1.
|
|
|
|
""",
|
|
|
|
queryargs=[
|
|
|
|
# name, type, required, default, allowed, doc
|
|
|
|
api_arg('domain', 'string', True, None, None, """
|
|
|
|
Domain of service to share to (google.com for gmail, facebook.com, twitter.com)
|
|
|
|
"""),
|
|
|
|
api_arg('message', 'string', True, None, None, """
|
|
|
|
Message entered by user
|
|
|
|
"""),
|
|
|
|
api_arg('username', 'string', False, None, None, """
|
2011-04-13 05:19:45 +04:00
|
|
|
Optional username, required if more than one account is configured for """
|
|
|
|
"""a domain.
|
2010-11-26 21:59:06 +03:00
|
|
|
"""),
|
|
|
|
api_arg('userid', 'string', False, None, None, """
|
|
|
|
Optional userid, required if more than one account is configured for a domain.
|
|
|
|
"""),
|
|
|
|
api_arg('link', 'string', False, None, None, """
|
|
|
|
URL to share
|
|
|
|
"""),
|
|
|
|
api_arg('shorturl', 'string', False, None, None, """
|
|
|
|
Shortened version of URL to share
|
|
|
|
"""),
|
|
|
|
api_arg('shorten', 'boolean', False, None, None, """
|
|
|
|
Force a shortening of the URL provided
|
|
|
|
"""),
|
|
|
|
api_arg('to', 'string', False, None, None, """
|
|
|
|
Individual or group to share with, not supported by all services.
|
|
|
|
"""),
|
|
|
|
api_arg('subject', 'string', False, None, None, """
|
|
|
|
Subject line for emails, not supported by all services.
|
|
|
|
"""),
|
|
|
|
api_arg('picture', 'string', False, None, None, """
|
|
|
|
URL to publicly available thumbnail, not supported by all services.
|
2011-01-18 22:00:42 +03:00
|
|
|
"""),
|
|
|
|
api_arg('picture_base64', 'string', False, None, None, """
|
|
|
|
Base 64 encoded PNG version of the picture used for attaching to emails.
|
2010-11-26 21:59:06 +03:00
|
|
|
"""),
|
|
|
|
api_arg('description', 'string', False, None, None, """
|
|
|
|
Site provided description of the shared item, not supported by all services.
|
|
|
|
"""),
|
|
|
|
api_arg('name', 'string', False, None, None, """
|
|
|
|
"""),
|
|
|
|
],
|
2011-04-13 05:19:45 +04:00
|
|
|
response={'type': 'list', 'doc': 'raw data list'})
|
2010-09-02 10:29:21 +04:00
|
|
|
def send(self):
|
2010-09-03 01:02:32 +04:00
|
|
|
result = {}
|
|
|
|
error = None
|
2011-03-25 00:25:46 +03:00
|
|
|
acct = None
|
2010-09-10 04:36:13 +04:00
|
|
|
domain = request.POST.get('domain')
|
2010-09-30 10:37:46 +04:00
|
|
|
message = request.POST.get('message', '')
|
2010-09-10 04:36:13 +04:00
|
|
|
username = request.POST.get('username')
|
2010-10-15 02:23:16 +04:00
|
|
|
longurl = request.POST.get('link')
|
2010-10-16 00:55:52 +04:00
|
|
|
shorten = asbool(request.POST.get('shorten', 0))
|
2010-09-15 01:18:46 +04:00
|
|
|
shorturl = request.POST.get('shorturl')
|
2010-09-10 04:36:13 +04:00
|
|
|
userid = request.POST.get('userid')
|
2010-09-15 01:18:46 +04:00
|
|
|
to = request.POST.get('to')
|
2011-02-18 03:06:46 +03:00
|
|
|
account_data = request.POST.get('account', None)
|
2010-09-30 10:37:46 +04:00
|
|
|
if not domain:
|
2010-09-10 04:36:13 +04:00
|
|
|
error = {
|
2010-10-01 04:36:12 +04:00
|
|
|
'message': "'domain' is not optional",
|
2011-04-13 05:19:45 +04:00
|
|
|
'code': constants.INVALID_PARAMS,
|
2010-09-03 01:02:32 +04:00
|
|
|
}
|
|
|
|
return {'result': result, 'error': error}
|
2010-09-03 02:24:50 +04:00
|
|
|
provider = get_provider(domain)
|
2011-03-22 06:38:54 +03:00
|
|
|
if provider is None:
|
|
|
|
error = {
|
|
|
|
'message': "'domain' is invalid",
|
2011-04-13 05:19:45 +04:00
|
|
|
'code': constants.INVALID_PARAMS,
|
2011-03-22 06:38:54 +03:00
|
|
|
}
|
|
|
|
return {'result': result, 'error': error}
|
|
|
|
|
2011-03-25 00:25:46 +03:00
|
|
|
if account_data:
|
|
|
|
acct = json.loads(account_data)
|
2010-09-23 04:44:26 +04:00
|
|
|
if not acct:
|
2011-03-03 22:37:24 +03:00
|
|
|
metrics.track(request, 'send-noaccount', domain=domain)
|
2010-09-09 00:18:53 +04:00
|
|
|
error = {'provider': domain,
|
2011-03-31 23:09:24 +04:00
|
|
|
'message': ("not logged in or no user "
|
|
|
|
"account for that domain"),
|
2011-04-13 05:19:45 +04:00
|
|
|
'status': 401,
|
2010-09-03 01:02:32 +04:00
|
|
|
}
|
|
|
|
return {'result': result, 'error': error}
|
2010-09-02 10:29:21 +04:00
|
|
|
|
2010-10-15 02:23:16 +04:00
|
|
|
args = copy.copy(request.POST)
|
2010-10-16 00:55:52 +04:00
|
|
|
if shorten and not shorturl and longurl:
|
2011-02-11 06:39:38 +03:00
|
|
|
link_timer = metrics.start_timer(request, long_url=longurl)
|
2010-10-15 02:23:16 +04:00
|
|
|
u = urlparse(longurl)
|
|
|
|
if not u.scheme:
|
|
|
|
longurl = 'http://' + longurl
|
2011-02-18 01:56:42 +03:00
|
|
|
shorturl = shorten_link(longurl)
|
2011-02-11 06:39:38 +03:00
|
|
|
link_timer.track('link-shorten', short_url=shorturl)
|
2010-10-15 02:23:16 +04:00
|
|
|
args['shorturl'] = shorturl
|
|
|
|
|
2011-03-31 23:09:24 +04:00
|
|
|
acct_hash = hashlib.sha1(
|
|
|
|
"%s#%s" % ((username or '').encode('utf-8'),
|
|
|
|
(userid or '').encode('utf-8'))).hexdigest()
|
|
|
|
timer = metrics.start_timer(request, domain=domain,
|
|
|
|
message_len=len(message),
|
|
|
|
long_url=longurl,
|
|
|
|
short_url=shorturl,
|
|
|
|
acct_id=acct_hash)
|
2010-09-02 10:29:21 +04:00
|
|
|
# send the item.
|
2011-04-21 08:22:08 +04:00
|
|
|
headers = get_passthrough_headers(request)
|
2010-11-06 00:36:35 +03:00
|
|
|
try:
|
2011-04-21 08:22:08 +04:00
|
|
|
result, error = provider.api(acct).sendmessage(message, args,
|
|
|
|
headers)
|
2011-03-03 22:37:24 +03:00
|
|
|
except OAuthKeysException, e:
|
2011-02-09 08:49:00 +03:00
|
|
|
# XXX - I doubt we really want a full exception logged here?
|
2011-03-03 22:37:24 +03:00
|
|
|
#log.exception('error providing item to %s: %s', domain, e)
|
2010-11-06 00:36:35 +03:00
|
|
|
# XXX we need to handle this better, but if for some reason the
|
|
|
|
# oauth values are bad we will get a ValueError raised
|
|
|
|
error = {'provider': domain,
|
2011-03-31 23:09:24 +04:00
|
|
|
'message': ("not logged in or no user account "
|
|
|
|
"for that domain"),
|
2011-04-13 05:19:45 +04:00
|
|
|
'status': 401,
|
2010-11-06 00:36:35 +03:00
|
|
|
}
|
2011-03-24 15:55:49 +03:00
|
|
|
|
2011-03-03 22:37:24 +03:00
|
|
|
metrics.track(request, 'send-oauth-keys-missing', domain=domain)
|
2011-02-11 06:39:38 +03:00
|
|
|
timer.track('send-error', error=error)
|
2010-11-06 00:36:35 +03:00
|
|
|
return {'result': result, 'error': error}
|
2011-03-21 04:14:57 +03:00
|
|
|
except ServiceUnavailableException, e:
|
|
|
|
error = {'provider': domain,
|
2011-03-31 23:09:24 +04:00
|
|
|
'message': ("The service is temporarily unavailable "
|
|
|
|
"- please try again later."),
|
2011-04-13 05:19:45 +04:00
|
|
|
'status': 503,
|
2011-03-21 04:14:57 +03:00
|
|
|
}
|
|
|
|
if e.debug_message:
|
|
|
|
error['debug_message'] = e.debug_message
|
|
|
|
metrics.track(request, 'send-service-unavailable', domain=domain)
|
|
|
|
timer.track('send-error', error=error)
|
|
|
|
return {'result': result, 'error': error}
|
2010-09-02 10:29:21 +04:00
|
|
|
|
|
|
|
if error:
|
2011-02-11 06:39:38 +03:00
|
|
|
timer.track('send-error', error=error)
|
2010-09-02 10:29:21 +04:00
|
|
|
assert not result
|
2011-03-25 00:25:46 +03:00
|
|
|
#log.error("send failure: %r %r %r", username, userid, error)
|
2010-09-02 10:29:21 +04:00
|
|
|
else:
|
|
|
|
# create a new record in the history table.
|
|
|
|
assert result
|
2010-09-15 01:18:46 +04:00
|
|
|
result['shorturl'] = shorturl
|
|
|
|
result['from'] = userid
|
|
|
|
result['to'] = to
|
2011-02-11 06:39:38 +03:00
|
|
|
timer.track('send-success')
|
2010-09-02 10:29:21 +04:00
|
|
|
# no redirects requests, just return the response.
|
|
|
|
return {'result': result, 'error': error}
|