├── README.md ├── logging.conf ├── LICENSE ├── Japanese.md ├── English.md └── tipzeny.py /README.md: -------------------------------------------------------------------------------- 1 | # tipzeny Twitter用BitZeny投げ銭bot 2 | 3 | 使い方は 4 | [使い方](https://github.com/trasta298/tipzeny/blob/master/Japanese.md) 5 | [Usage](https://github.com/trasta298/tipzeny/blob/master/English.md) 6 | をどうぞ 7 | -------------------------------------------------------------------------------- /logging.conf: -------------------------------------------------------------------------------- 1 | [loggers] 2 | keys=root 3 | 4 | [handlers] 5 | keys=consoleHandler, fileHandler 6 | 7 | [formatters] 8 | keys=logFormatter 9 | 10 | [logger_root] 11 | level=DEBUG 12 | handlers=consoleHandler, fileHandler 13 | 14 | [handler_consoleHandler] 15 | class=StreamHandler 16 | formatter=logFormatter 17 | args=(sys.stderr, ) 18 | 19 | [handler_fileHandler] 20 | class=FileHandler 21 | formatter=logFormatter 22 | args=('zeny.log', 'a') 23 | 24 | [formatter_logFormatter] 25 | format=%(asctime)s %(levelname)8s %(message)s -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 trasta 2 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 3 | 4 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 5 | 6 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 7 | -------------------------------------------------------------------------------- /Japanese.md: -------------------------------------------------------------------------------- 1 | # りん姫 How to use 2 | 3 | ここはりん姫(BitZeny投げ銭bot)のヘルプページです。以下で使えるコマンドを参照してください。 4 | botが止まっていた時や質問があるときは[開発者twitter](https://twitter.com/tra_sta)まで。 5 | ※注意 6 | ・コマンドを使うときの空白はすべて半角にしてください。 7 | 8 | 9 | ## balance/残高 10 | ### @zenytips balance (コメント) 11 | 残高を確認できます。 12 | 例:`@zenytips balance` 13 | 14 | 15 | ## deposit/入金 16 | ### @zenytips deposit (コメント) 17 | 入金用アドレスを返します。 18 | 例:`@zenytips deposit` 19 | 20 | 21 | ## withdraw/出金 22 | ### @zenytips withdraw 受取ZNYアドレス 出金額 23 | 指定した額を出金することができます。 24 | 例:`@zenytips withdraw EXAMPleAdDreSS 10` 25 | 26 | 27 | ## withdrawall/全額出金 28 | ### @zenytips withdrawall 受取ZNYアドレス 29 | りん姫にある残高すべてを出金することができます。 30 | 例:`@zenytips withdrawall EXAMPleAdDreSS` 31 | 32 | ## tip/send/投げ銭/送金 33 | ### @￰zenytips send @￰twitterアカウント 送金額 (コメント) 34 | 指定された額のZNYを相手に送ります。 35 | 例:`@zenytips tip @tra_sta 3.9 ありがとう!` 36 | ### @￰zenytips tip @￰zenytips 投銭額 37 | で開発者に寄付できます。サーバー維持費に使うので是非投げ銭ください。 38 | 39 | ## thanks 40 | ### @￰zenytips send @￰twitterアカウント (コメント) 41 | 3.939ZNYを相手に送ります。 42 | 例:`@zenytips thanks @tra_sta yay!` 43 | 44 | 78 | -------------------------------------------------------------------------------- /English.md: -------------------------------------------------------------------------------- 1 | # Usages for Rinhime(りん姫), the BitZeny tipping bot on Twitter 2 | 3 | This is the help page for Rinhime *(pronounced: `Ling-he-may`)* , the BitZeny tipping bot on Twitter. 4 | Please refer below for commands. 5 | You can use any command by both tweeting or messaging except for `giveme`, `rainlist`, and `rainfollowerlist` command. 6 | For any issues about the bot (stopped, or bugs), please contact the dev's [Twitter](https://twitter.com/tra_sta). 7 | 8 | Translated by [nao20010128nao](https://github.com/nao20010128nao). 9 | 10 | **Notices:** 11 | - Follow back won't be done for everyone. 12 | - You need at least 5 ZNY for receiving RAIN. 13 | 14 | ## balance 15 | ### @rintips balance (any comment, optional) 16 | Replies you the balance you have. 17 | **Example:** `@rintips balance` 18 | 19 | 20 | ## deposit 21 | ### @rintips deposit (any comment, optional) 22 | Replies you deposit address. 23 | **Example:** `@rintips deposit` 24 | 25 | 26 | ## withdraw 27 | ### @rintips withdraw (ZNY address, required) (amount to withdraw, required) 28 | Withdraws specified amount of BitZeny to the specified address. 29 | **Example:** `@rintips withdraw ZuGdQvycbE9HTfke3EPcSUQEH2joaYqXjj 10` 30 | 31 | 32 | ## withdrawall 33 | ### @rintips withdrawall (ZNY address, required) 34 | Withdraws *all* BitZeny to the specified address. 35 | **Example:** `@rintips withdrawall ZuGdQvycbE9HTfke3EPcSUQEH2joaYqXjj` 36 | **CAUTION:** This command will withdraw **ALL** BitZeny including the last 5ZNY. 37 | 38 | ## send 39 | ### @￰rintips send (Twitter account ID starting with @, required) (amount to send, required) (any comment, optional) 40 | Sends specified amount of BitZeny to the specified account. 41 | 42 | ## tip 43 | ### @￰rintips tip (Twitter account ID starting with @, required) (amount to tip, required) (any comment, optional) 44 | Sends specified amount of BitZeny to the specified account. 45 | The receiver needs to use `balance` command within 3 days to receive. 46 | If the receiver didn't received your tip, it'll be sent back to your balance. 47 | **Example:** `@rintips tip @tra_sta 3.9 Thanks!` 48 | **Tip:** You can donate the author by: `@￰rintips tip @￰rintips (amount to tip, required)` 49 | 50 | ## rain 51 | ### @￰rintips rain (amount to rain, required) 52 | Delivers equally ZNYs to the users who fulfilled the following condition: 53 | - Have deposited at least 5 ZNY. 54 | 70 | ## giveme 71 | ### @rintips giveme (any comment, optional) 72 | If your account fulfills the following conditions, you can get a little ZNYs. 73 | - Using official client. 74 | - Tweeted more than 100 tweets. 75 | - 2 weeks elapsed from creation of your account. 76 | - Your balance is 10 ZNY or less. 77 | - 7 days elapsed from the last withdrawal. 78 | - 24 hours elapsed from the last `giveme` command. 79 | 80 | **Caution:** Not available in the Direct Messages, be careful. 81 | 82 | ## A hidden command only available for the New Year Day 83 | **Caution:** The following command contains Japanese Kanjis, you may need Copy and Paste. 84 | ### @￰rintips お年玉 (Twitter account ID starting with @, required) (amount to tip, required) (any comment, optional) 85 | You can send a New Year present. 86 | 87 | ### @￰rintips お賽銭 (amount to tip, required) (any comment, optional) 88 | You can make a money offering. More you make, I will be happier. 89 | -------------------------------------------------------------------------------- /tipzeny.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf-8 -*- 3 | 4 | from decimal import * 5 | import json 6 | import re 7 | import logging 8 | import sqlite3 9 | import logging.config 10 | from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException 11 | from tweepy.streaming import StreamListener, Stream 12 | from tweepy.auth import OAuthHandler 13 | from tweepy.api import API 14 | import datetime 15 | 16 | # bitcoind 17 | rpc_user='' 18 | rpc_password='' 19 | zeny = AuthServiceProxy("http://%s:%s@ip:port"%(rpc_user, rpc_password)) 20 | 21 | # logger 22 | logging.config.fileConfig('logging.conf') 23 | logger = logging.getLogger() 24 | 25 | def get_oauth(): 26 | consumer_key = '' 27 | consumer_secret = '' 28 | access_key = '' 29 | access_secret = '' 30 | auth = OAuthHandler(consumer_key, consumer_secret) 31 | auth.set_access_token(access_key, access_secret) 32 | return auth 33 | 34 | def DecimaltoStr(d): 35 | return '{0:f}'.format(d) 36 | 37 | def str_isfloat(str): 38 | try: 39 | float(str) 40 | return True 41 | 42 | except ValueError: 43 | return False 44 | 45 | def savetip(from_id, to_id, amount): 46 | con = sqlite3.connect('tipzeny.db') 47 | c = con.cursor() 48 | 49 | create_table = '''CREATE TABLE IF NOT EXISTS tiplist(from_id int, to_id int, amount text, date_time text)''' 50 | c.execute(create_table) 51 | 52 | date_str = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") 53 | amount = str(amount) 54 | 55 | ins = 'insert into tiplist (from_id, to_id, amount, date_time) values (?,?,?,?)' 56 | tip = (from_id, to_id, amount, date_str) 57 | c.execute(ins, tip) 58 | con.commit() 59 | con.close() 60 | 61 | def gettip(user_id): 62 | con = sqlite3.connect('tipzeny.db') 63 | c = con.cursor() 64 | 65 | from_ids = c.execute("select * from tiplist where from_id = ?",(user_id,)) 66 | for row in from_ids: 67 | date = datetime.datetime.strptime(row[3], "%Y/%m/%d %H:%M:%S") 68 | if datetime.datetime.now() > date + datetime.timedelta(days = 3): 69 | zeny.move("tippot", "tipzeny-" + str(row[0]), float(row[2])) 70 | c.execute("delete from tiplist where date_time = ? and from_id = ?", (row[3],row[0])) 71 | con.commit() 72 | 73 | tos = c.execute("select * from tiplist where to_id = ?",(user_id,)) 74 | for row in tos: 75 | date = datetime.datetime.strptime(row[3], "%Y/%m/%d %H:%M:%S") 76 | if datetime.datetime.now() < date + datetime.timedelta(days = 3): 77 | zeny.move("tippot", "tipzeny-" + str(row[1]), float(row[2])) 78 | c.execute("delete from tiplist where date_time = ? and from_id = ?", (row[3],row[0])) 79 | con.commit() 80 | con.close() 81 | 82 | 83 | def helptweet(status,txt): 84 | tweet = "@" + status.user.screen_name + u" " + txt 85 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 86 | 87 | # ツイート処理 88 | def on_tweet(status): 89 | if status.text.find("RT") == -1 and status.text.find("QT") == -1 and status.user.screen_name != "zenytips": 90 | if status.text.find("@zenytips") == -1: 91 | return 92 | 93 | name = status.user.screen_name 94 | message = status.text[(status.text.find("@zenytips")+10):] 95 | account = "tipzeny-" + str(status.user.id) 96 | 97 | if re.search("balance", message) or re.search(u"残高", message): 98 | gettip(status.user.id) 99 | balance = zeny.getbalance(account,6) 100 | all_balance = zeny.getbalance(account,0) 101 | 102 | if all_balance < 10: 103 | f = open('accountlist.json','r') 104 | json_data = json.load(f) 105 | if status.user.id in json_data: 106 | datas = filter(lambda x: x == status.user.id, json_data) 107 | w = open('accountlist.json','w') 108 | json.dump(datas, w) 109 | else: 110 | f = open('accountlist.json','r') 111 | json_data = json.load(f) 112 | if status.user.id not in json_data: 113 | json_data.append(status.user.id) 114 | w = open('accountlist.json','w') 115 | json.dump(json_data, w) 116 | 117 | 118 | logger.info("check balance..." + name) 119 | logger.info(DecimaltoStr(balance) + "ZNY all(" + DecimaltoStr(all_balance) + "ZNY)") 120 | tweet = "@" + name + " " + DecimaltoStr(balance) + u"ZNY持ってます!" 121 | if balance < all_balance: 122 | tweet += u"\n(confirm中" + DecimaltoStr(all_balance-balance) + u"ZNY)" 123 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 124 | 125 | elif re.search("deposit", message) or re.search(u"入金", message): 126 | address = zeny.getaccountaddress(account) 127 | logger.info("get deposit address..." + name) 128 | logger.info(account + " => " + address) 129 | tweet = "@" + name + " " + address + u" に送金お願いしますっ!" 130 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 131 | 132 | elif re.match("withdrawall", message) or re.match(u"全額出金", message): 133 | m = re.split(" ", message) 134 | if len(m) < 2: 135 | helptweet(status, u"withdrawall(全額出金)の使い方\n@￰zenytips withdrawall 受取ZNYアドレス\nhttps://github.com/trasta298/tipzeny/wiki") 136 | return 137 | 138 | address = m[1] 139 | balance = zeny.getbalance(account,6) 140 | tax = 0.01 141 | payying = float(balance)-tax 142 | 143 | logger.info("withdraw..."+name) 144 | 145 | if round(0-payying,7) >= 0: 146 | logger.info("-> Not enough ZNY (0.01 > " + str(payying) + ")") 147 | tweet = "@" + name + u" 残高が足りないみたいですっ!\n所持zny: " + str(balance) + "ZNY" 148 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 149 | return 150 | 151 | validate = zeny.validateaddress(address) 152 | if not validate['isvalid']: 153 | logger.info("-> Invalid address") 154 | tweet = "@" + name + u" アドレスが間違ってるみたいですっ" 155 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 156 | return 157 | 158 | logger.info("-> Sending...") 159 | txid = zeny.sendfrom(account,address,payying) 160 | 161 | # taxまわりとりあえず後回し 162 | logger.info("-> Checking transaction...") 163 | tx = zeny.gettransaction(txid) 164 | if tx: 165 | fee = float(tx['fee']) 166 | logger.info("-> Tax: " + str(fee)) 167 | else: 168 | fee = 0 169 | logger.info("-> No Tax") 170 | 171 | zeny.move(account, "taxpot", tax+fee) 172 | logger.info("-> Fee sent to taxpot: " + str(tax+fee) + "ZNY") 173 | tweet = "@" + name + u" zenyを引き出しましたっ!(手数料0.01ZNY)\nhttp://namuyan.dip.jp/MultiLightBlockExplorer/gettxid.php?coin=zeny&txid=" + str(txid) 174 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 175 | 176 | f = open('accountlist.json','r') 177 | json_data = json.load(f) 178 | if status.user.id in json_data: 179 | datas = filter(lambda x: x == status.user.id, json_data) 180 | w = open('accountlist.json','w') 181 | json.dump(datas, w) 182 | 183 | elif re.match("withdraw", message) or re.match(u"出金", message): 184 | m = re.split(" ", message) 185 | if len(m) < 3 or not str_isfloat(m[2]): 186 | helptweet(status, u"withdraw(出金)の使い方\n@￰zenytips withdraw 受取ZNYアドレス 出金額(ZNY)\nhttps://github.com/trasta298/tipzeny/wiki") 187 | return 188 | 189 | address = m[1] 190 | amot= float(m[2]) 191 | balance = zeny.getbalance(account,6) 192 | tax = 0.01 193 | amount = amot-tax 194 | 195 | if amount <= 0: 196 | tweet = "@" + name + u" 0以下の数は指定できません!" 197 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 198 | return 199 | 200 | logger.info("withdraw..."+name) 201 | 202 | if round(Decimal(amount)-balance,7) >= 0: 203 | logger.info("-> Not enough ZNY ("+ DecimaltoStr(balance) + " < " + str(amount) + ")") 204 | tweet = "@" + name + u" 残高が足りないみたいですっ!\n所持zny: " + DecimaltoStr(balance) + "ZNY" 205 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 206 | return 207 | 208 | validate = zeny.validateaddress(address) 209 | if not validate['isvalid']: 210 | logger.info("-> Invalid address") 211 | tweet = "@" + name + u" アドレスが間違ってるみたいですっ" 212 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 213 | return 214 | 215 | logger.info("-> Sending...") 216 | txid = zeny.sendfrom(account,address,amount) 217 | 218 | # taxまわりとりあえず後回し 219 | logger.info("-> Checking transaction...") 220 | tx = zeny.gettransaction(txid) 221 | if tx: 222 | fee = float(tx['fee']) 223 | logger.info("-> Tax: " + str(fee)) 224 | else: 225 | fee = 0 226 | logger.info("-> No Tax") 227 | 228 | zeny.move(account, "taxpot", tax+fee) 229 | logger.info("-> Fee sent to taxpot: " + str(tax+fee) + "ZNY") 230 | tweet = "@" + name + u" zenyを引き出しましたっ!(手数料0.01ZNY)\nhttp://namuyan.dip.jp/MultiLightBlockExplorer/gettxid.php?coin=zeny&txid=" + str(txid) 231 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 232 | 233 | if float(balance)-amount < 10: 234 | f = open('accountlist.json','r') 235 | json_data = json.load(f) 236 | if status.user.id in json_data: 237 | datas = filter(lambda x: x == status.user.id, json_data) 238 | w = open('accountlist.json','w') 239 | json.dump(datas, w) 240 | 241 | elif re.match("rain", message) or re.match(u"撒き銭", message): 242 | m = re.split(" ", message) 243 | if len(m) < 2 or not str_isfloat(m[1]): 244 | helptweet(status, u"rain(撒き銭)の使い方\n@￰zenytips rain 撒銭額(ZNY)\nhttps://github.com/trasta298/tipzeny/wiki") 245 | return 246 | amount = float(m[1]) 247 | balance = zeny.getbalance(account,6) 248 | 249 | if amount <= 0: 250 | tweet = "@" + name + u" 0以下の数は指定できません!" 251 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 252 | return 253 | 254 | logger.info("Raining..."+str(amount)+"ZNY from "+name) 255 | 256 | if round(Decimal(amount)-balance,7) > 0: 257 | logger.info("-> Not enough ZNY ("+ DecimaltoStr(balance) + " < " + str(amount) + ")") 258 | tweet = "@" + name + u" 残高が足りないみたいですっ!\n所持zny: " + DecimaltoStr(balance) + "ZNY" 259 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 260 | return 261 | 262 | f = open('accountlist.json','r') 263 | json_data = json.load(f) 264 | nmb = len(json_data) 265 | if nmb == 0: 266 | tweet = "@" + name + u" 対象者がいないみたいです。。。" 267 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 268 | 269 | mon = round(amount/nmb,7) 270 | for userid in json_data: 271 | to_account = "tipzeny-" + str(userid) 272 | zeny.move(account,to_account,mon) 273 | logger.info("-> Sent.") 274 | 275 | tweet = "@" + name + u" " + str(nmb) + u"人にそれぞれ " + str(mon) + u"ZNYずつ送りましたっ!" 276 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 277 | 278 | elif re.match("send", message) or re.match(u"送金", message): 279 | m = re.split(" ", message) 280 | if len(m) < 3 or not str_isfloat(m[2]): 281 | helptweet(status, u"send(送金)の使い方\n@￰zenytips send @￰twitterアカウント 投銭額(ZNY)\nhttps://github.com/trasta298/tipzeny/wiki") 282 | return 283 | if m[1][0] != "@": 284 | helptweet(status, u"send(送金)の使い方\n@￰zenytips send @￰twitterアカウント 投銭額(ZNY)\nhttps://github.com/trasta298/tipzeny/wiki") 285 | return 286 | 287 | to = m[1][1:] 288 | amount = float(m[2]) 289 | balance = zeny.getbalance(account,6) 290 | 291 | if amount <= 0: 292 | tweet = "@" + name + u" 0以下の数は指定できません!" 293 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 294 | return 295 | 296 | logger.info("Sending..."+str(amount)+"ZNY from "+name+" to "+to) 297 | 298 | if round(Decimal(amount)-balance,7) > 0: 299 | logger.info("-> Not enough ZNY ("+ DecimaltoStr(balance) + " < " + str(amount) + ")") 300 | tweet = "@" + name + u" 残高が足りないみたいですっ!\n所持zny: " + DecimaltoStr(balance) + "ZNY" 301 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 302 | return 303 | 304 | try: 305 | to_user = api.get_user(to) 306 | 307 | except: 308 | logger.info("-> User not found.") 309 | tweet = "@" + name + u" 送り主(" + to + u")が見つかりませんでした…" 310 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 311 | return 312 | 313 | to_account = "tipzeny-" + str(to_user.id) 314 | zeny.move(account,to_account,amount) 315 | logger.info("-> Sent.") 316 | tweet = "@" + to + u" りん姫より @" + name + u" さんから" + str(amount) + u"ZNYのお届け物だよっ!" 317 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 318 | 319 | elif re.match("tip", message) or re.match(u"投銭", message): 320 | m = re.split(" ", message) 321 | if len(m) < 3 or not str_isfloat(m[2]): 322 | helptweet(status, u"tip(投銭)の使い方\n@￰zenytips tip @￰twitterアカウント 投銭額(ZNY)\nhttps://github.com/trasta298/tipzeny/wiki") 323 | return 324 | if m[1][0] != "@": 325 | helptweet(status, u"tip(投銭)の使い方\n@￰zenytips tip @￰twitterアカウント 投銭額(ZNY)\nhttps://github.com/trasta298/tipzeny/wiki") 326 | return 327 | 328 | to = m[1][1:] 329 | amount = float(m[2]) 330 | balance = zeny.getbalance(account,6) 331 | 332 | if amount <= 0: 333 | tweet = "@" + name + u" 0以下の数は指定できません!" 334 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 335 | return 336 | 337 | logger.info("Tip..."+str(amount)+"ZNY from "+name+" to "+to) 338 | 339 | if round(Decimal(amount)-balance,7) > 0: 340 | logger.info("-> Not enough ZNY ("+ DecimaltoStr(balance) + " < " + str(amount) + ")") 341 | tweet = "@" + name + u" 残高が足りないみたいですっ!\n所持zny: " + DecimaltoStr(balance) + "ZNY" 342 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 343 | return 344 | 345 | try: 346 | to_user = api.get_user(to) 347 | 348 | except: 349 | logger.info("-> User not found.") 350 | tweet = "@" + name + u" 送り主(" + to + u")が見つかりませんでした…" 351 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 352 | return 353 | 354 | to_account = "tipzeny-" + str(to_user.id) 355 | savetip(status.user.id, to_user.id, amount) 356 | zeny.move(account,"tippot",amount) 357 | logger.info("-> Sent.") 358 | tweet = "@" + to + u" りん姫より @" + name + u" さんから" + str(amount) + u"ZNYのお届け物だよっ! 3日以内にbalanceして受け取ってね!" 359 | api.update_status(status=tweet, in_reply_to_status_id=status.id) 360 | 361 | elif len(message) < 2: 362 | helptweet(status, u"りん姫の使い方はここっ\nhttps://github.com/trasta298/tipzeny/wiki") 363 | 364 | 365 | #3029861817 366 | class Listener(StreamListener): 367 | def on_status(self, status): 368 | on_tweet(status) 369 | return True 370 | 371 | def on_data(self, raw_data): 372 | data = json.loads(raw_data) 373 | if 'direct_message' in data: 374 | print(raw_data) 375 | return True 376 | 377 | def on_error(self, status_code): 378 | logger.error('エラー発生: ' + str(status_code)) 379 | return True 380 | 381 | def on_connect(self): 382 | logger.info('Streamに接続しました') 383 | return 384 | 385 | def on_disconnect(self, notice): 386 | logger.info('Streamから切断されました:' + str(notice.code)) 387 | return 388 | 389 | def on_limit(self, track): 390 | logger.warning('受信リミットが発生しました:' + str(track)) 391 | return 392 | 393 | def on_timeout(self): 394 | logger.info('タイムアウト') 395 | return True 396 | 397 | def on_warning(self, notice): 398 | logger.warning('警告メッセージ:' + str(notice.message)) 399 | return 400 | 401 | def on_exception(self, exception): 402 | logger.error('例外エラー:' + str(exception)) 403 | return 404 | 405 | 406 | # main 407 | if __name__ == '__main__': 408 | auth = get_oauth() 409 | api = API(auth) 410 | stream = Stream(auth, Listener(), secure=True) 411 | stream.userstream() --------------------------------------------------------------------------------