def is_contain(self, userid, target_userid): """ 二者間でのブラックリストチェック userid が target_userid をブラックリスト登録してるか? """ path = '/blacklist/%s/@all/%s' % (str(userid), str(target_userid)) # ブラックリスト登録してない(データがない)と例外 404 try: requestor_id = self.request.osuser.userid self.container.oauth_request('GET', requestor_id, path) #oauth_request は、例外を出さなくなった Log.debug("blacklist2 latest_error_code = %s" % self.latest_error_code); if self.latest_error_code == None: data = True Log.debug('Blacklist True. (None)') elif self.latest_error_code == 200: data = True Log.debug('Blacklist True. (200)') elif self.latest_error_code == 404: data = False Log.debug('Blacklist False.(404)') else: data = False Log.error('blacklist2 unexpected error code.') except: data = False Log.debug('Blacklist False. (except)') return data
def is_contain(self, userid, target_userid): """ 二者間でのブラックリストチェック userid が target_userid をブラックリスト登録してるか? """ path = '/blacklist/%s/@all/%s' % (str(userid), str(target_userid)) # ブラックリスト登録してない(データがない)と例外 404 try: requestor_id = self.request.osuser.userid self.container.oauth_request('GET', requestor_id, path) #oauth_request は、例外を出さなくなった Log.debug("blacklist2 latest_error_code = %s" % self.latest_error_code) if self.latest_error_code == None: data = True Log.debug('Blacklist True. (None)') elif self.latest_error_code == 200: data = True Log.debug('Blacklist True. (200)') elif self.latest_error_code == 404: data = False Log.debug('Blacklist False.(404)') else: data = False Log.error('blacklist2 unexpected error code.') except: data = False Log.debug('Blacklist False. (except)') return data
def get_myself_data(self, userid, fields=None, caching=True, cache_update=None): """ アプリを利用しているユーザー本人の情報を取得する 任意でキャッシュできる(デフォルトではキャッシュする) Get the information of user. You can use caching(default will do it) """ path = '/people/%s/@self' % userid cache_key = path data = None if caching: data = GsocialCache.get_cache(cache_key) #print 'cache:', data # dataが空の時、もしくは、キャッシュを更新したい時 if data == None or cache_update == True: #print 'not cache:', data #print 'cache_update:', cache_update params = {} if fields: params['fields'] = fields res = self.get_response(userid, path, params) Log.debug('Debug.', res) if res: try: data = simplejson.loads(res) if caching: GsocialCache.set_cache(cache_key, data) except TypeError: Log.error(self.LOG_MSG2, [userid, path, res]) try: data = simplejson.loads(unicode( res, "utf-8", "ignore")) if caching: GsocialCache.set_cache(cache_key, data) except TypeError: data = None Log.error(self.LOG_MSG3, [userid, path, res]) except Exception: data = None Log.error(self.LOG_MSG1, [userid, path, res]) except Exception: data = None Log.error(self.LOG_MSG1, [userid, path, res]) else: data = None Log.error(self.LOG_MSG4, [userid, path]) return data
def get_friends_page(self, userid, has_app=True, fields=None, page=1, limit=10): """ アプリを利用しているユーザーの友達情報を指定件数分返す 件数指定がない場合は10件 キャッシュはしない Return specified amount of the user`s friend information.By default,it will return 10 friends information. No caching. """ path = '/people/%s/@friends' % userid params = {'format': 'json'} params['count'] = limit params['startIndex'] = 1 + limit * (page - 1) data = None if fields: params['fields'] = fields if has_app: params['filterBy'] = 'hasApp' params['filterOp'] = 'equals' params['filterValue'] = 'true' res = self.get_response(userid, path, params=params) if res: try: data = simplejson.loads(res) except TypeError: Log.error(LOG_MSG2, [userid, path, res]) try: data = simplejson.loads(unicode(res, "utf-8", "ignore")) except TypeError: Log.error(LOG_MSG3, [userid, path, res]) except Exception: Log.error(LOG_MSG1, [userid, path, res]) except Exception: Log.error(LOG_MSG1, [userid, path, res]) else: Log.error(LOG_MSG4, [userid, path, res]) if data == None: data = { 'error': True, 'entry': [], 'totalResults': '0', 'itemsPerPage': '0', 'startIndex': '1' } return data
def get_myself_data(self, userid, fields=None, caching=True, cache_update=None): """ アプリを利用しているユーザー本人の情報を取得する 任意でキャッシュできる(デフォルトではキャッシュする) Get the information of user. You can use caching(default will do it) """ path = '/people/%s/@self' % userid cache_key = path data = None if caching: data = GsocialCache.get_cache(cache_key) #print 'cache:', data # dataが空の時、もしくは、キャッシュを更新したい時 if data == None or cache_update == True: #print 'not cache:', data #print 'cache_update:', cache_update params = {} if fields: params['fields'] = fields res = self.get_response(userid, path, params) Log.debug('Debug.', res) if res: try: data = simplejson.loads(res) if caching: GsocialCache.set_cache(cache_key, data) except TypeError: Log.error(self.LOG_MSG2, [userid, path, res]) try: data = simplejson.loads(unicode(res, "utf-8", "ignore")) if caching: GsocialCache.set_cache(cache_key, data) except TypeError: data = None Log.error(self.LOG_MSG3, [userid, path, res]) except Exception: data = None Log.error(self.LOG_MSG1, [userid, path, res]) except Exception: data = None Log.error(self.LOG_MSG1, [userid, path, res]) else: data = None Log.error(self.LOG_MSG4, [userid, path]) return data
def get_friends_page(self, userid, has_app=True, fields=None, page=1, limit=10): """ アプリを利用しているユーザーの友達情報を指定件数分返す 件数指定がない場合は10件 キャッシュはしない Return specified amount of the user`s friend information.By default,it will return 10 friends information. No caching. """ path = '/people/%s/@friends' % userid params = {'format': 'json'} params['count'] = limit params['startIndex'] = 1 + limit * (page - 1) data = None if fields: params['fields'] = fields if has_app: params['filterBy'] = 'hasApp' params['filterOp'] = 'equals' params['filterValue'] = 'true' res = self.get_response(userid, path, params=params) if res: try: data = simplejson.loads(res) except TypeError: Log.error(LOG_MSG2, [userid, path, res]) try: data = simplejson.loads(unicode(res, "utf-8", "ignore")) except TypeError: Log.error(LOG_MSG3, [userid, path, res]) except Exception: Log.error(LOG_MSG1, [userid, path, res]) except Exception: Log.error(LOG_MSG1, [userid, path, res]) else: Log.error(LOG_MSG4, [userid, path, res]) if data == None: data = {'error': True, 'entry': [], 'totalResults': '0', 'itemsPerPage': '0', 'startIndex': '1' } return data
def get_friend_data(self, userid, friend_userid, has_app=True, fields=None): """ アプリを利用しているユーザーのID指定した友達の情報を取得する キャッシュはしない Get the information of user`s friend with specified ID. No caching. """ path = '/people/%s/@friends/%s' % (userid, friend_userid) params = {'format': 'json'} if fields: params['fields'] = fields if has_app: params['filterBy'] = 'hasApp' res = self.get_response(userid, path, params) if res: try: data = simplejson.loads(res) except TypeError: Log.error(self.LOG_MSG2, [userid, path, res]) try: data = simplejson.loads(unicode(res, "utf-8", "ignore")) except TypeError: data = None Log.error(self.LOG_MSG3, [userid, path, res]) except Exception: data = None Log.error(self.LOG_MSG1, [userid, path, res]) except Exception: data = None Log.error(self.LOG_MSG1, [userid, path, res]) else: Log.error(self.LOG_MSG4, [userid, path, res]) data = {'error': True, 'entry': []} Log.debug('Check data for debug.', [userid, data]) return data
def get_friend_data(self, userid, friend_userid, has_app=True, fields=None): """ アプリを利用しているユーザーのID指定した友達の情報を取得する キャッシュはしない Get the information of user`s friend with specified ID. No caching. """ path = '/people/%s/@friends/%s' % (userid, friend_userid) params = {'format' : 'json'} if fields: params['fields'] = fields if has_app: params['filterBy'] = 'hasApp' res = self.get_response(userid, path, params) if res: try: data = simplejson.loads(res) except TypeError: Log.error(self.LOG_MSG2, [userid, path, res]) try: data = simplejson.loads(unicode(res, "utf-8", "ignore")) except TypeError: data = None Log.error(self.LOG_MSG3, [userid, path, res]) except Exception: data = None Log.error(self.LOG_MSG1, [userid, path, res]) except Exception: data = None Log.error(self.LOG_MSG1, [userid, path, res]) else: Log.error(self.LOG_MSG4, [userid, path, res]) data = {'error':True, 'entry':[]} Log.debug('Check data for debug.', [userid, data]) return data
def blacklist_check(self, userid, target_userid, caching=False, cache_update=None): """ 二者間でのブラックリストチェック userid が target_userid をブラックリスト登録してるか? 任意でキャッシュできる(デフォルトではキャッシュしない) (GREE規約上、ブラックリストは24時間キャッシュできるようだが、しない) 引数 userid target_userid caching cache_update 返り値 is_data : Trueなら、ブラックリストに登録している Falseなら、ブラックリストに登録されていない "Blacklist checking" between the two persons:whether the "userid" has registered "target_userid" for blacklist? You can cache it if you want(but by default you can`t cache it) arguments userid target_userid caching cache_update return value is_data : if True,registerd on blacklist if False,not registerd on blacklist """ from django.conf import settings if settings.OPENSOCIAL_DEBUG: return False #requestor_id = self.container.request.osuser.userid path = '/ignorelist/%s/@all/%s/' % (str(userid), str(target_userid)) cache_key = path data = [] # test #cache_update = True if caching and cache_update == False: is_data = GsocialCache.get_cache(cache_key) #print 'cache', is_data if is_data != None: return is_data for retry_count in xrange(self.RETRY_COUNT): try: res = self.get_response(userid, path) #res = self.get_response(requestor_id, path) data = simplejson.loads(res) break except TypeError: Log.warn('Blacklist: response type error. retry:%s' % retry_count) continue except Exception: Log.warn('Blacklist: response error. retry:%s' % retry_count) continue Log.debug(data) if not data: Log.error("Blacklist: not data.") raise self.container.ResponseError('Blacklist API', 'Get ignorelist (gree).') if 'entry' in data and data['entry']: is_data = True else: is_data = False #print 'no cache', is_data if caching: GsocialCache.set_cache(cache_key, is_data) return is_data
def get_friends(self, userid, has_app=True, fields=None): """ アプリを利用しているユーザーの友達情報を返す 友達情報を100件毎に取得し、最大1000件(100*10)取得する キャッシュはしない Return the information of user`s friends. Get 100 friends information each time,and at maximum you could get 1000 information(100*10). No caching. """ path = '/people/%s/@friends' % userid params = {'format': 'json', 'count': '1000'} data = None # GREEでは最大100件まで指定可能 params['count'] = 100 # リクエスト回数デフォルト値(ただし1回目リクエスト時のtotalResultsの値に書き換える) range_max = 2 total_data = None if fields: params['fields'] = fields if has_app: params['filterBy'] = 'hasApp' params['filterOp'] = 'equals' params['filterValue'] = 'true' for i in range(range_max): params['startIndex'] = params['count'] * i res = self.get_response(userid, path, params) if res: try: data = simplejson.loads(res) # totalResults==0(友達がいない)、もしくは、rangeを超えた時 if int(data['totalResults']) == 0 or i >= range_max - 1: data = total_data break else: # for文1回目(total_dataにデータが入っていない時) if not total_data: # 友達数(totalResults)を取得出来るので、range_maxを書き換え range_max = int(data['totalResults']) / 100 total_data = data total_data['totalResults'] = int( total_data['totalResults']) total_data['itemsPerPage'] = int( total_data['itemsPerPage']) # for文2回目以降 else: total_data['totalResults'] += data['totalResults'] total_data['itemsPerPage'] += data['itemsPerPage'] total_data['entry'] += data['entry'] # list except TypeError: Log.error(LOG_MSG2, [userid, path, res]) try: data = simplejson.loads(unicode( res, "utf-8", "ignore")) # totalResults==0(友達がいない) if int(data['totalResults']) == 0: data = total_data else: # for文1回目(total_dataにデータが入っていない時) if not total_data: total_data = data total_data['totalResults'] = int( total_data['totalResults']) total_data['itemsPerPage'] = int( total_data['itemsPerPage']) # for文2回目以降 else: total_data['totalResults'] += int( data['totalResults']) total_data['itemsPerPage'] += int( data['itemsPerPage']) total_data['entry'] += data['entry'] # list except TypeError: Log.error(LOG_MSG3, [userid, path, res]) break except Exception: Log.error(LOG_MSG1, [userid, path, res]) break except Exception: Log.error(LOG_MSG1, [userid, path, res]) break else: Log.error(LOG_MSG4, [userid, path]) break else: data = total_data if data == None: data = { 'error': True, 'entry': [], 'totalResults': '0', 'itemsPerPage': '0' } return data
Log.info('local_hash1', binascii.b2a_base64(local_hash1)[:-1]) Log.info('local_hash2', binascii.b2a_base64(local_hash2)[:-1]) Log.info('local_hash1 == remote_hash ?', (local_hash1 == remote_hash)) Log.info('local_hash2 == remote_hash ?', (local_hash2 == remote_hash)) if local_hash1 != remote_hash and local_hash2 != remote_hash: raise except Error, err: Log.error('oauth error', err.message) return HttpResponseNotAuthorized(request.get_full_path()) except: import sys exceptionType, exceptionValue, exceptionTraceback = sys.exc_info() Log.error('Invalid OAuth Signature.', [exceptionType, exceptionValue]) Log.error('HTTP_AUTHORIZATION', auth_string) return HttpResponseNotAuthorized(request.get_full_path()) else: opensocial_owner_id = request.REQUEST.get('opensocial_owner_id', None) if opensocial_owner_id is not None: request.opensocial_userid = str(opensocial_owner_id) request.opensocial_viewer_id = str(opensocial_owner_id) return None def _verify_sign_header(request): """ OAuth checking of header output authorization ok :None
def _verify_sign_mobile(request): """ Oauth checking process for FP output authorization ok :None with error : redirect to request.get_full_path else: raise FP用のOAUTH認証処理 output 認証ok: None error時: request.get_full_pathへのリダイレクト それ以外: raise """ Log.debug("[Method] _verify_sign_mobile") request.opensocial_container = containerdata # header_params = {} # oauth_signature = request.REQUEST.get('oauth_signature', None) auth_string = '' try: auth_string = request.META.get('HTTP_AUTHORIZATION', '') auth_string = auth_string.replace('OAuth ', '') Log.debug('HTTP_AUTHORIZATION', auth_string) params = {} remote_hash = False for param in auth_string.split(','): Log.debug('param', param) (key, value) = param.strip().split('=', 1) value = value.strip('"').encode('utf-8') if key == 'oauth_signature': remote_hash = base64.decodestring(urllib.unquote(value)) elif key and key != 'OAuth realm' and key != 'realm': params[key] = value Log.debug('params', params) if not remote_hash: raise oauth_token_secret = params.get('oauth_token_secret', '') # Some container only need query parameter to create base_string # while some need postdata as well,so you create both hash pattern. # As one of them matches,checking will be passed. # コンテナによって、base_stringを作成するのにクエリパラメータのみを使うもの、 # postdataも含めるものがあるので、両方のパターンのハッシュを作り # どちらかがマッチすれば認証OKとする。 encoding = request.encoding if not encoding: encoding = 'utf-8' for key, value in request.GET.items(): if key and key != 'oauth_signature': params[key] = value.encode(encoding) Log.debug('params', params) #local_hash1 = local_hash2 = u'' #create hash by only using query parameter. # クエリパラメータのみを使ってハッシュを作成 local_hash1 = create_hmac_hash(request, params, oauth_token_secret) #create hash with using parameter contain POSTDATA. # POSTDATAも含めたパラメータを使ってハッシュを作成 post_param = generate_post_hash(request, encoding) params.update(post_param) local_hash2 = create_hmac_hash(request, params, oauth_token_secret) host = request.get_host() host = host.split(',')[0] base_url = request.is_secure() and 'https://' or 'http://' + host + request.path Log.info('base_url', base_url) for k, v in params.iteritems(): if isinstance(v, basestring): Log.info('Check k and v.decode(encoding) of params.iteritems()', [k, v.decode(encoding)]) else: Log.info('Check k and v of params.iteritems()', [k, v]) Log.info('raw', request.raw_post_data) Log.info('remote_hash', binascii.b2a_base64(remote_hash)[:-1]) Log.info('local_hash1', binascii.b2a_base64(local_hash1)[:-1]) Log.info('local_hash2', binascii.b2a_base64(local_hash2)[:-1]) Log.info('local_hash1 == remote_hash ?', (local_hash1 == remote_hash)) Log.info('local_hash2 == remote_hash ?', (local_hash2 == remote_hash)) if local_hash1 != remote_hash and local_hash2 != remote_hash: raise except Error, err: Log.error('oauth error', err.message) return HttpResponseNotAuthorized(request.get_full_path())
Log.info('local_hash1', binascii.b2a_base64(local_hash1)[:-1]) Log.info('local_hash2', binascii.b2a_base64(local_hash2)[:-1]) Log.info('local_hash1 == remote_hash ?', (local_hash1 == remote_hash)) Log.info('local_hash2 == remote_hash ?', (local_hash2 == remote_hash)) if local_hash1 != remote_hash and local_hash2 != remote_hash: raise except Error, err: Log.error('oauth error', err.message) return HttpResponseNotAuthorized(request.get_full_path()) except: import sys exceptionType, exceptionValue, exceptionTraceback = sys.exc_info() Log.error('Invalid OAuth Signature.', [exceptionType, exceptionValue]) Log.error('HTTP_AUTHORIZATION', auth_string) return HttpResponseNotAuthorized(request.get_full_path()) else: opensocial_owner_id = request.REQUEST.get('opensocial_owner_id', None) if opensocial_owner_id is not None: request.opensocial_userid = str(opensocial_owner_id) request.opensocial_viewer_id = str(opensocial_owner_id) return None def _verify_sign_header(request): """ OAuth checking of header output authorization ok :None else: raise
def get_request_form( request_users, submit_value, title, body, callbackurl, mobile_url, touch_url, option_params={} ): u""" リクエストサービスのフォームを生成し、返す フィーチャーフォン版 外部テンプレート: gsocial/templates/opensocial/request.html 使い方:: {% get_request_form <request_users> <submit_value> <title> <body> <callbackurl> <mobile_url> <touch_url> <option_params> %} 引数: :request_users: リクエストを送信したいユーザリスト (to_user_id[]に渡すパラメータ) :submit_value: 送信ボタンの文言 :title: リクエストのタイトル(必須) :body: 本文 :callbackurl: リクエストした後に遷移するURL :mobile_url: リクエストをユーザがクリックした際の飛び先のURL(FP) :touch_url: リクエストをユーザがクリックした際の飛び先のURL(SP) :option_params: オプションディクショナリ option_params: :backto_url: リクエスト送信確認画面からアプリへ戻るためのURL :mobile_image: メッセージに含める画像のURL(FP) :touch_image: メッセージに含める画像のURL(SP) :list_type: リクエストの対象となるユーザの種別 :editable: メッセージをユーザに入力させる :expire_time: リクエストが期限切れとなる日時(UTC FORMAT) Create the form for the request service and return it.(For FP) Customize the following source cord with your own designs of the forms. Arguments: :request_users: A Userlist whom you want to send request.(A parameter to be handed to to_user_id[]) :submit_value: A letter on submit botton :title: The title of request(indispensable) :body: Message :callbackurl: A URL which will be redirected after the request. :mobile_url: A URL which will be redirected after the click(FP). :touch_url: A URL which will be redirected after the click(SP). :option_params: a optional dictionary option_params: :backto_url: A URL of the application from the "request sent confirmation"screen :mobile_image: URL of the image which will be contain in the message(FP) :touch_image: URL of the image which will be contain in the message(SP) :list_type: The type of subjected users. :editable: Whether User is allowed to edit or not. :expire_time: The expire date of the request(UTC FORMAT) """ # checks the content of option_params # option_paramsの中身をチェック # TODO : もっと綺麗にしたい keys = option_params.keys() backto_url = option_params['backto_url'] if 'backto_url' in keys else None mobile_image = option_params['mobile_image'] if 'mobile_image' in keys else None touch_image = option_params['touch_image'] if 'touch_image' in keys else None list_type = option_params['list_type'] if 'list_type' in keys else None editable = option_params['editable'] if 'editable' in keys else None expire_time = option_params['expire_time'] if 'expire_time' in keys else None # title is indispensable,so check. # titleは必須のため、チェック if not title: Log.error('title is empty.', body) raise # if list_type was not setted,use "specified" # list_typeの指定が無かった場合、specifiedを指定する if list_type == None: list_type = 'specified' # body is indispensable when editable is True,so check # bodyはeditableがtrueでない場合は必須のため、チェック # TODO : editable==Trueの場合、メッセージをユーザに入力させる # そのため、フォーム生成のhtml側で、入力フォームを生成する必要がある if editable != True: if body == None: Log.error('body is empty.', body) raise if request_users: temp = [] for user in request_users: user_params = {} user_params['id'] = user['id'] if 'id' in user else None user_params['nickname'] = user['nickname'] if 'nickname' in user else None user_params['thumbnail'] = user['thumbnail'] if 'thumbnail' in user else None temp.append(user_params) return { 'request_users': temp, 'submit_value': submit_value, 'title': title, 'body': body, 'callbackurl': callbackurl, 'mobile_url': mobile_url, 'touch_url': touch_url, 'backto_url': backto_url, 'mobile_image': mobile_image, 'touch_image': touch_image, 'list_type': list_type, 'editable': editable, 'expire_time': expire_time, }
def blacklist_check(self, userid, target_userid, caching=False, cache_update=None): """ 二者間でのブラックリストチェック userid が target_userid をブラックリスト登録してるか? 任意でキャッシュできる(デフォルトではキャッシュしない) (GREE規約上、ブラックリストは24時間キャッシュできるようだが、しない) 引数 userid target_userid caching cache_update 返り値 is_data : Trueなら、ブラックリストに登録している Falseなら、ブラックリストに登録されていない "Blacklist checking" between the two persons:whether the "userid" has registered "target_userid" for blacklist? You can cache it if you want(but by default you can`t cache it) arguments userid target_userid caching cache_update return value is_data : if True,registerd on blacklist if False,not registerd on blacklist """ from django.conf import settings if settings.OPENSOCIAL_DEBUG: return False #requestor_id = self.container.request.osuser.userid path = '/ignorelist/%s/@all/%s/' % (str(userid), str(target_userid)) cache_key = path data = [] # test #cache_update = True if caching and cache_update == False: is_data = GsocialCache.get_cache(cache_key) #print 'cache', is_data if is_data != None: return is_data for retry_count in xrange(self.RETRY_COUNT): try: res = self.get_response(userid, path) #res = self.get_response(requestor_id, path) data = simplejson.loads(res) break except TypeError: Log.warn('Blacklist: response type error. retry:%s' % retry_count) continue except Exception: Log.warn('Blacklist: response error. retry:%s' % retry_count) continue Log.debug(data) if not data: Log.error("Blacklist: not data.") raise self.container.ResponseError('Blacklist API','Get ignorelist (gree).') if 'entry' in data and data['entry']: is_data = True else: is_data = False #print 'no cache', is_data if caching: GsocialCache.set_cache(cache_key, is_data) return is_data
def _verify_sign_mobile(request): """ Oauth checking process for FP output authorization ok :None with error : redirect to request.get_full_path else: raise FP用のOAUTH認証処理 output 認証ok: None error時: request.get_full_pathへのリダイレクト それ以外: raise """ Log.debug("[Method] _verify_sign_mobile") request.opensocial_container = containerdata # header_params = {} # oauth_signature = request.REQUEST.get('oauth_signature', None) auth_string = '' try: auth_string = request.META.get('HTTP_AUTHORIZATION', '') auth_string = auth_string.replace('OAuth ', '') Log.debug('HTTP_AUTHORIZATION', auth_string) params = {} remote_hash = False for param in auth_string.split(','): Log.debug('param', param) (key, value) = param.strip().split('=', 1) value = value.strip('"').encode('utf-8') if key == 'oauth_signature': remote_hash = base64.decodestring(urllib.unquote(value)) elif key and key != 'OAuth realm' and key != 'realm': params[key] = value Log.debug('params', params) if not remote_hash: raise oauth_token_secret = params.get('oauth_token_secret', '') # Some container only need query parameter to create base_string # while some need postdata as well,so you create both hash pattern. # As one of them matches,checking will be passed. # コンテナによって、base_stringを作成するのにクエリパラメータのみを使うもの、 # postdataも含めるものがあるので、両方のパターンのハッシュを作り # どちらかがマッチすれば認証OKとする。 encoding = request.encoding if not encoding: encoding = 'utf-8' for key, value in request.GET.items(): if key and key != 'oauth_signature': params[key] = value.encode(encoding) Log.debug('params', params) #local_hash1 = local_hash2 = u'' #create hash by only using query parameter. # クエリパラメータのみを使ってハッシュを作成 local_hash1 = create_hmac_hash(request, params, oauth_token_secret) #create hash with using parameter contain POSTDATA. # POSTDATAも含めたパラメータを使ってハッシュを作成 post_param = generate_post_hash(request, encoding) params.update(post_param) local_hash2 = create_hmac_hash(request, params, oauth_token_secret) host = request.get_host() host = host.split(',')[0] base_url = request.is_secure( ) and 'https://' or 'http://' + host + request.path Log.info('base_url', base_url) for k, v in params.iteritems(): if isinstance(v, basestring): Log.info( 'Check k and v.decode(encoding) of params.iteritems()', [k, v.decode(encoding)]) else: Log.info('Check k and v of params.iteritems()', [k, v]) Log.info('raw', request.raw_post_data) Log.info('remote_hash', binascii.b2a_base64(remote_hash)[:-1]) Log.info('local_hash1', binascii.b2a_base64(local_hash1)[:-1]) Log.info('local_hash2', binascii.b2a_base64(local_hash2)[:-1]) Log.info('local_hash1 == remote_hash ?', (local_hash1 == remote_hash)) Log.info('local_hash2 == remote_hash ?', (local_hash2 == remote_hash)) if local_hash1 != remote_hash and local_hash2 != remote_hash: raise except Error, err: Log.error('oauth error', err.message) return HttpResponseNotAuthorized(request.get_full_path())
def get_friends(self, userid, has_app=True, fields=None): """ アプリを利用しているユーザーの友達情報を返す 友達情報を100件毎に取得し、最大1000件(100*10)取得する キャッシュはしない Return the information of user`s friends. Get 100 friends information each time,and at maximum you could get 1000 information(100*10). No caching. """ path = '/people/%s/@friends' % userid params = {'format': 'json', 'count': '1000'} data = None # GREEでは最大100件まで指定可能 params['count'] = 100 # リクエスト回数デフォルト値(ただし1回目リクエスト時のtotalResultsの値に書き換える) range_max = 2 total_data = None if fields: params['fields'] = fields if has_app: params['filterBy'] = 'hasApp' params['filterOp'] = 'equals' params['filterValue'] = 'true' for i in range(range_max): params['startIndex'] = params['count'] * i res = self.get_response(userid, path, params) if res: try: data = simplejson.loads(res) # totalResults==0(友達がいない)、もしくは、rangeを超えた時 if int(data['totalResults']) == 0 or i >= range_max - 1: data = total_data break else: # for文1回目(total_dataにデータが入っていない時) if not total_data: # 友達数(totalResults)を取得出来るので、range_maxを書き換え range_max = int(data['totalResults']) / 100 total_data = data total_data['totalResults'] = int( total_data['totalResults']) total_data['itemsPerPage'] = int( total_data['itemsPerPage']) # for文2回目以降 else: total_data['totalResults'] += data['totalResults'] total_data['itemsPerPage'] += data['itemsPerPage'] total_data['entry'] += data['entry'] # list except TypeError: Log.error(LOG_MSG2, [userid, path, res]) try: data = simplejson.loads(unicode(res, "utf-8", "ignore")) # totalResults==0(友達がいない) if int(data['totalResults']) == 0: data = total_data else: # for文1回目(total_dataにデータが入っていない時) if not total_data: total_data = data total_data['totalResults'] = int( total_data['totalResults']) total_data['itemsPerPage'] = int( total_data['itemsPerPage']) # for文2回目以降 else: total_data['totalResults'] += int( data['totalResults']) total_data['itemsPerPage'] += int( data['itemsPerPage']) total_data['entry'] += data['entry'] # list except TypeError: Log.error(LOG_MSG3, [userid, path, res]) break except Exception: Log.error(LOG_MSG1, [userid, path, res]) break except Exception: Log.error(LOG_MSG1, [userid, path, res]) break else: Log.error(LOG_MSG4, [userid, path]) break else: data = total_data if data == None: data = {'error': True, 'entry': [], 'totalResults': '0', 'itemsPerPage': '0' } return data
def get_request_form(request_users, submit_value, title, body, callbackurl, mobile_url, touch_url, option_params={}): u""" リクエストサービスのフォームを生成し、返す フィーチャーフォン版 外部テンプレート: gsocial/templates/opensocial/request.html 使い方:: {% get_request_form <request_users> <submit_value> <title> <body> <callbackurl> <mobile_url> <touch_url> <option_params> %} 引数: :request_users: リクエストを送信したいユーザリスト (to_user_id[]に渡すパラメータ) :submit_value: 送信ボタンの文言 :title: リクエストのタイトル(必須) :body: 本文 :callbackurl: リクエストした後に遷移するURL :mobile_url: リクエストをユーザがクリックした際の飛び先のURL(FP) :touch_url: リクエストをユーザがクリックした際の飛び先のURL(SP) :option_params: オプションディクショナリ option_params: :backto_url: リクエスト送信確認画面からアプリへ戻るためのURL :mobile_image: メッセージに含める画像のURL(FP) :touch_image: メッセージに含める画像のURL(SP) :list_type: リクエストの対象となるユーザの種別 :editable: メッセージをユーザに入力させる :expire_time: リクエストが期限切れとなる日時(UTC FORMAT) Create the form for the request service and return it.(For FP) Customize the following source cord with your own designs of the forms. Arguments: :request_users: A Userlist whom you want to send request.(A parameter to be handed to to_user_id[]) :submit_value: A letter on submit botton :title: The title of request(indispensable) :body: Message :callbackurl: A URL which will be redirected after the request. :mobile_url: A URL which will be redirected after the click(FP). :touch_url: A URL which will be redirected after the click(SP). :option_params: a optional dictionary option_params: :backto_url: A URL of the application from the "request sent confirmation"screen :mobile_image: URL of the image which will be contain in the message(FP) :touch_image: URL of the image which will be contain in the message(SP) :list_type: The type of subjected users. :editable: Whether User is allowed to edit or not. :expire_time: The expire date of the request(UTC FORMAT) """ # checks the content of option_params # option_paramsの中身をチェック # TODO : もっと綺麗にしたい keys = option_params.keys() backto_url = option_params['backto_url'] if 'backto_url' in keys else None mobile_image = option_params[ 'mobile_image'] if 'mobile_image' in keys else None touch_image = option_params[ 'touch_image'] if 'touch_image' in keys else None list_type = option_params['list_type'] if 'list_type' in keys else None editable = option_params['editable'] if 'editable' in keys else None expire_time = option_params[ 'expire_time'] if 'expire_time' in keys else None # title is indispensable,so check. # titleは必須のため、チェック if not title: Log.error('title is empty.', body) raise # if list_type was not setted,use "specified" # list_typeの指定が無かった場合、specifiedを指定する if list_type == None: list_type = 'specified' # body is indispensable when editable is True,so check # bodyはeditableがtrueでない場合は必須のため、チェック # TODO : editable==Trueの場合、メッセージをユーザに入力させる # そのため、フォーム生成のhtml側で、入力フォームを生成する必要がある if editable != True: if body == None: Log.error('body is empty.', body) raise if request_users: temp = [] for user in request_users: user_params = {} user_params['id'] = user['id'] if 'id' in user else None user_params[ 'nickname'] = user['nickname'] if 'nickname' in user else None user_params['thumbnail'] = user[ 'thumbnail'] if 'thumbnail' in user else None temp.append(user_params) return { 'request_users': temp, 'submit_value': submit_value, 'title': title, 'body': body, 'callbackurl': callbackurl, 'mobile_url': mobile_url, 'touch_url': touch_url, 'backto_url': backto_url, 'mobile_image': mobile_image, 'touch_image': touch_image, 'list_type': list_type, 'editable': editable, 'expire_time': expire_time, }