PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/app/controllers/sns.py

https://bitbucket.org/liutaihua/yyu
Python | 391 lines | 386 code | 3 blank | 2 comment | 0 complexity | 47e4ab2d7fdabf5f0ac5c265d081def9 MD5 | raw file
  1. #!/usr/bin/env python
  2. # coding: utf-8
  3. import web
  4. import httplib2
  5. import config
  6. import datetime
  7. import urllib
  8. import collections
  9. from config import view, site_name, db
  10. from app.common import session
  11. from app.models import users
  12. siteName = site_name
  13. u = session.get_session()
  14. def httplib2_request(uri, method="GET", body='', headers=None,
  15. redirections=httplib2.DEFAULT_MAX_REDIRECTS,
  16. connection_type=None, disable_ssl_certificate_validation=True):
  17. DEFAULT_POST_CONTENT_TYPE = 'application/x-www-form-urlencoded'
  18. if not isinstance(headers, dict):
  19. headers = {}
  20. if method == "POST":
  21. headers['Content-Type'] = headers.get('Content-Type',
  22. DEFAULT_POST_CONTENT_TYPE)
  23. return httplib2.Http(disable_ssl_certificate_validation=disable_ssl_certificate_validation).\
  24. request(uri, method=method, body=body,
  25. headers=headers, redirections=redirections,
  26. connection_type=connection_type)
  27. class OAuth2Login(object):
  28. version = '2.0'
  29. authorize_uri = ''
  30. access_token_uri = ''
  31. def __init__(self, apikey, apikey_secret, redirect_uri,
  32. scope=None, state=None, display=None):
  33. self.apikey = apikey
  34. self.apikey_secret = apikey_secret
  35. self.redirect_uri = redirect_uri
  36. self.scope = scope
  37. self.state = state
  38. self.display = display
  39. def get_login_uri(self):
  40. qs = {
  41. 'client_id' : self.apikey,
  42. 'response_type' : 'code',
  43. 'redirect_uri' : self.redirect_uri,
  44. }
  45. if self.display:
  46. qs['display'] = self.display
  47. if self.scope:
  48. qs['scope'] = self.scope
  49. if self.state:
  50. qs['state'] = self.state
  51. qs = urllib.urlencode(qs)
  52. uri = '%s?%s' %(self.authorize_uri, qs)
  53. return uri
  54. def get_access_token(self, authorization_code):
  55. qs = {
  56. "client_id": self.apikey,
  57. "client_secret": self.apikey_secret,
  58. "redirect_uri": self.redirect_uri,
  59. "grant_type": "authorization_code",
  60. "code": authorization_code,
  61. }
  62. qs = urllib.urlencode(qs)
  63. resp, content = httplib2_request(self.access_token_uri, "POST", body=qs)
  64. if resp.status != 200:
  65. return view.error404('Connection failed') #note:need to change view name "error404"
  66. #raise OAuthLoginError('get_access_token, status=%s:reason=%s:content=%s' \
  67. # %(resp.status, resp.reason, content))
  68. return json_decode(content)
  69. class DoubanLogin(OAuth2Login):
  70. provider = config.OPENID_DOUBAN
  71. authorize_uri = 'https://www.douban.com/service/auth2/auth'
  72. access_token_uri = 'https://www.douban.com/service/auth2/token'
  73. user_info_uri = 'https://api.douban.com/v2/user/~me'
  74. def __init__(self, apikey, apikey_secret, redirect_uri,
  75. scope=None, state=None, display=None):
  76. super(DoubanLogin, self).__init__(apikey, apikey_secret, redirect_uri, scope)
  77. def get_user_info(self, access_token, uid=None):
  78. headers = {"Authorization": "Bearer %s" % access_token}
  79. qs = {
  80. "alt":"json",
  81. }
  82. uri = "%s?%s" %(self.user_info_uri, urllib.urlencode(qs))
  83. resp, content = httplib2_request(uri, "GET",
  84. headers = headers)
  85. if resp.status != 200:
  86. print "========error connect author douban ============",resp.status, content
  87. return False
  88. #return view.error404('Connection failed') #note:need to change view name "error404"
  89. # raise OAuthLoginError('get_access_token, status=%s:reason=%s:content=%s' \
  90. # %(resp.status, resp.reason, content))
  91. r = json_decode(content)
  92. user_info = DoubanUser(r)
  93. return r
  94. class OAuthLoginError(Exception):
  95. def __init__(self, msg):
  96. # if isinstance(msg, TweepError):
  97. # self.msg = "%s:%s" %(msg.reason, msg.response)
  98. # else:
  99. # self.msg = msg
  100. self.msg = msg
  101. def __str__(self):
  102. return "%s" % (self.msg,)
  103. __repr__ = __str__
  104. #-----
  105. try:
  106. import json
  107. assert hasattr(json, "loads") and hasattr(json, "dumps")
  108. _json_decode = json.loads
  109. _json_encode = json.dumps
  110. except Exception:
  111. try:
  112. import simplejson
  113. _json_decode = lambda s: simplejson.loads(_unicode(s))
  114. _json_encode = lambda v: simplejson.dumps(v)
  115. except ImportError:
  116. try:
  117. # For Google AppEngine
  118. from django.utils import simplejson
  119. _json_decode = lambda s: simplejson.loads(_unicode(s))
  120. _json_encode = lambda v: simplejson.dumps(v)
  121. except ImportError:
  122. def _json_decode(s):
  123. raise NotImplementedError(
  124. "A JSON parser is required, e.g., simplejson at "
  125. "http://pypi.python.org/pypi/simplejson/")
  126. _json_encode = _json_decode
  127. #----
  128. def json_decode(value):
  129. """Returns Python objects for the given JSON string."""
  130. return _json_decode(to_basestring(value))
  131. _BASESTRING_TYPES = (basestring, type(None))
  132. def to_basestring(value):
  133. """Converts a string argument to a subclass of basestring.
  134. In python2, byte and unicode strings are mostly interchangeable,
  135. so functions that deal with a user-supplied argument in combination
  136. with ascii string constants can use either and should return the type
  137. the user supplied. In python3, the two types are not interchangeable,
  138. so this method is needed to convert byte strings to unicode.
  139. """
  140. if isinstance(value, _BASESTRING_TYPES):
  141. return value
  142. assert isinstance(value, bytes)
  143. return value.decode("utf-8")
  144. class Douban:
  145. def GET(self):
  146. data = web.input()
  147. if data.has_key('code'):
  148. code = data.code
  149. provider = 'douban'
  150. d = config.APIKEY_DICT.get(provider)
  151. login_service = None
  152. if provider == config.OPENID_DOUBAN:
  153. openid_type = config.OPENID_TYPE_DICT[config.OPENID_DOUBAN]
  154. douban_login = DoubanLogin(d['key'], d['secret'], d['redirect_uri'])
  155. # elif provider == config.OPENID_SINA:
  156. # openid_type = config.OPENID_TYPE_DICT[config.OPENID_SINA]
  157. # login_service = SinaLogin(d['key'], d['secret'], d['redirect_uri'])
  158. # else:
  159. # ## 处理以oauth1的方式授权的
  160. # if provider == config.OPENID_QQ:
  161. # user = _qqweibo_callback(request)
  162. # elif provider == config.OPENID_TWITTER:
  163. # user = _twitter_callback(request)
  164. # if user:
  165. # _add_sync_task_and_push_queue(provider, user)
  166. # return redirect(url_for('index'))
  167. # else:
  168. # return "connect to %s fail" % provider
  169. token_dict = douban_login.get_access_token(code)
  170. if not token_dict or not token_dict.get("access_token"):
  171. return(401, "no_access_token")
  172. user_info = douban_login.get_user_info(token_dict.get("access_token"), token_dict.get("uid"))
  173. if user_info:
  174. douban_id = user_info['id']
  175. nickname = user_info[u'name']
  176. avatarPath = user_info['avatar']
  177. #判断邮箱激活表中是否有此豆瓣ID
  178. if users.douban_id_exist_in_table_confirm_email(int(douban_id)):
  179. #如果此用户填写过email
  180. if users.get_confirm_email_by_douban_id(douban_id).email:
  181. info = users.get_confirm_email_by_douban_id(douban_id)
  182. c = info.confirmed
  183. #如果填写的邮箱已经验证
  184. if c == 1:
  185. #更新用户邮箱 昵称 等资料
  186. users.update_user_by_douid(
  187. douban_id,
  188. nickname = nickname,
  189. avatarPath = avatarPath,
  190. nicknameChangeTime = datetime.datetime.now(),
  191. lastLoginIP = web.ctx.ip,
  192. lastLoginTime = datetime.datetime.now()
  193. )
  194. # last_user_id = db.query("SELECT LAST_INSERT_ID()")[0].values()[0]
  195. last_user_id = users.get_douban_user_by_doubanid(douban_id).id
  196. city = user_info.get('loc_name')
  197. desc = user_info.get('desc')
  198. users.update_profile(last_user_id, city = city, bio = desc )
  199. session.douban_login(douban_id)
  200. raise web.seeother(session.get_last_visited_url())
  201. elif c == 0:
  202. session.douban_callback(user_info)
  203. #返回 提醒用户需要激活邮件 的页面
  204. raise web.seeother('/welcome/'+ user_info['uid'] +'/send_email_feedback?status=succesful')
  205. #如果没填写email
  206. else:
  207. session.douban_callback(user_info)
  208. #删除表中的记录 为了一会儿重新insert
  209. users.del_verification_data_by_douban_id(douban_id)
  210. #跳转到邮箱设置页面
  211. raise web.seeother('/welcome/'+ user_info['uid'])
  212. #如果是新用户
  213. else:
  214. session.douban_callback(user_info)
  215. #跳转到邮箱设置页面
  216. raise web.seeother('/welcome/'+ user_info['uid'])
  217. # #判断用户表中是否已有此douban_id如果已经存在此用户
  218. # if users.get_douban_user_by_doubanid(douban_id):
  219. # print '1111111111111111'
  220. # douban_user = users.get_douban_user_by_doubanid(douban_id)
  221. # #如果已经填写了邮箱地址
  222. # if douban_user.email:
  223. # print '222222222222'
  224. # email = douban_user.email
  225. # #查询邮箱验证记录
  226. # e = users.get_confirm_email_by_email(email).get('confirmed')
  227. # #已验证邮箱登录
  228. # if e == 1:
  229. # print '33333333333333'
  230. # session.douban_login(douban_id)
  231. # raise web.seeother(session.get_last_visited_url())
  232. # #未验证邮箱,跳转到邮箱验证页面
  233. # elif e == 0:
  234. # print '4444444444444444'
  235. # #先把user_info信息放到 session 供跳转后取出使用
  236. # session.douban_callback(user_info)
  237. # raise web.seeother('/welcome/'+ user_info['uid'] +'confirm_email')
  238. # #如果未填写邮箱地址
  239. # else:
  240. # print '55555555555555'
  241. # #先把user_info信息放到 session 供跳转后取出使用
  242. # session.douban_callback(user_info)
  243. # #跳转到邮箱设置页面
  244. # raise web.seeother('/welcome/'+ user_info['uid'])
  245. # #如果用户表中没有此用户
  246. # else:
  247. # #先把user_info信息放到 session 供跳转后取出使用
  248. # session.douban_callback(user_info)
  249. # #跳转到邮箱设置页面
  250. # raise web.seeother('/welcome/'+ user_info['uid'])
  251. else:
  252. return view.error404('Connection failed')
  253. else:
  254. return view.error404('Connection failed')
  255. #connect_douban
  256. class connect_douban:
  257. def GET(self):
  258. provider = 'douban'
  259. d = config.APIKEY_DICT.get(provider)
  260. raise web.seeother('https://www.douban.com/service/auth2/auth?client_id='+ d['key'] +'&redirect_uri='+ d['redirect_uri'] +'&response_type=code')
  261. class connect_sina:
  262. def GET(self):
  263. provider = 'sina'
  264. d = config.APIKEY_DICT.get(provider)
  265. client = APIClient(app_key=d['key'], app_secret=d['secret'], redirect_uri=d['redirect_uri'])
  266. url = client.get_authorize_url()
  267. raise web.seeother(url)
  268. ## User数据接口
  269. class AbsUserData(object):
  270. def __init__(self, data):
  271. if data:
  272. self.data = data
  273. else:
  274. self.data = {}
  275. if isinstance(data, basestring):
  276. self.data = json_decode(data)
  277. def get_user_id(self):
  278. raise NotImplementedError
  279. def get_uid(self):
  280. raise NotImplementedError
  281. def get_nickname(self):
  282. return ""
  283. def get_intro(self):
  284. return ""
  285. def get_signature(self):
  286. return ""
  287. def get_avatar(self):
  288. return ""
  289. def get_icon(self):
  290. return ""
  291. def get_email(self):
  292. return ""
  293. ## 豆瓣user数据接口
  294. class DoubanUser(AbsUserData):
  295. def __init__(self, data):
  296. super(DoubanUser, self).__init__(data)
  297. def get_user_id(self):
  298. id_ = self.data.get("id", {}).get("$t")
  299. if id_:
  300. return (id_.rstrip("/").split("/"))[-1]
  301. return None
  302. def get_uid(self):
  303. return self.data.get("uid", {}).get("$t")
  304. def get_nickname(self):
  305. return self.data.get("title", {}).get("$t")
  306. def get_intro(self):
  307. return self.data.get("content", {}).get("$t")
  308. def get_signature(self):
  309. return self.data.get("signature", {}).get("$t")
  310. def get_avatar(self):
  311. icon = self.get_icon()
  312. user_id = self.get_user_id()
  313. return icon.replace(user_id, "l%s" % user_id)
  314. def get_icon(self):
  315. links = {}
  316. _links = self.data.get("link", [])
  317. for x in _links:
  318. rel = x.get("@rel")
  319. links[rel] = x.get("@href")
  320. return links.get("icon", "")