ゼロと無限の間に

フリーでオープンソースなJavaScriptとかPHPとか。

ユーザ用ツール

サイト用ツール


python-box:appengine-twitter

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
python-box:appengine-twitter [2009/08/05 22:52] dgbadminpython-box:appengine-twitter [2017/05/13 05:36] (現在) – [AppEngine-Twitterのソースコード] dgbadmin
行 7: 行 7:
 Google App EngineでTwitter APIを操作するライブラリを作ってみた。\\ Google App EngineでTwitter APIを操作するライブラリを作ってみた。\\
 車輪の再発明ではなく、趣味の車輪作り。 車輪の再発明ではなく、趣味の車輪作り。
 +
 +バージョン0.3.0からはTwitter Search APIの廃止に対応して、検索もOAuthを使ってTwitter REST API 1.1を使うように変更した。
  
  
行 15: 行 17:
  
 ===== デモ(動作サンプル) ===== ===== デモ(動作サンプル) =====
- 
-※OAuthを使っているデモについては[[python-box/appengine-oauth]]を参照 
- 
  
 ==== その1. RT(ReTweet)の多いつぶやきを報告するBot ==== ==== その1. RT(ReTweet)の多いつぶやきを報告するBot ====
行 26: 行 25:
 [[http://twitter.com/who_is_near|@who_is_near]] [[http://twitter.com/who_is_near|@who_is_near]]
  
 +※検索がまだTwitter REST API 1.1に対応させてないので今は動かない(はず)
  
-==== その3. ユーザー名・パスワードを入力してTwitter APIの主な操作を一通りするデモ ==== +=== 使用例 === 
-[[http://0-oo.appspot.com/twitter/|ユーザー名・パスワードを入力してTwitter APIの主な操作一通りするデモ]]+<code>@who_is_near 六本木</code> 
 +試しにつぶやくには、Twitterにログイン後に[[http://twitter.com/?status=%40who_is_near%20%E5%85%AD%E6%9C%AC%E6%9C%A8|ここクリック]]
  
-ソースコード(※[[python-box/appengine-basehandler]]を使っている。それとOAuth使っていない場合でも、[[python-box/appengine-oauth]]も無いと動かないかも。) 
-<code python> 
-#!/usr/bin/env python 
-# -*- coding: UTF-8 -*- 
-''' 
-Sample for AppEngine-Twitter on Google App Engine 
  
-See: http://0-oo.net/sbox/python-box/appengine-twitter +==== そ3出発地点と目的地を告げると、乗換(ルート)案内Googleマップ表示してくれるBot ==== 
-''' +[[http://twitter.com/norikae_map|@norikae_map]]
- +
-import logging +
-import wsgiref.handlers +
-from appengine_twitter import AppEngineTwitter +
-from basehandler import BaseHandler,+
-from google.appengine.ext import webapp +
- +
- +
-class MainHandler(BaseHandler): +
- +
-  def get(self): +
-    self.show() +
- +
-     +
-  def post(self): +
-    self.show(self.request.get('name'), self.request.get('pswd')) +
- +
- +
-  def show(self, name='', pswd=''): +
-    self.simple_header(u'AppEngine-Twitterデモ'+
-     +
-    self.p(u'<h1>AppEngine-Twitterデモ</h1>'+
-    self.p(u'<h2>Twitterログイン情報入力してください</h2>'+
-    self.p('<form method="post" action="./">'+
-    self.p(u'ユーザー名 ') +
-    self.p('<input type="text" name="name" value="' + h(name) + '">') +
-    self.p(u' パスワード ') +
-    self.p('<input type="password" name="pswd"'+
-              ' value="' + h(pswd) + '">'+
-    self.p(' <input type="submit">'+
-    self.p('</form>', True) +
-    self.p('<br>'+
- +
-    if name and pswd: +
-      self.test(name, pswd) +
- +
-    self.p('<hr>', True) +
-    self.p(u'このページは'+
-    self.p('<a href="http://0-oo.net/sbox/python-box/appengine-twitter">'+
-    self.p('AppEngine-Twitter'+
-    self.p(u'</a>のデモです'+
-     +
-    self.simple_footer() +
- +
- +
-  def test(self, name, pswd):     +
-    twitter = AppEngineTwitter(name, pswd) +
-       +
-    self.p(u'<h2>実行結果</h2>', True) +
- +
-    self.p(u'<b>verify()</b> ユーザー名とパスワードの確認(200ならOK)', True) +
-    self.p(twitter.verify(), True) +
-    self.p('<br>'+
-       +
-    self.p(u'<b>search()</b> "腹減った"を検索(3件まで)', True) +
-    results = twitter.search(u'腹減った'.encode('utf8'), {'rpp': 3}) +
-    for result in results: +
-      self.p(result['text'], True) +
-    self.p('<br>'+
-       +
-    self.p(u'<b>is_following()</b> @uresuji_booksをフォローしてる?', True) +
-    if twitter.is_following('uresuji_books'): +
-      self.p('True'+
-    else: +
-      self.p('False'+
-    self.p('<br>', True)+
  
-    note u'<b>follow()</b@uresuji_booksをフォローする' +=== 使用例 1. 移動方法を指定しないと、電車でのルート検索・乗り換え案内になる === 
-    note += u'(200なら成功403なら既フォー済み)' +<code>@norikae_map 東京 大阪</code
-    self.p(note, True) +試しにつぶやくにはTwitterにログイン後に[[http://twitter.com/?status=%40norikae_map%20%E6%9D%B1%E4%BA%AC%20%E5%A4%A7%E9%98%AA|ここをクリック]]
-    self.p(twitter.follow('uresuji_books'), True) +
-    self.p('<br>')+
  
-    self.p(u'<b>update()</b> つぶやく(200なら成功。自分のTLを見てみてね)', True) +=== 使用例 2車でのルートの案内 === 
-    msg = 'AppEngine-Twitter (on Python and Google App Engine) ' +<code>@norikae_map 木更津駅 羽田空港駅 車</code> 
-    msg += u'http://0-oo.appspot.com/twitter/ からんにちは!' +試しにつぶやくには、Twitterにログイン後に[[http://twitter.com/?status=%40norikae_map%20%E6%9C%A8%E6%9B%B4%E6%B4%A5%E9%A7%85%20%E7%BE%BD%E7%94%B0%E7%A9%BA%E6%B8%AF%E9%A7%85%20%E8%BB%8A|こをクリック]]
-    self.p(twitter.update(msg.encode('utf8')), True) +
-    self.p('<br>')+
  
 +=== 使用例 3. 歩きでのルートの案内 ===
 +<code>@norikae_map 霞が関 霞が関 歩き</code>
 +試しにつぶやくには、Twitterにログイン後に[[http://twitter.com/?status=%40norikae_map%20%E9%9C%9E%E3%81%8C%E9%96%A2%20%E9%9C%9E%E3%81%8C%E9%96%A2%20%E6%AD%A9%E3%81%8D|ここをクリック]]
  
  
-logging.getLogger() +==== その4Twitter APIでOAuth認証してつぶやいたりフォローしたりするデモ ====
-routing [('/twitter/.*', MainHandler)] +
-application webapp.WSGIApplication(routing, debug=False) +
-wsgiref.handlers.CGIHandler().run(application) +
-</code>+
  
 +[[python-box/appengine-oauth|AppEngine Oauth]]のデモその4を参照。
  
  
行 141: 行 66:
  
 See also: See also:
-  http://apiwiki.twitter.com/Twitter-API-Documentation +  https://dev.twitter.com/docs/api 
-  http://code.google.com/intl/ja/appengine/docs/python/urlfetch/+  https://developers.google.com/appengine/docs/python/urlfetch/?hl=ja
 ''' '''
  
 __author__ = 'dgbadmin@gmail.com' __author__ = 'dgbadmin@gmail.com'
-__version__ = '0.1.0'+__version__ = '0.4.0'
  
  
-import base64+import json
 import urllib import urllib
 from appengine_oauth import AppEngineOAuth from appengine_oauth import AppEngineOAuth
-from django.utils import simplejson 
 from google.appengine.api import urlfetch from google.appengine.api import urlfetch
- +
  
 class AppEngineTwitter(object): class AppEngineTwitter(object):
  
-  def __init__(self, tw_name='', tw_pswd=''): +  def __init__(self): 
-    ''' +    self._api_url = 'https://api.twitter.com/1.1/
-    Note: Some actions require password or OAuth. +    self._oauth_url = 'https://api.twitter.com/oauth/' 
-    ''' +    self._oauth = None 
-    self._api_url = 'https://twitter.com' +    self._tw_name = ''
-    self._search_url = 'http://search.twitter.com'+
  
-    self.tw_name = tw_name 
-    self._oauth = None 
-     
-    self._headers = {} 
-    if tw_pswd != '': 
-      auth = base64.encodestring(tw_name + ':' + tw_pswd)[:-1] 
-      self._headers['Authorization'] = 'Basic ' + auth 
-  
  
   def update(self, message):   def update(self, message):
行 179: 行 94:
     Sucess => Retrun 200 / Fialed => Return other HTTP status     Sucess => Retrun 200 / Fialed => Return other HTTP status
     '''     '''
-    return self._post('/statuses/update.json', {'status': message}) +    return self._post('statuses/update.json', {'status': message}) 
- + 
 + 
 +  def retweet(self, tweet_id): 
 +    ''' 
 +    ReTweet a tweet 
 +    Sucess => Retrun 200 / Fialed => Return other HTTP status 
 +    ''' 
 +    return self._post('statuses/retweet/' + tweet_id + '.json', {}) 
  
   def follow(self, target_name):   def follow(self, target_name):
行 187: 行 110:
     Fialed => Return other HTTP status     Fialed => Return other HTTP status
     '''     '''
-    return self._post('/friendships/create.json', {'screen_name': target_name}) +    return self._post('friendships/create.json', {'screen_name': target_name}) 
- +
  
   def is_following(self, target_name):   def is_following(self, target_name):
行 195: 行 118:
     Fialed => Return HTTP status except 200     Fialed => Return HTTP status except 200
     '''     '''
-    if self.tw_name == '': +    if self._tw_name == '':
-      # With OAuth, screen_name is not required.+
       self.verify()       self.verify()
-      user_info = simplejson.loads(self.last_response.content) +      user_info = json.loads(self.last_response.content) 
-      self.tw_name = user_info['screen_name'+      self._tw_name = user_info['screen_name'
-       + 
-    status = self._get('/friendships/exists.json', +    status = self._get('friendships/exists.json', 
-                       {'user_a': self.tw_name, 'user_b': target_name})+                       {'user_a': self._tw_name, 'user_b': target_name})
     if status == 200:     if status == 200:
       return (self.last_response.content == 'true')       return (self.last_response.content == 'true')
行 214: 行 136:
     Sucess => Return 200 / Fialed => Return other HTTP status     Sucess => Return 200 / Fialed => Return other HTTP status
     '''     '''
-    return self._get('/account/verify_credentials.json', {}) +    return self._get('account/verify_credentials.json', {}) 
- +
  
   def search(self, keyword, params={}):   def search(self, keyword, params={}):
     '''     '''
-    Sucess => Return Array of dict / Fialed => Return HTTP status except 200+    Sucess => Return Array of dict / Fialed => raise an Exception
     '''     '''
     params['q'] = keyword     params['q'] = keyword
-    return self._search('/search.json', params)+    status = self._get('search/tweets.json', params
 + 
 +    if status == 200: 
 +      return json.loads(self.last_response.content)['statuses'
 +    else: 
 +      raise Exception('Error: HTTP Status is ' + str(status))
  
  
行 239: 行 166:
     Get request token, request token secret and login URL     Get request token, request token secret and login URL
     '''     '''
-    dic = self._oauth.prepare_login(self._api_url + '/oauth/request_token/') +    dic = self._oauth.prepare_login(self._oauth_url + 'request_token'
-    dic['url'] = self._api_url + '/oauth/authorize?' + dic['params']+    dic['url'] = self._oauth_url + 'authorize?' + dic['params']
     return dic     return dic
  
行 248: 行 175:
     Exchange request token for access token     Exchange request token for access token
     '''     '''
-    return self._oauth.exchange_tokens(self._api_url + '/oauth/access_token/',+    return self._oauth.exchange_tokens(self._oauth_url + 'access_token',
                                        req_token,                                        req_token,
                                        req_token_secret)                                        req_token_secret)
行 254: 行 181:
  
   # Private methods   # Private methods
- +
   def _post(self, path, params):   def _post(self, path, params):
     url = self._api_url + path     url = self._api_url + path
-    if self._oauth != None: +    params = self._oauth.get_oauth_params(url, params, 'POST'
-      params = self._oauth.get_oauth_params(url, params, 'POST'+    res = urlfetch.fetch(url=url, payload=urllib.urlencode(params), method='POST')
-    res = urlfetch.fetch(url=url, +
-                         payload=urllib.urlencode(params), +
-                         method='POST'+
-                         headers=self._headers)+
     self.last_response = res     self.last_response = res
     return res.status_code     return res.status_code
- +
  
   def _get(self, path, params):   def _get(self, path, params):
行 272: 行 195:
       params = self._oauth.get_oauth_params(url, params, 'GET')       params = self._oauth.get_oauth_params(url, params, 'GET')
     url += '?' + urllib.urlencode(params)     url += '?' + urllib.urlencode(params)
-    res = urlfetch.fetch(url=url, method='GET', headers=self._headers)+    res = urlfetch.fetch(url=url, method='GET')
     self.last_response = res     self.last_response = res
     return res.status_code     return res.status_code
-  
- 
-  def _search(self, path, params): 
-    ''' 
-    FYI http://apiwiki.twitter.com/Rate-limiting (Especially 503 error) 
-    ''' 
-    url = url=self._search_url + path + '?' + urllib.urlencode(params) 
-    res = urlfetch.fetch(url=url, method='GET') 
-    self.last_response = res 
-     
-    if res.status_code == 200: 
-      return simplejson.loads(res.content)['results'] 
-    elif res.status_code == 503: 
-      err_msg = 'Rate Limiting: Retry After ' + res.headers['Retry-After'] 
-    else: 
-      err_msg = 'Error: HTTP Status is ' + str(res.status_code) 
- 
-    raise Exception('Twitter Search API ' + err_msg) 
 </code> </code>
  
  
python-box/appengine-twitter.1249480328.txt.gz · 最終更新: 2009/08/05 22:52 by dgbadmin

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki