Commit c98aeb50be7be7637f7aa3960913fa590dff149e

Authored by Nadya Sutjiadi
Committed by GitHub
1 parent f6d4b30b

Add files via upload

LINETCR/Api/Poll.py 0 โ†’ 100644
  1 +import os, sys, time
  2 +path = os.path.join(os.path.dirname(__file__), '../lib/')
  3 +sys.path.insert(0, path)
  4 +
  5 +from thrift.transport import THttpClient
  6 +from thrift.protocol import TCompactProtocol
  7 +
  8 +from curve import LineService
  9 +from curve.ttypes import *
  10 +
  11 +class Poll:
  12 +
  13 + client = None
  14 +
  15 + auth_query_path = "/api/v4/TalkService.do";
  16 + http_query_path = "/S4";
  17 + polling_path = "/P4";
  18 + host = "gd2.line.naver.jp";
  19 + port = 443;
  20 +
  21 + UA = "Line/1.4.17"
  22 +# LA = "IOSIPAD\x097.14.0\x09iPhone_OS\x0910.12.0"
  23 + LA = "CHROMEOS\t1.4.17\tChrome_OS\t1"
  24 +
  25 + rev = 0
  26 +
  27 + def __init__(self, authToken):
  28 + self.transport = THttpClient.THttpClient('https://gd2.line.naver.jp:443'+ self.http_query_path)
  29 + self.transport.setCustomHeaders({
  30 + "User-Agent" : self.UA,
  31 + "X-Line-Application" : self.LA,
  32 + "X-Line-Access": authToken
  33 + });
  34 + self.protocol = TCompactProtocol.TCompactProtocol(self.transport);
  35 + self.client = LineService.Client(self.protocol)
  36 + self.rev = self.client.getLastOpRevision()
  37 + self.transport.path = self.polling_path
  38 + self.transport.open()
  39 +
  40 + def stream(self, sleep=50000):
  41 + #usleep = lambda x: time.sleep(x/1000000.0)
  42 + while True:
  43 + try:
  44 + Ops = self.client.fetchOps(self.rev, 5)
  45 + except EOFError:
  46 + raise Exception("It might be wrong revision\n" + str(self.rev))
  47 +
  48 + for Op in Ops:
  49 + # print Op.type
  50 + if (Op.type != OpType.END_OF_OPERATION):
  51 + self.rev = max(self.rev, Op.revision)
  52 + return Op
  53 +
  54 + #usleep(sleep)
... ...
LINETCR/Api/Talk.py 0 โ†’ 100644
  1 +# -*- coding: utf-8 -*-
  2 +import os, sys
  3 +path = os.path.join(os.path.dirname(__file__), '../lib/')
  4 +sys.path.insert(0, path)
  5 +
  6 +import requests, rsa
  7 +
  8 +from thrift.transport import THttpClient
  9 +from thrift.protocol import TCompactProtocol
  10 +
  11 +from curve import LineService
  12 +from curve.ttypes import *
  13 +
  14 +class Talk:
  15 + client = None
  16 +
  17 + auth_query_path = "/api/v4/TalkService.do";
  18 + http_query_path = "/S4";
  19 + wait_for_mobile_path = "/Q";
  20 + host = "gd2.line.naver.jp";
  21 + port = 443;
  22 +
  23 + UA = "Line/1.4.17"
  24 +# LA = "IOSIPAD\x097.14.0\x09iPhone_OS\x0910.12.0"
  25 + LA = "CHROMEOS\t1.4.17\tChrome_OS\t1"
  26 +
  27 + authToken = None
  28 + cert = None
  29 +
  30 + def __init__(self):
  31 + self.transport = THttpClient.THttpClient('https://gd2.line.naver.jp:443'+self.auth_query_path)
  32 + self.transport.setCustomHeaders({
  33 + "User-Agent" : self.UA,
  34 + "X-Line-Application" : self.LA,
  35 + })
  36 + self.transport.open()
  37 + self.protocol = TCompactProtocol.TCompactProtocol(self.transport);
  38 + self.client = LineService.Client(self.protocol)
  39 +
  40 + def login(self, mail, passwd, cert=None, callback=None):
  41 + self.transport.path = self.auth_query_path
  42 + rsakey = self.client.getRSAKeyInfo(IdentityProvider.LINE)
  43 + crypt = self.__crypt(mail, passwd, rsakey)
  44 +
  45 + result = self.client.loginWithIdentityCredentialForCertificate(
  46 + IdentityProvider.LINE,
  47 + rsakey.keynm,
  48 + crypt,
  49 + True,
  50 + '127.0.0.1',
  51 + 'http://dg.b9dm.com/KoenoKatachi.mp4',
  52 + cert
  53 + )
  54 +
  55 + if result.type == 3:
  56 + callback(result.pinCode)
  57 + header = {"X-Line-Access": result.verifier}
  58 + r = requests.get(url="https://" + self.host + self.wait_for_mobile_path, headers=header)
  59 +
  60 + result = self.client.loginWithVerifierForCerificate(r.json()["result"]["verifier"])
  61 + self.transport.setCustomHeaders({
  62 + "X-Line-Application" : self.LA,
  63 + "User-Agent" : self.UA,
  64 + "X-Line-Access" : result.authToken
  65 + })
  66 +
  67 + self.authToken = result.authToken
  68 + self.cert = result.certificate
  69 + self.transport.path = self.http_query_path
  70 +
  71 + elif result.type == 1:
  72 + self.authToken = result.authToken
  73 + self.cert = result.certificate
  74 + self.transport.setCustomHeaders({
  75 + "X-Line-Application" : self.LA,
  76 + "User-Agent" : self.UA,
  77 + "X-Line-Access" : result.authToken
  78 + })
  79 + self.transport.path = self.http_query_path
  80 +
  81 + def TokenLogin(self, authToken):
  82 + self.transport.setCustomHeaders({
  83 + "X-Line-Application" : self.LA,
  84 + "User-Agent" : self.UA,
  85 + "X-Line-Access" : authToken,
  86 + })
  87 + self.authToken = authToken
  88 + self.transport.path = self.http_query_path
  89 +
  90 + def qrLogin(self, callback):
  91 + self.transport.path = self.auth_query_path
  92 +
  93 + qr = self.client.getAuthQrcode(True, "Bot")
  94 + callback("Copy to Line and Click\nYour LINK QR is: line://au/q/" + qr.verifier)
  95 +
  96 + r = requests.get("https://" + self.host + self.wait_for_mobile_path, headers={
  97 + "X-Line-Application": self.LA,
  98 + "X-Line-Access": qr.verifier,
  99 + })
  100 +
  101 + vr = r.json()["result"]["verifier"]
  102 + lr = self.client.loginWithVerifierForCerificate(vr)
  103 + self.transport.setCustomHeaders({
  104 + "X-Line-Application" : self.LA,
  105 + "User-Agent" : self.UA,
  106 + "X-Line-Access": lr.authToken
  107 + })
  108 + self.authToken = lr.authToken
  109 + self.cert = lr.certificate
  110 + self.transport.path = self.http_query_path
  111 +
  112 +
  113 + def __crypt(self, mail, passwd, RSA):
  114 + message = (chr(len(RSA.sessionKey)) + RSA.sessionKey +
  115 + chr(len(mail)) + mail +
  116 + chr(len(passwd)) + passwd).encode('utf-8')
  117 +
  118 + pub_key = rsa.PublicKey(int(RSA.nvalue, 16), int(RSA.evalue, 16))
  119 + crypto = rsa.encrypt(message, pub_key).encode('hex')
  120 +
  121 + return crypto
... ...
LINETCR/Api/channel.py 0 โ†’ 100644
  1 +# -*- coding: utf-8 -*-
  2 +import os, sys, json
  3 +path = os.path.join(os.path.dirname(__file__), '../lib/')
  4 +sys.path.insert(0, path)
  5 +import requests
  6 +
  7 +from thrift.transport import THttpClient
  8 +from thrift.protocol import TCompactProtocol
  9 +
  10 +from curve import LineService
  11 +from curve.ttypes import *
  12 +import tempfile
  13 +
  14 +class Channel:
  15 + client = None
  16 +
  17 + host = "gd2.line.naver.jp"
  18 + http_query_path = "/S4"
  19 + channel_query_path = "/CH4"
  20 +
  21 + UA = "Line/1.4.17"
  22 + LA = "CHROMEOS\t1.4.17\tChrome_OS\t1"
  23 +
  24 +
  25 + authToken = None
  26 + mid = None
  27 + channel_access_token = None
  28 + token = None
  29 + obs_token = None
  30 + refresh_token = None
  31 +
  32 + def __init__(self, authToken):
  33 + self.authToken = authToken
  34 + self.transport = THttpClient.THttpClient('https://gd2.line.naver.jp:443'+self.http_query_path)
  35 + self.transport.setCustomHeaders({ "User-Agent" : self.UA,
  36 + "X-Line-Application" : self.LA,
  37 + "X-Line-Access": self.authToken
  38 + })
  39 + self.transport.open()
  40 + self.protocol = TCompactProtocol.TCompactProtocol(self.transport)
  41 + self.client = LineService.Client(self.protocol)
  42 + self.mid = self.client.getProfile().mid
  43 + self.transport.path = self.channel_query_path
  44 +
  45 + def login(self):
  46 + result = self.client.issueChannelToken("1341209850")
  47 +
  48 + self.channel_access_token = result.channelAccessToken
  49 + self.token = result.token
  50 + self.obs_token = result.obsToken
  51 + self.refresh_token = result.refreshToken
  52 +
  53 + print "channelAccessToken:" + result.channelAccessToken
  54 + print "token:" + result.token
  55 + print "obs_token:" + result.obsToken
  56 + print "refreshToken:" + result.refreshToken
  57 +
  58 + def new_post(self, text):
  59 +
  60 + header = {
  61 + "Content-Type": "application/json",
  62 + "User-Agent" : self.UA,
  63 + "X-Line-Mid" : self.mid,
  64 + "x-lct" : self.channel_access_token,
  65 + }
  66 +
  67 + payload = {
  68 + "postInfo" : { "readPermission" : { "type" : "ALL" } },
  69 + "sourceType" : "TIMELINE",
  70 + "contents" : { "text" : text }
  71 + }
  72 +
  73 + r = requests.post(
  74 + "http://" + self.host + "/mh/api/v24/post/create.json",
  75 + headers = header,
  76 + data = json.dumps(payload)
  77 + )
  78 +
  79 + return r.json()
  80 +
  81 + def postPhoto(self,text,path):
  82 + header = {
  83 + "Content-Type": "application/json",
  84 + "User-Agent" : self.UA,
  85 + "X-Line-Mid" : self.mid,
  86 + "x-lct" : self.channel_access_token,
  87 + }
  88 +
  89 + payload = {
  90 + "postInfo" : { "readPermission" : { "type" : "ALL" } },
  91 + "sourceType" : "TIMELINE",
  92 + "contents" : { "text" : text ,"media" : [{u'objectId': u'F57144CF9ECC4AD2E162E68554D1A8BD1a1ab0t04ff07f6'}]}
  93 + }
  94 + r = requests.post(
  95 + "http://" + self.host + "/mh/api/v24/post/create.json",
  96 + headers = header,
  97 + data = json.dumps(payload)
  98 + )
  99 +
  100 + return r.json()
  101 +
  102 + def like(self, mid, postid, likeType=1001):
  103 +
  104 + header = {
  105 + "Content-Type" : "application/json",
  106 + "X-Line-Mid" : self.mid,
  107 + "x-lct" : self.channel_access_token,
  108 + }
  109 +
  110 + payload = {
  111 + "likeType" : likeType,
  112 + "activityExternalId" : postid,
  113 + "actorId" : mid
  114 + }
  115 +
  116 + r = requests.post(
  117 + "http://" + self.host + "/mh/api/v23/like/create.json?homeId=" + mid,
  118 + headers = header,
  119 + data = json.dumps(payload)
  120 + )
  121 +
  122 + return r.json()
  123 +
  124 + def comment(self, mid, postid, text):
  125 + header = {
  126 + "Content-Type" : "application/json",
  127 + "X-Line-Mid" : self.mid,
  128 + "x-lct" : self.channel_access_token,
  129 + }
  130 +
  131 + payload = {
  132 + "commentText" : text,
  133 + "activityExternalId" : postid,
  134 + "actorId" : mid
  135 + }
  136 +
  137 + r = requests.post(
  138 + "http://" + self.host + "/mh/api/v23/comment/create.json?homeId=" + mid,
  139 + headers = header,
  140 + data = json.dumps(payload)
  141 + )
  142 +
  143 + return r.json()
  144 +
  145 + def activity(self, limit=20):
  146 +
  147 + header = {
  148 + "Content-Type" : "application/json",
  149 + "X-Line-Mid" : self.mid,
  150 + "x-lct" : self.channel_access_token,
  151 + }
  152 +
  153 + r = requests.get(
  154 + "http://" + self.host + "/tl/mapi/v21/activities?postLimit=" + str(limit),
  155 + headers = header
  156 + )
  157 + return r.json()
  158 + def getAlbum(self, gid):
  159 +
  160 + header = {
  161 + "Content-Type" : "application/json",
  162 + "X-Line-Mid" : self.mid,
  163 + "x-lct": self.channel_access_token,
  164 +
  165 + }
  166 +
  167 + r = requests.get(
  168 + "http://" + self.host + "/mh/album/v3/albums?type=g&sourceType=TALKROOM&homeId=" + gid,
  169 + headers = header
  170 + )
  171 + return r.json()
  172 + def changeAlbumName(self,gid,name,albumId):
  173 + header = {
  174 + "Content-Type" : "application/json",
  175 + "X-Line-Mid" : self.mid,
  176 + "x-lct": self.channel_access_token,
  177 +
  178 + }
  179 + payload = {
  180 + "title": name
  181 + }
  182 + r = requests.put(
  183 + "http://" + self.host + "/mh/album/v3/album/" + albumId + "?homeId=" + gid,
  184 + headers = header,
  185 + data = json.dumps(payload),
  186 + )
  187 + return r.json()
  188 + def deleteAlbum(self,gid,albumId):
  189 + header = {
  190 + "Content-Type" : "application/json",
  191 + "X-Line-Mid" : self.mid,
  192 + "x-lct": self.channel_access_token,
  193 +
  194 + }
  195 + r = requests.delete(
  196 + "http://" + self.host + "/mh/album/v3/album/" + albumId + "?homeId=" + gid,
  197 + headers = header,
  198 + )
  199 + return r.json()
  200 + def getNote(self,gid, commentLimit, likeLimit):
  201 + header = {
  202 + "Content-Type" : "application/json",
  203 + "X-Line-Mid" : self.mid,
  204 + "x-lct": self.channel_access_token,
  205 +
  206 + }
  207 + r = requests.get(
  208 + "http://" + self.host + "/mh/api/v27/post/list.json?homeId=" + gid + "&commentLimit=" + commentLimit + "&sourceType=TALKROOM&likeLimit=" + likeLimit,
  209 + headers = header
  210 + )
  211 + return r.json()
  212 +
  213 + def postNote(self, gid, text):
  214 + header = {
  215 + "Content-Type": "application/json",
  216 + "User-Agent" : self.UA,
  217 + "X-Line-Mid" : self.mid,
  218 + "x-lct" : self.channel_access_token,
  219 + }
  220 + payload = {"postInfo":{"readPermission":{"homeId":gid}},
  221 + "sourceType":"GROUPHOME",
  222 + "contents":{"text":text}
  223 + }
  224 + r = requests.post(
  225 + "http://" + self.host + "/mh/api/v27/post/create.json",
  226 + headers = header,
  227 + data = json.dumps(payload)
  228 + )
  229 + return r.json()
  230 +
  231 + def getDetail(self, mid):
  232 + header = {
  233 + "Content-Type": "application/json",
  234 + "User-Agent" : self.UA,
  235 + "X-Line-Mid" : self.mid,
  236 + "x-lct" : self.channel_access_token,
  237 + }
  238 +
  239 + r = requests.get(
  240 + "http://" + self.host + "/ma/api/v1/userpopup/getDetail.json?userMid=" + mid,
  241 + headers = header
  242 + )
  243 + return r.json()
  244 +
  245 + def getHome(self,mid):
  246 + header = {
  247 + "Content-Type": "application/json",
  248 + "User-Agent" : self.UA,
  249 + "X-Line-Mid" : self.mid,
  250 + "x-lct" : self.channel_access_token,
  251 + }
  252 +
  253 + r = requests.get(
  254 + "http://" + self.host + "/mh/api/v27/post/list.json?homeId=" + mid + "&commentLimit=2&sourceType=LINE_PROFILE_COVER&likeLimit=6",
  255 + headers = header
  256 + )
  257 + return r.json()
  258 + def getCover(self,mid):
  259 + h = self.getHome(mid)
  260 + objId = h["result"]["homeInfo"]["objectId"]
  261 + return "http://dl.profile.line-cdn.net/myhome/c/download.nhn?userid=" + mid + "&oid=" + objId
  262 + def createAlbum(self,gid,name):
  263 + header = {
  264 + "Content-Type": "application/json",
  265 + "User-Agent" : self.UA,
  266 + "X-Line-Mid" : self.mid,
  267 + "x-lct" : self.channel_access_token,
  268 + }
  269 + payload = {
  270 + "type" : "image",
  271 + "title" : name
  272 + }
  273 + r = requests.post(
  274 + "http://" + self.host + "/mh/album/v3/album?count=1&auto=0&homeId=" + gid,
  275 + headers = header,
  276 + data = json.dumps(payload)
  277 + )
  278 + return r.json()
  279 +
  280 + def createAlbum2(self,gid,name,path,oid):
  281 + header = {
  282 + "Content-Type": "application/json",
  283 + "User-Agent" : self.UA,
  284 + "X-Line-Mid" : self.mid,
  285 + "x-lct" : self.channel_access_token,
  286 + }
  287 + payload = {
  288 + "type" : "image",
  289 + "title" : name
  290 + }
  291 + r = requests.post(
  292 + "http://" + self.host + "/mh/album/v3/album?count=1&auto=0&homeId=" + gid,
  293 + headers = header,
  294 + data = json.dumps(payload)
  295 + )
  296 + #albumId = r.json()["result"]["items"][0]["id"]
  297 +
  298 +
  299 + #h = {
  300 + # "Content-Type": "application/x-www-form-urlencoded",
  301 + # "User-Agent" : self.UA,
  302 + # "X-Line-Mid" : gid,
  303 + # "X-Line-Album" : albumId,
  304 + # "x-lct" : self.channel_access_token,
  305 + #"x-obs-host" : "obs-jp.line-apps.com:443",
  306 +
  307 + #}
  308 + #print r.json()
  309 + #files = {
  310 + # 'file': open(path, 'rb'),
  311 + #}
  312 + #p = {
  313 + # "userid" : gid,
  314 + # "type" : "image",
  315 + # "oid" : oid,
  316 + # "ver" : "1.0"
  317 + #}
  318 + #data = {
  319 + # 'params': json.dumps(p)
  320 + #}
  321 + #r = requests.post(
  322 + #"http://obs-jp.line-apps.com/oa/album/a/object_info.nhn:443",
  323 + #headers = h,
  324 + #data = data,
  325 + #files = files
  326 + #)
  327 + return r.json()
  328 + #cl.createAlbum("cea9d61ba824e937aaf91637991ac934b","ss3ai","kawamuki.png")
... ...