Merge pull request #22 from star-inc/rolling

v6.5.3-alpha_RC2 from Rolling
This commit is contained in:
SuperSonic 2020-03-14 14:12:41 +08:00 committed by GitHub
commit 418d412ad6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 98 additions and 118 deletions

View file

@ -1,23 +1,27 @@
Star Yuuki(pYthon) BOT - Yuuki
==================
# Star Yuuki(pYthon) BOT - Yuuki
![Version](https://img.shields.io/badge/v6.5.3-OpenSource-FF0033.svg) ![Series](https://img.shields.io/badge/syb-Series-7700FF.svg) ![License](https://img.shields.io/badge/license-MPL--2.0-FF6600.svg) ![Python](https://img.shields.io/badge/python-3.x-0066FF.svg) ![Platform](https://img.shields.io/badge/base_on-LINE-00DD00.svg)
[![Scrutinizer-CI_Build](https://scrutinizer-ci.com/g/star-inc/star_yuuki_bot/badges/build.png?b=master) ![Scrutinizer-CI_Quality](https://scrutinizer-ci.com/g/star-inc/star_yuuki_bot/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/star-inc/star_yuuki_bot/) [![Code-Inspector_Score](https://www.code-inspector.com/project/3632/score/svg) ![Code-Inspector_Score](https://www.code-inspector.com/project/3632/status/svg)](https://frontend.code-inspector.com/public/project/3632/star_yuuki_bot/dashboard)
[![Scrutinizer-CI_Build](https://scrutinizer-ci.com/g/star-inc/star_yuuki_bot/badges/build.png?b=rolling) ![Scrutinizer-CI_Quality](https://scrutinizer-ci.com/g/star-inc/star_yuuki_bot/badges/quality-score.png?b=rolling)](https://scrutinizer-ci.com/g/star-inc/star_yuuki_bot/) [![Code-Inspector_Score](https://www.code-inspector.com/project/3632/score/svg) ![Code-Inspector_Score](https://www.code-inspector.com/project/3632/status/svg)](https://frontend.code-inspector.com/public/project/3632/star_yuuki_bot/dashboard)
A Python BOT for LINE Group Protection.
![ICON](logo.png)
## Maybe you had seen it !
Yeah! This is the BOT which was the first Chinese LINE Group Security BOT.
Now, it is OpenSource.
## License
The software licensed under [Mozilla Public License 2.0](LICENSE.md) with [COPYING.md](COPYING.md).
## Warning
Some function of old version maybe will make your LINE account be banned.
## Requirement
Recommend Environment:
Ubuntu >= 18.04
@ -26,27 +30,29 @@ Recommend Environment:
git >= 2.17
## Setup
+ Check your system environment(Operating System, Requirements...)
+ Exec:
+ Execute:
pip install -Ur requirements.txt
`pip install -Ur requirements.txt`
## Usage
+ Copy `config.yaml` from `config.sample.yaml`
+ Configure your settings and environment in `config.yaml`
+ Exec:
+ Execute:
python main.py
`python main.py`
## Old Version
Maybe you want the source of history version. Click [it](https://github.com/star-inc/star_yuuki_bot/releases/tag/old-versions).
Maybe you want the source of history version. [Click me](https://github.com/star-inc/star_yuuki_bot/releases/tag/old-versions)
### Logo Copyright
Copyright of the Image which was named "logo.png" belongs to "[©川原 礫ASCII Media WorksSAO Project](https://www.aniplex.co.jp)".
> (c) 2020 Star Inc.

View file

@ -1,21 +1,17 @@
# Sample Config File for star_yuuki_bot
# Please replace setting options from `libs/config.py`
Yuuki:
SecurityService: True
Default_Language: en
Admin:
-
Hour_KickLimit: 10
Hour_CancelLimit: 10
GroupMebers_Demand: 10
LINE:
Server:
Host:
Command_Path:
LongPoll_path:
Host: https://example.com
Command_Path: /example_path
LongPoll_path: /example_path
Account:
X-Line-Application:
X-Line-Access:
User-Agent:
helper_LINE_ACCESS_KEYs:
-
X-Line-Application: LINE_Application_Identification
X-Line-Access: LINE_Application_AccessKey
User-Agent: LINE_Application_User-Agent

View file

@ -37,7 +37,7 @@ class Yuuki_Config:
systemConfig = {
"name": "Yuuki",
"version": "v6.5.3-alpha_RC1",
"version": "v6.5.3-alpha_RC2",
"version_check": True,
"project_url": "https://tinyurl.com/syb-yuuki",
"man_page": "https://tinyurl.com/yuuki-manual",
@ -57,13 +57,13 @@ class Yuuki_Config:
}
def __init__(self, config_path="config.yaml"):
assert os.path.isfile(config_path), "The configure file, `config.yaml` was not found."
assert os.path.isfile(config_path), "The config file, `config.yaml` was not found."
with open(config_path, "r") as configfile:
self.config = yaml.load(configfile, Loader=yaml.FullLoader)
self._yuuki_config()
def _yuuki_config(self):
assert self.config is not None, "Invalid configure file"
assert self.config is not None, "Invalid config file"
if "Yuuki" in self.config:
for key in self.config["Yuuki"]:
if key in self.systemConfig:

View file

@ -9,7 +9,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
from thrift.protocol import TCompactProtocol
from thrift.transport import THttpClient
from yuuki_core.TalkService import Client
from yuuki_core.TalkService import Client, TalkException
# NC HighSpeed Library
try:
@ -21,16 +21,14 @@ except ImportError:
class Yuuki_Connect:
def __init__(self, Yuuki_Configs):
self.helper = {}
self.host = Yuuki_Configs.connectInfo["Host"]
self.com_path = Yuuki_Configs.connectInfo["Command_Path"]
self.poll_path = Yuuki_Configs.connectInfo["LongPoll_path"]
self.con_header = Yuuki_Configs.connectHeader
self.helper = []
self.helper_ids = []
self.helper_authTokens = {}
def connect(self, listen_timeout=600000):
transport = THttpClient.THttpClient(self.host + self.com_path)
transport_in = THttpClient.THttpClient(self.host + self.poll_path)
@ -51,41 +49,20 @@ class Yuuki_Connect:
return client, listen
def helperConnect(self, LINE_ACCESS_KEY):
helper_ConnectHeader = self.con_header.copy()
helper_ConnectHeader["X-Line-Access"] = LINE_ACCESS_KEY
def helperConnect(self, auth_token):
helper_connect_header = self.con_header.copy()
helper_connect_header["X-Line-Access"] = auth_token
transport = THttpClient.THttpClient(self.host + self.com_path)
transport.setCustomHeaders(helper_ConnectHeader)
transport.setCustomHeaders(helper_connect_header)
protocol = TCompactProtocol.TCompactProtocol(transport)
client = Client(protocol)
transport.open()
# noinspection PyBroadException
try:
profile = client.getProfile()
self.helper.append(client)
self.helper_ids.append(profile.mid)
self.helper_authTokens[profile.mid] = LINE_ACCESS_KEY
self.helper[profile.mid] = client
return True
except:
print("Error:\n%s\nNot Acceptable\n" % (LINE_ACCESS_KEY,))
def helperThreadConnect(self, userId):
if userId in self.helper_authTokens:
LINE_ACCESS_KEY = self.helper_authTokens.get(userId)
else:
return None
helper_ConnectHeader = self.con_header.copy()
helper_ConnectHeader["X-Line-Access"] = LINE_ACCESS_KEY
transport = THttpClient.THttpClient(self.host + self.com_path)
transport.setCustomHeaders(helper_ConnectHeader)
protocol = TCompactProtocol.TCompactProtocol(transport)
client = Client(protocol)
transport.open()
return client
except TalkException:
print("Error:\n%s\nNot Acceptable\n" % (auth_token,))

View file

@ -82,25 +82,16 @@ class Yuuki_Data:
for data_type in self.DataType:
name = self.DataPath + self.DataName.format(data_type)
test_result = 0
if not os.path.isfile(name):
with open(name, "w") as f:
f.write("")
self.Data[data_type] = self.DataType[data_type]
json.dump(f, self.Data[data_type])
else:
with open(name, "r") as f:
try:
json.load(f)
self.Data[data_type] = json.load(f)
except ValueError:
test_result = 1
assert test_result == 0, "{}\nJson Test Error".format(name)
with open(name, "r+") as f:
text = f.read()
if text != "":
self.Data[data_type] = json.loads(text)
else:
self.Data[data_type] = self.DataType[data_type]
f.write(json.dumps(self.Data[data_type]))
assert "{}\nJson Test Error".format(name)
return self._MDS_Initialize()

View file

@ -105,7 +105,7 @@ class PythonMDS:
return {"status": 200}
def _yuuki_limit_decrease(self, data):
self.switch_data["LimitInfo"][data["path"]][data["userId"]] -= 1
self.switch_data["LimitInfo"][data["path"]][data["data"]] -= 1
return {"status": 200}
def _shutdown(self, data):

View file

@ -56,7 +56,7 @@ class Yuuki_Command:
GroupPrivilege = self.Yuuki.Admin + [self.Yuuki_StaticTools.sybGetGroupCreator(GroupInfo).mid] + \
self.Yuuki.data.getGroup(GroupInfo.id)["Ext_Admin"]
if ncMessage.message.from_ in GroupPrivilege:
for userId in self.Yuuki.Connect.helper_ids:
for userId in self.Yuuki.Connect.helper:
self.Yuuki_DynamicTools.sendUser(
self.Yuuki_StaticTools.sendToWho(ncMessage), userId)
@ -210,7 +210,9 @@ class Yuuki_Command:
for userId in self.Yuuki.data.getGroup(GroupInfo.id)["Ext_Admin"]:
if userId not in status_added:
status += "{}: {}\n".format(
self.Yuuki.get_text("Unknown"), userId)
self.Yuuki.get_text("Unknown"),
userId
)
self.Yuuki_DynamicTools.sendText(
self.Yuuki_StaticTools.sendToWho(ncMessage),
status + self.Yuuki.get_text("\nExtend Administrator(s)")
@ -281,7 +283,7 @@ class Yuuki_Command:
ncMessage), self.Yuuki.get_text("Bye Bye"))
self.Yuuki_DynamicTools.getClient(
self.Yuuki.MyMID).leaveGroup(self.Yuuki.Seq, GroupInfo.id)
for userId in self.Yuuki.Connect.helper_ids:
for userId in self.Yuuki.Connect.helper:
if userId in [member.mid for member in GroupInfo.members]:
self.Yuuki_DynamicTools.getClient(
userId).leaveGroup(self.Yuuki.Seq, GroupInfo.id)

View file

@ -58,7 +58,7 @@ class Yuuki_JoinGroup:
def _helper_check(self, ncMessage, GroupInvite, BlockedIgnore):
if ncMessage.param1 in self.Yuuki.data.getData(["Global", "GroupJoined"]) and not BlockedIgnore:
for userId in self.Yuuki.Connect.helper_ids:
for userId in self.Yuuki.Connect.helper:
if self.Yuuki_DynamicTools.checkInInvitationList(ncMessage, userId) or userId in GroupInvite:
self.Yuuki_DynamicTools.getClient(userId).acceptGroupInvitation(self.Yuuki.Seq, ncMessage.param1)
self.Yuuki_DynamicTools.getGroupTicket(ncMessage.param1, userId, True)

View file

@ -12,6 +12,14 @@ from yuuki_core.ttypes import OpType
from ..tools import Yuuki_StaticTools, Yuuki_DynamicTools
def security_access_checker(function):
def wrapper(*args):
if not args[2].get("Security_Access"):
return
return function(*args)
return wrapper
class Yuuki_Security:
def __init__(self, Yuuki):
"""
@ -26,9 +34,10 @@ class Yuuki_Security:
self.Yuuki_StaticTools = Yuuki_StaticTools()
self.Yuuki_DynamicTools = Yuuki_DynamicTools(self.Yuuki)
@security_access_checker
def _NOTIFIED_UPDATE_GROUP(self, GroupInfo, SecurityInfo, ncMessage):
if SecurityInfo["Another"] == '4':
if not GroupInfo.preventJoinByTicket and SecurityInfo["Action"] not in self.Yuuki.Connect.helper_ids:
if not GroupInfo.preventJoinByTicket and SecurityInfo["Action"] not in self.Yuuki.Connect.helper:
self.Yuuki.threadExec(
self.Yuuki_DynamicTools.changeGroupUrlStatus,
(GroupInfo, False)
@ -49,12 +58,13 @@ class Yuuki_Security:
ncMessage.type
))
@security_access_checker
def _NOTIFIED_INVITE_INTO_GROUP(self, GroupInfo, SecurityInfo, ncMessage):
Canceler = "None"
if "\x1e" in SecurityInfo["Another"]:
Canceler = self._NOTIFIED_INVITE_INTO_GROUP_list(GroupInfo, SecurityInfo, ncMessage, Canceler)
elif SecurityInfo["Another"] not in self.Yuuki.AllAccountIds + SecurityInfo["GroupPrivilege"]:
Canceler = self._NOTIFIED_INVITE_INTO_GROUP_single(GroupInfo, SecurityInfo, ncMessage, Canceler)
Canceler = self._NOTIFIED_INVITE_INTO_GROUP_single(GroupInfo, SecurityInfo, ncMessage)
if Canceler != "None":
self.Yuuki_DynamicTools.sendText(
SecurityInfo["GroupID"],
@ -89,7 +99,7 @@ class Yuuki_Security:
))
return Canceler
def _NOTIFIED_INVITE_INTO_GROUP_single(self, GroupInfo, SecurityInfo, ncMessage, Canceler):
def _NOTIFIED_INVITE_INTO_GROUP_single(self, GroupInfo, SecurityInfo, ncMessage):
if GroupInfo.invitee and SecurityInfo["Another"] in [user.mid for user in GroupInfo.invitee]:
Canceler = self.Yuuki_DynamicTools.modifyGroupMemberList(2, GroupInfo, SecurityInfo["Another"])
else:
@ -113,6 +123,7 @@ class Yuuki_Security:
))
return Canceler
@security_access_checker
def _NOTIFIED_ACCEPT_GROUP_INVITATION(self, GroupInfo, SecurityInfo, ncMessage):
for userId in self.Yuuki.data.getData(["BlackList"]):
if userId == SecurityInfo["Action"]:
@ -133,7 +144,7 @@ class Yuuki_Security:
))
def _NOTIFIED_KICKOUT_FROM_GROUP(self, GroupInfo, SecurityInfo, ncMessage):
if SecurityInfo["Action"] in self.Yuuki.Connect.helper_ids:
if SecurityInfo["Action"] in self.Yuuki.Connect.helper:
# Log
self.Yuuki.data.updateLog("KickEvent", (
self.Yuuki.data.getTime(),

View file

@ -116,17 +116,10 @@ class Yuuki_DynamicTools:
:param userId: string
:return: TalkServiceClient
"""
if self.Yuuki.Threading:
if userId == self.Yuuki.MyMID:
(client, _) = self.Yuuki.Connect.connect()
return client
else:
return self.Yuuki.Connect.helperThreadConnect(userId)
if userId == self.Yuuki.MyMID:
return self.Yuuki.client
else:
Accounts = [self.Yuuki.client] + self.Yuuki.Connect.helper
for count, AccountUserId in enumerate(self.Yuuki.AllAccountIds):
if AccountUserId == userId:
return Accounts[count]
return self.Yuuki.Connect.helper[userId]
def checkInInvitationList(self, ncMessage, userId=None):
"""

View file

@ -35,7 +35,7 @@ class Yuuki_WebAdminAPI:
def get_helpers(self, data):
if data:
pass
return self.Yuuki.Connect.helper_ids
return self.Yuuki.Connect.helper
def get_logs(self, data):
return self.Yuuki_DataHandle.get_logs(data)

View file

@ -50,16 +50,13 @@ class Yuuki:
origin_url = "https://github.com/star-inc/star_yuuki_bot.git"
if self.YuukiConfigs["version_check"]:
# noinspection PyBroadException
try:
git_remote = Repo('.').remote()
update_status = git_remote.fetch()[0]
if update_status.flags == 64:
git_result = "New version found."
elif update_status.flags == 4:
git_result = "This is the latest version."
except:
git_result = "Something was wrong."
git_remote = Repo('.').remote()
update_status = git_remote.fetch()[0]
if update_status.flags == 64:
git_result = "New version found."
elif update_status.flags == 4:
git_result = "This is the latest version."
origin_url = "\n".join(git_remote.urls)
return self._Announce_Dog(git_result, origin_url)
@ -68,8 +65,8 @@ class Yuuki:
"\n{} {}\n"
"\t===\n\n"
"<*> {}\n\n"
"More Information:\n"
"{}\n\n\t\t\t\t\t"
"Update Origin:\n"
"\t{}\n\n\t\t\t\t\t"
"{}\n\t{}\n".format(
self.YuukiConfigs["name"],
self.YuukiConfigs["version"],
@ -107,7 +104,10 @@ class Yuuki:
self.MyMID = self.profile.mid
self.revision = self.client.getLastOpRevision()
self.AllAccountIds = [self.MyMID] + self.Connect.helper_ids
self.AllAccountIds = [self.MyMID]
for userId in self.Connect.helper:
self.AllAccountIds.append(userId)
if len(self.data.getData(["LimitInfo"])) != 2:
self.data.updateData(["LimitInfo"], self.data.LimitType)
@ -144,20 +144,24 @@ class Yuuki:
time.sleep(1)
self.data.MdsThreadControl.stop("wa_listen")
if restart:
if platform.system() == "Windows":
with open("cache.bat", "w") as c:
c.write(sys.executable + " ./main.py")
os.system("cache.bat")
os.system("del cache.bat")
elif platform.system() == "Linux":
with open(".cache.sh", "w") as c:
c.write(sys.executable + " ./main.py")
os.system("sh .cache.sh")
os.system("rm .cache.sh")
else:
print("Star Yuuki BOT - Restart Error\n\nUnknown Platform")
self.__restart()
sys.exit(0)
@staticmethod
def __restart():
if platform.system() == "Windows":
with open("cache.bat", "w") as c:
c.write(sys.executable + " ./main.py")
os.system("cache.bat")
os.system("del cache.bat")
elif platform.system() == "Linux":
with open(".cache.sh", "w") as c:
c.write(sys.executable + " ./main.py")
os.system("sh .cache.sh")
os.system("rm .cache.sh")
else:
print("Star Yuuki BOT - Restart Error\n\nUnknown Platform")
def threadExec(self, function, args):
if self.Threading:
self.Thread_Control.add(function, args)