mirror of
https://github.com/hyper-neptune/yuuki.git
synced 2024-12-26 06:40:57 +08:00
Update
This commit is contained in:
parent
a0f7b60739
commit
ead0b1335f
8 changed files with 344 additions and 13 deletions
42
README.md
42
README.md
|
@ -1,8 +1,8 @@
|
|||
Star Yuuki(pYthon) BOT - Yuuki
|
||||
==================
|
||||
![Version](https://img.shields.io/badge/v6.3.2-OpenSource-33FF33.svg) ![License](https://img.shields.io/badge/license-MPL--2.0-FF8800.svg) ![Python](https://img.shields.io/badge/python-2.x-0066FF.svg)
|
||||
![Version](https://img.shields.io/badge/v6.5.0-OpenSource-33FF33.svg) ![License](https://img.shields.io/badge/license-MPL--2.0-FF8800.svg) ![Python](https://img.shields.io/badge/python-3.x-0066FF.svg)
|
||||
|
||||
A LINE Unofficial API Python BOT by SA Kingdom and Star Inc.
|
||||
A Python BOT for LINE Group Protection with LINE Unofficial API.
|
||||
![ICON](logo.png)
|
||||
|
||||
## Maybe you had seen it !
|
||||
|
@ -13,26 +13,42 @@ Now, it is OpenSource.
|
|||
This software using Mozilla Public License 2.0.
|
||||
|
||||
## Warning
|
||||
The project was stopped in 2017/06. So the latest stable version is "v6.3.2". Some function of old version maybe will make your LINE account be banned.
|
||||
The latest stable version is "v6.5.0".
|
||||
|
||||
Some function of old version maybe will make your LINE account be banned.
|
||||
|
||||
## Requires
|
||||
python >= 2.6 (Python 3 Not Support)
|
||||
thrift >= 0.11.0
|
||||
[!] Run with GNU/Linux only
|
||||
|
||||
### Before v6.5.0:
|
||||
It was used the edited version of [carpedm20/LINE](https://github.com/carpedm20/LINE) API to run the Application. So you need to make the LINEAPI for it.
|
||||
Recommand Environment:
|
||||
|
||||
### After (Future):
|
||||
You need the "LINE Unofficial API Python Core" only. (Ex:[olsb](https://github.com/star-inc/olsb_cores), [akad](https://pypi.org/project/akad), [curve](https://pypi.org/project/curve) ...)
|
||||
Ubuntu >= 18.04
|
||||
python >= 3.7
|
||||
pip >= 19.2
|
||||
|
||||
## Old Version
|
||||
Maybe you want the history version of SYB. Click [it](https://github.com/star-inc/star_yuuki_bot/releases/tag/old-versions).
|
||||
You need the "LINE Unofficial API Core for Python". (Ex:[olsb](https://github.com/star-inc/olsb_cores), [akad](https://pypi.org/project/akad), [curve](https://pypi.org/project/curve) ...)
|
||||
|
||||
Please place the core directory in `./libs/`
|
||||
|
||||
## Installation
|
||||
|
||||
+ Check your system environment(Operating System, Requirements..)
|
||||
|
||||
+ Exec:
|
||||
|
||||
|
||||
pip install -Ur requirements.txt
|
||||
|
||||
## Usage
|
||||
+ Config your connection infomations in `main.py`
|
||||
|
||||
+ Exec:
|
||||
|
||||
|
||||
python main.py
|
||||
|
||||
### Notice
|
||||
The helpers of the project("syb-sc", "syb-ab") have not been OpenSource. And "4syb" is a part of [StarNeptuneBOT](https://starinc.xyz/snb).
|
||||
## Old Version
|
||||
Maybe you want the source of history version. Click [it](https://github.com/star-inc/star_yuuki_bot/releases/tag/old-versions).
|
||||
|
||||
### Logo Copyright
|
||||
Copyright of the Image which was named "logo.png" belogs to "[ ©川原 礫/ASCII Media Works/SAO Project](https://www.aniplex.co.jp)".
|
||||
|
|
1
libs/__init__.py
Normal file
1
libs/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
__all__ = ['function', 'connection']
|
58
libs/connection.py
Normal file
58
libs/connection.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/python3
|
||||
# coding=UTF-8
|
||||
|
||||
from .core.TalkService import Client
|
||||
|
||||
from thrift.transport import THttpClient
|
||||
from thrift.protocol import TCompactProtocol
|
||||
|
||||
""" NC HightSpeed Lib """
|
||||
try:
|
||||
from thrift.protocol import fastbinary
|
||||
except:
|
||||
fastbinary = None
|
||||
##########################################
|
||||
|
||||
class Yuuki_Connection:
|
||||
""" Connection Dict Type """
|
||||
|
||||
connectInfo = {
|
||||
"Host": "",
|
||||
"Command_Path": "",
|
||||
"LongPoll_path": ""
|
||||
}
|
||||
|
||||
connectHeader = {
|
||||
"X-Line-Application": "",
|
||||
"X-Line-Access": "",
|
||||
"User-Agent": ""
|
||||
}
|
||||
|
||||
|
||||
|
||||
class YuukiConnect:
|
||||
def __init__(self, Yuuki_Connection):
|
||||
|
||||
self.host = Yuuki_Connection.connectInfo["Host"]
|
||||
self.com_path = Yuuki_Connection.connectInfo["Command_Path"]
|
||||
self.poll_path = Yuuki_Connection.connectInfo["LongPoll_path"]
|
||||
|
||||
self.con_header = Yuuki_Connection.connectHeader
|
||||
|
||||
def connect(self):
|
||||
transport = THttpClient.THttpClient(self.host + self.com_path)
|
||||
transport_in = THttpClient.THttpClient(self.host + self.poll_path)
|
||||
|
||||
transport.setCustomHeaders(self.con_header)
|
||||
transport_in.setCustomHeaders(self.con_header)
|
||||
|
||||
protocol = TCompactProtocol.TCompactProtocol(transport)
|
||||
protocol_in = TCompactProtocol.TCompactProtocol(transport_in)
|
||||
|
||||
client = Client(protocol)
|
||||
listen = Client(protocol_in)
|
||||
|
||||
transport.open()
|
||||
transport_in.open()
|
||||
|
||||
return client, listen
|
6
libs/data.py
Normal file
6
libs/data.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/python3
|
||||
# coding=UTF-8
|
||||
|
||||
class Yuuki_Data:
|
||||
def __init__(self):
|
||||
pass
|
192
libs/function.py
Normal file
192
libs/function.py
Normal file
|
@ -0,0 +1,192 @@
|
|||
#!/usr/bin/python3
|
||||
# coding=UTF-8
|
||||
|
||||
import os, time,\
|
||||
requests, \
|
||||
json, ntpath
|
||||
|
||||
from libs.core.TalkService import *
|
||||
from .connection import YuukiConnect
|
||||
|
||||
class Yuuki:
|
||||
def __init__(self, Seq, Yuuki_Connection, Accounts, Admin=[]):
|
||||
self.Seq = Seq
|
||||
self.LINE_Media_server = "https://obs.line-apps.com"
|
||||
|
||||
Connect = YuukiConnect(Yuuki_Connection)
|
||||
|
||||
(self.client, self.listen) = Connect.connect()
|
||||
self.connectHeader = Yuuki_Connection.connectHeader
|
||||
|
||||
self.MyMID = self.client.getProfile().mid
|
||||
|
||||
def exit(restart=False):
|
||||
if restart:
|
||||
Catched = open(".cache.sh", "w")
|
||||
Catched.write(sys.executable + " ./bot.py")
|
||||
Catched.close()
|
||||
os.system("sh .cache.sh")
|
||||
os.system("rm .cache.sh")
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(0)
|
||||
|
||||
def readCommandLine(self, msgs):
|
||||
replymsg = ""
|
||||
for msg in msgs:
|
||||
replymsg = replymsg + " " + msg
|
||||
return replymsg
|
||||
|
||||
def checkInInvitationList(self, ncMessage):
|
||||
if ncMessage.param3 == self.MyMID:
|
||||
inList = True
|
||||
elif "\x1e" in ncMessage.param3:
|
||||
if self.MyMID in ncMessage.param3.split("\x1e"):
|
||||
inList = True
|
||||
else:
|
||||
inList = False
|
||||
else:
|
||||
inList = False
|
||||
return inList
|
||||
|
||||
def changeGroupUrlStatus(self, group, stat):
|
||||
if stat == True:
|
||||
us = False
|
||||
else:
|
||||
us = True
|
||||
group.members, group.invitee = None, None
|
||||
group.preventJoinByTicket = us
|
||||
self.client.send_updateGroup(self.Seq, group)
|
||||
|
||||
def cleanMyGroupInvitations(self):
|
||||
for cleanInvitations in self.client.getGroupIdsInvited():
|
||||
self.client.send_acceptGroupInvitation(self.Seq, cleanInvitations)
|
||||
self.client.send_leaveGroup(self.Seq, cleanInvitations)
|
||||
|
||||
def getContact(self, mid):
|
||||
if len(mid) == len(self.MyMID) and mid[0] == "u":
|
||||
try:
|
||||
contactInfo = self.getContact(mid)
|
||||
except:
|
||||
contactInfo = False
|
||||
else:
|
||||
contactInfo = False
|
||||
return contactInfo
|
||||
|
||||
def sendToWho(self, Message):
|
||||
if Message.message.toType == MIDType.USER:
|
||||
return Message.message.from_
|
||||
elif Message.message.toType == MIDType.ROOM:
|
||||
return Message.message.to
|
||||
elif Message.message.toType == MIDType.GROUP:
|
||||
return Message.message.to
|
||||
|
||||
def sendText(self, toid, msg):
|
||||
message = Message(to=toid, text=msg.encode('utf-8'))
|
||||
self.client.send_sendMessage(self.Seq, message)
|
||||
|
||||
def sendUser(self, toid, mid):
|
||||
message = Message(contentType=ContentType.CONTACT,
|
||||
text='',
|
||||
contentMetadata={
|
||||
'mid': mid,
|
||||
'displayName': 'LINE User',
|
||||
},
|
||||
to=toid)
|
||||
self.client.send_sendMessage(self.Seq, message)
|
||||
|
||||
def sendMedia(self, toid, type, path):
|
||||
if os.path.exists(path):
|
||||
file_name = ntpath.basename(path)
|
||||
file_size = len(open(path, 'rb').read())
|
||||
message = Message(to=toid, text=None)
|
||||
message.contentType = type
|
||||
message.contentPreview = None
|
||||
message.contentMetadata = {
|
||||
'FILE_NAME': str(file_name),
|
||||
'FILE_SIZE': str(file_size),
|
||||
}
|
||||
if type == ContentType.FILE:
|
||||
media_name = file_name
|
||||
else:
|
||||
media_name = 'media'
|
||||
message_id = self.client.sendMessage(self.Seq, message).id
|
||||
files = {
|
||||
'file': open(path, 'rb'),
|
||||
}
|
||||
params = {
|
||||
'name': media_name,
|
||||
'oid': message_id,
|
||||
'size': file_size,
|
||||
'type': ContentType._VALUES_TO_NAMES[type].lower(),
|
||||
'ver': '1.0',
|
||||
}
|
||||
data = {
|
||||
'params': json.dumps(params)
|
||||
}
|
||||
url = self.LINE_Media_server + '/talk/m/upload.nhn'
|
||||
r = requests.post(url, headers=self.connectHeader, data=data, files=files)
|
||||
if r.status_code != 201:
|
||||
self.client.sendText(toid, "Error!")
|
||||
|
||||
def Poll(self):
|
||||
NoWork = 0
|
||||
catchedNews = []
|
||||
ncMessage = Operation()
|
||||
Revision = self.client.getLastOpRevision()
|
||||
while True:
|
||||
try:
|
||||
if NoWork == 300:
|
||||
Revision = self.client.getLastOpRevision()
|
||||
catchedNews = self.listen.fetchOperations(Revision, 50)
|
||||
if catchedNews:
|
||||
NoWork = 0
|
||||
for ncMessage in catchedNews:
|
||||
if ncMessage.type == OpType.RECEIVE_MESSAGE:
|
||||
self.Commands(ncMessage)
|
||||
elif ncMessage.type == OpType.NOTIFIED_INVITE_INTO_GROUP:
|
||||
self.Main(ncMessage)
|
||||
if ncMessage.reqSeq != -1:
|
||||
Revision = max(Revision, ncMessage.revision)
|
||||
else:
|
||||
NoWork = NoWork + 1
|
||||
except SystemExit:
|
||||
self.exit()
|
||||
except EOFError:
|
||||
pass
|
||||
except:
|
||||
err1, err2, err3 = sys.exc_info()
|
||||
try:
|
||||
if catchedNews and ncMessage:
|
||||
Finded = False
|
||||
for Catched in catchedNews:
|
||||
if Catched.revision == ncMessage.revision:
|
||||
Finded = True
|
||||
if Finded:
|
||||
Revision = Catched.revision
|
||||
break
|
||||
if not Finded:
|
||||
Revision = self.client.getLastOpRevision()
|
||||
for Root in self.permission["Admin"]:
|
||||
self.sendText(Root, "Star Yuuki BOT - Something was wrong...\nError:\n%s\n%s\n%s" %
|
||||
(err1, err2, err3))
|
||||
except:
|
||||
print("Star Yuuki BOT - Damage!\nError:\n%s\n%s\n%s" % (err1, err2, err3))
|
||||
self.exit()
|
||||
|
||||
def Main(self, ncMessage):
|
||||
pass
|
||||
|
||||
def Commands(self, ncMessage):
|
||||
if 'BOT_CHECK' in ncMessage.message.contentMetadata:
|
||||
pass
|
||||
elif ncMessage.message.toType == MIDType.ROOM:
|
||||
self.client.send_leaveRoom(self.Seq, ncMessage.message.to)
|
||||
elif ncMessage.message.contentType == ContentType.NONE:
|
||||
if 'Yuuki/mid' == ncMessage.message.text:
|
||||
self.sendText(self.sendToWho(ncMessage), "LINE System UserID:\n" + ncMessage.message.from_)
|
||||
elif 'Yuuki/Speed' == ncMessage.message.text:
|
||||
Time1 = time.time()
|
||||
self.sendText(self.sendToWho(ncMessage), "Testing...")
|
||||
Time2 = time.time()
|
||||
self.sendText(self.sendToWho(ncMessage), "Speed:\n%ss" % (Time2 - Time1,))
|
6
libs/thread_control.py
Normal file
6
libs/thread_control.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/python3
|
||||
# coding=UTF-8
|
||||
|
||||
class Thread_Control:
|
||||
def __init__(self):
|
||||
pass
|
45
main.py
45
main.py
|
@ -0,0 +1,45 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Star Yuuki Bot - Yuuki
|
||||
~~~~~~~~~~~
|
||||
This is a main program in SYB.
|
||||
It`s belong to Star Yuuki(pYthon) Bot Project of Star Neptune Bot
|
||||
Version: v6.5.0
|
||||
Copyright(c) 2019 Star Inc. All Rights Reserved.
|
||||
"""
|
||||
|
||||
Admin = [""]
|
||||
|
||||
LINE_ACCESS_KEY = ""
|
||||
|
||||
########################Initializing##########################
|
||||
from libs.function import Yuuki
|
||||
from libs.connection import Yuuki_Connection
|
||||
|
||||
Connection = Yuuki_Connection()
|
||||
|
||||
Connection.connectInfo = {
|
||||
'Host': '',
|
||||
'Command_Path': '',
|
||||
'LongPoll_path': ''
|
||||
}
|
||||
|
||||
Connection.connectHeader = {
|
||||
'X-Line-Application': '',
|
||||
'X-Line-Access': LINE_ACCESS_KEY,
|
||||
'User-Agent': ''
|
||||
}
|
||||
|
||||
Seq = 0
|
||||
Accounts = []
|
||||
|
||||
Console = Yuuki(Seq, Connection, Accounts, Admin)
|
||||
Console.cleanMyGroupInvitations()
|
||||
|
||||
##############################################################
|
||||
|
||||
###########################Start!#############################
|
||||
print("Star Yuuki BOT - Start Successful!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
Console.Poll()
|
7
requirements.txt
Normal file
7
requirements.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
certifi==2019.6.16
|
||||
chardet==3.0.4
|
||||
idna==2.8
|
||||
requests==2.22.0
|
||||
six==1.12.0
|
||||
thrift==0.11.0
|
||||
urllib3==1.25.3
|
Loading…
Reference in a new issue