Commit 711947d5be2465574ac9a21180231c4e42828ea7

Authored by rizqiqiqi
Committed by GitHub
1 parent 3017e0f0

Add files via upload

LineAlpha/Api/LineTracer.py 0 → 100644
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +from .LineClient import LineClient
  4 +from types import *
  5 +from ..lib.Gen.ttypes import OpType
  6 +from ..Net.LineServer import url
  7 +
  8 +
  9 +class LineTracer(object):
  10 + OpInterrupt = {}
  11 + client = None
  12 +
  13 + def __init__(self, client):
  14 + if type(client) is not LineClient:
  15 + raise Exception(
  16 + "You need to set LineClient instance to initialize LineTracer")
  17 +
  18 + self.client = client
  19 + self.client.endPoint(url.LONG_POLLING)
  20 +
  21 + def addOpInterruptWithDict(self, OpInterruptDict):
  22 + """To add Operation with Callback function {Optype.NOTIFIED_INTO_GROUP: func}"""
  23 + self.OpInterrupt.update(OpInterruptDict)
  24 +
  25 + def addOpInterrupt(self, OperationType, DisposeFunc):
  26 + self.OpInterrupt[OperationType] = DisposeFunc
  27 +
  28 + def execute(self):
  29 + try:
  30 + operations = self.client.fetchOperation(self.client.revision, 10)
  31 + #print "======================================================="
  32 + # print operations
  33 + #print "======================================================="
  34 + except EOFError:
  35 + return
  36 + except KeyboardInterrupt:
  37 + exit()
  38 + except:
  39 + return
  40 +
  41 + for op in operations:
  42 + if op.type in self.OpInterrupt.keys():
  43 + #print "======================================================="
  44 + #print str(op.type) + "[" + str(op) + "]"
  45 + #print "======================================================="
  46 + self.OpInterrupt[op.type](op)
  47 +
  48 + self.client.revision = max(op.revision, self.client.revision)
... ...
LineAlpha/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 Gen import LineService
  9 +from Gen.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/6.0.0 iPad4,1 9.0.2"
  22 + LA = "IOSIPAD 6.0.0 iPhone OS 9.0.2"
  23 +
  24 + rev = 0
  25 +
  26 + def __init__(self, authToken):
  27 + self.transport = THttpClient.THttpClient(self.host, self.port, self.http_query_path)
  28 + self.transport.setCustomHeaders({
  29 + "User-Agent" : self.UA,
  30 + "X-Line-Application" : self.LA,
  31 + "X-Line-Access": authToken
  32 + });
  33 + self.protocol = TCompactProtocol.TCompactProtocol(self.transport);
  34 + self.client = LineService.Client(self.protocol)
  35 + self.rev = self.client.getLastOpRevision()
  36 + self.transport.path = self.polling_path
  37 + self.transport.open()
  38 +
  39 + def stream(self, sleep=50000):
  40 + usleep = lambda x: time.sleep(x/1000000.0)
  41 + while True:
  42 + try:
  43 + Ops = self.client.fetchOps(self.rev, 5, 0, 0)
  44 + except EOFError:
  45 + raise Exception("It might be wrong revision\n" + str(self.rev))
  46 +
  47 + for Op in Ops:
  48 + # print Op.type
  49 + if (Op.type != OpType.END_OF_OPERATION):
  50 + self.rev = max(self.rev, Op.revision)
  51 + return Op
  52 +
  53 + usleep(sleep)
... ...
LineAlpha/Api/Poll.pyc 0 → 100644
No preview for this file type
LineAlpha/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 Gen import LineService
  12 +from Gen.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/6.0.0 iPad4,1 9.0.2"
  24 + LA = "IOSIPAD 6.0.0 iPhone OS 9.0.2"
  25 +
  26 + authToken = None
  27 + cert = None
  28 +
  29 + def __init__(self):
  30 + self.transport = THttpClient.THttpClient(self.host, self.port, self.http_query_path)
  31 + self.transport.setCustomHeaders({
  32 + "User-Agent" : self.UA,
  33 + "X-Line-Application" : self.LA,
  34 + })
  35 + self.transport.open()
  36 + self.protocol = TCompactProtocol.TCompactProtocol(self.transport);
  37 + self.client = LineService.Client(self.protocol)
  38 +
  39 + def login(self, mail, passwd, cert=None, callback=None):
  40 + self.transport.path = self.auth_query_path
  41 + rsakey = self.client.getRSAKeyInfo(IdentityProvider.LINE)
  42 + crypt = self.__crypt(mail, passwd, rsakey)
  43 +
  44 + result = self.client.loginWithIdentityCredentialForCertificate(
  45 + IdentityProvider.LINE,
  46 + rsakey.keynm,
  47 + crypt,
  48 + True,
  49 + '127.0.0.1',
  50 + 'LemonBOT',
  51 + cert
  52 + )
  53 +
  54 + if result.type == 3:
  55 + callback(result.pinCode)
  56 + header = {"X-Line-Access": result.verifier}
  57 + r = requests.get(url="http://" + self.host + self.wait_for_mobile_path, headers=header)
  58 +
  59 + result = self.client.loginWithVerifierForCerificate(r.json()["result"]["verifier"])
  60 + self.transport.setCustomHeaders({
  61 + "X-Line-Application" : self.LA,
  62 + "User-Agent" : self.UA,
  63 + "X-Line-Access" : result.authToken
  64 + })
  65 +
  66 + self.authToken = result.authToken
  67 + self.cert = result.certificate
  68 + self.transport.path = self.http_query_path
  69 +
  70 + elif result.type == 1:
  71 + self.authToken = result.authToken
  72 + self.cert = result.certificate
  73 + self.transport.setCustomHeaders({
  74 + "X-Line-Application" : self.LA,
  75 + "User-Agent" : self.UA,
  76 + "X-Line-Access" : result.authToken
  77 + })
  78 + self.transport.path = self.http_query_path
  79 +
  80 + def TokenLogin(self, authToken):
  81 + self.transport.setCustomHeaders({
  82 + "X-Line-Application" : self.LA,
  83 + "User-Agent" : self.UA,
  84 + "X-Line-Access" : authToken,
  85 + })
  86 + self.authToken = authToken
  87 + self.transport.path = self.http_query_path
  88 +
  89 + def qrLogin(self, callback):
  90 + self.transport.path = self.auth_query_path
  91 +
  92 + qr = self.client.getAuthQrcode(True, "LemonBOT")
  93 + callback("line://au/q/" + qr.verifier)
  94 +
  95 + r = requests.get("http://" + self.host + self.wait_for_mobile_path, headers={
  96 + "X-Line-Application": self.LA,
  97 + "X-Line-Access": qr.verifier,
  98 + })
  99 +
  100 + vr = r.json()["result"]["verifier"]
  101 + lr = self.client.loginWithVerifierForCerificate(vr)
  102 + self.transport.setCustomHeaders({
  103 + "X-Line-Application" : self.LA,
  104 + "User-Agent" : self.UA,
  105 + "X-Line-Access": lr.authToken
  106 + })
  107 + self.authToken = lr.authToken
  108 + self.cert = lr.certificate
  109 + self.transport.path = self.http_query_path
  110 +
  111 +
  112 + def __crypt(self, mail, passwd, RSA):
  113 + message = (chr(len(RSA.sessionKey)) + RSA.sessionKey +
  114 + chr(len(mail)) + mail +
  115 + chr(len(passwd)) + passwd).encode('utf-8')
  116 +
  117 + pub_key = rsa.PublicKey(int(RSA.nvalue, 16), int(RSA.evalue, 16))
  118 + crypto = rsa.encrypt(message, pub_key).encode('hex')
  119 +
  120 + return crypto
... ...
LineAlpha/Api/Talk.pyc 0 → 100644
No preview for this file type
LineAlpha/Api/__init__.py 0 → 100644
  1 +from Talk import Talk
  2 +from Poll import Poll
  3 +from channel import Channel
... ...
LineAlpha/Api/__init__.pyc 0 → 100644
No preview for this file type
LineAlpha/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 Gen import LineService
  11 +from Gen.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/6.0.0 iPad4,1 9.0.2"
  22 +
  23 + LA = "IOSIPAD 6.0.0 iPhone OS 9.0.2"
  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(self.host, 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("1341209950")
  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")
... ...
LineAlpha/Api/channel.pyc 0 → 100644
No preview for this file type