diff --git a/COPYRIGHT.md b/COPYING.md
similarity index 66%
rename from COPYRIGHT.md
rename to COPYING.md
index 1ffb207..4fdecb3 100644
--- a/COPYRIGHT.md
+++ b/COPYING.md
@@ -1,6 +1,6 @@
-# The software licensed under Mozilla Public LICENSE 2.0.
+# Star Yuuki BOT - Yuuki
-1)You can edit/copy these files, but you need to keep the original "[COPYRIGHT.md](COPYRIGHT.md)", "[LICENSE.md](LICENSE.md)" and in the program which you did it.
+1)You can edit/copy these files, but you need to keep the original "[COPYING.md](COPYING.md)", "[LICENSE.md](LICENSE.md)" and in the program which you did it.
2)The copyright of [Line Services](https://line.starinc.xyz/) contents belongs to [Star Inc.](https://starinc.xyz), we DO NOT assume any legal responsibility.
diff --git a/README.md b/README.md
index 37bb363..e079dc1 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
Star Yuuki(pYthon) BOT - Yuuki
==================
-![Version](https://img.shields.io/badge/v6.5.1-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)
+![Version](https://img.shields.io/badge/v6.5.2-OpenSource-FF0033.svg) ![Series](https://img.shields.io/badge/syb_Yuuki-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)
A Python BOT for LINE Group Protection with LINE Unofficial API.
![ICON](logo.png)
diff --git a/libs/data.py b/libs/data.py
index b07c93d..2f08c60 100644
--- a/libs/data.py
+++ b/libs/data.py
@@ -1,9 +1,16 @@
#!/usr/bin/python3
# coding=UTF-8
-import os, time, json
+import \
+ os, \
+ time,\
+ json, \
+ random,\
+ requests
from .core.ttypes import OpType
+from .data_mds import listen as msd_listen
+
from .thread_control import Yuuki_Thread
from .thread_control import Yuuki_Multiprocess
@@ -11,13 +18,10 @@ class Yuuki_Data:
def __init__(self, threading):
self.threading = threading
self.ThreadControl = Yuuki_Thread()
- self.MpDataControl = Yuuki_Multiprocess()
+ MdsThreadControl = Yuuki_Multiprocess()
# Data
- if self.threading:
- self.Data = self.MpDataControl.dataManager.dict()
- else:
- self.Data = {}
+ self.Data = {}
self.DataType = {
"Global":{
@@ -79,6 +83,25 @@ class Yuuki_Data:
self.Data[Type] = self.DataType[Type]
f.write(json.dumps(self.Data[Type]))
+ # Python MDS
+
+ if self.threading:
+ self.mdsHost = "http://localhost:2019/"
+ self.mdsCode = "{}.{}".format(random.random(), time.time())
+ MdsThreadControl.add(msd_listen, (self.mdsCode,))
+
+ # MDS Sync
+
+ time.sleep(1)
+ requests.post(
+ url=self.mdsHost,
+ json={
+ "code": self.mdsCode,
+ "do": "SYC",
+ "path": self.Data
+ }
+ )
+
# Log
self.LogType = {
@@ -111,6 +134,52 @@ class Yuuki_Data:
else:
Function(*args)
+ def _mdsShake(self, do, path, data=None):
+ if self.threading:
+ mds = requests.post(
+ url=self.mdsHost,
+ json={
+ "code": self.mdsCode,
+ "do": do,
+ "path": path,
+ "data": data
+ }
+ )
+ over = mds.json()
+ assert over["status"] == 200, "mds - ERROR\n{} on {}".format(do, path)
+ return over
+ else:
+ status = {"status" : 0}
+ return json.dumps(status)
+
+ def _local_query(self, query_data):
+ if type(query_data) is list:
+ result = self.Data.copy()
+ query_len = len(query_data)
+ source_data = self.Data
+ for count, key in enumerate(query_data):
+ if key in source_data:
+ if count < (query_len - 1):
+ if type(source_data.get(key)) is dict:
+ source_data = source_data.get(key)
+ else:
+ result = 1
+ break
+ else:
+ result = source_data.get(key)
+ else:
+ result = 2
+ break
+
+ return result
+ return 0
+
+ def _local_update(self, path, data):
+ over = self._local_query(path)
+ if not str(over).isnumeric():
+ over.update(data)
+ return False
+
def file(self, Type, Mode, Format):
if Format == "Data":
return open(self.DataPath + self.DataName.format(Type), Mode)
@@ -118,24 +187,36 @@ class Yuuki_Data:
return open(self.LogPath + self.LogName.format(Type), Mode)
def syncData(self):
+ if self.threading:
+ sync = self._mdsShake("GET", [])
+ self.Data = sync.get("data")
for Type in self.DataType:
with self.file(Type, "w", "Data") as f:
f.write(json.dumps(self.Data[Type]))
- def updateData(self, Object, Input, Data):
+ def updateData(self, path, data):
if self.threading:
- self.ThreadExec(self._updateData, (Object, Input, Data))
+ self.ThreadExec(self._updateData, (path, data))
else:
- self._updateData(Object, Input, Data)
+ self._updateData(path, data)
- def _updateData(self, Object, Input, Data):
- if type(Object) == list:
- if Input:
- Object.append(Data)
- else:
- Object.remove(Data)
- elif type(Object) == dict:
- Object[Input] = Data
+ def _updateData(self, path, data):
+ if not path:
+ assert "Empty path - updateData"
+ elif len(path) == 1:
+ origin = self.getData([]).copy()
+ origin[path] = data
+ data = origin
+ else:
+ origin = self.getData(path[:-1]).copy()
+ origin[path[-1]] = data
+ path = path[:-1]
+ data = origin
+ assert type(data) == dict, "Error data type - updateData"
+ if self.threading:
+ self._mdsShake("UPT", path, data)
+ else:
+ self._local_update(path, data)
def updateLog(self, Type, Data):
if self.threading:
@@ -147,40 +228,30 @@ class Yuuki_Data:
with self.file(Type, "a", "Log") as f:
f.write(self.LogType[Type] % Data)
- def getTime(self, format="%b %d %Y %H:%M:%S %Z"):
+ @staticmethod
+ def getTime(time_format="%b %d %Y %H:%M:%S %Z"):
Time = time.localtime(time.time())
- return time.strftime(format, Time)
+ return time.strftime(time_format, Time)
- def getData(self, Type):
- return self.Data[Type]
-
- def getLimit(self, Type):
- LimitInfo = self.getData("LimitInfo")
- if Type == "Kick":
- Limit = {}
- for Mode in LimitInfo["KickLimit"]:
- Limit[Mode] = int(LimitInfo["KickLimit"][Mode])
- elif Type == "Cancel":
- Limit = {}
- for Mode in LimitInfo["CancelLimit"]:
- Limit[Mode] = int(LimitInfo["CancelLimit"][Mode])
+ def getData(self, path):
+ if self.threading:
+ return self._mdsShake("GET", path).get("data")
else:
- Limit = None
- return Limit
+ return self._local_query(path)
def getGroup(self, GroupID):
- Groups = self.getData("Group")
+ Groups = self.getData(["Group"])
if len(Groups) > 0:
GroupIDs = [Group for Group in Groups]
if GroupID not in GroupIDs:
- Groups[GroupID] = self.GroupType
+ self.updateData(["Group", GroupID], self.GroupType)
else:
- Groups[GroupID] = self.GroupType
- return Groups[GroupID]
+ self.updateData(["Group", GroupID], self.GroupType)
+ return self.getData(["Group", GroupID])
def getSEGroup(self, GroupID):
SEMode = self.getGroup(GroupID).get("SEGroup")
- if SEMode == None:
+ if SEMode is None:
return None
SEMode_ = {}
for Mode in SEMode:
diff --git a/libs/data_mds.py b/libs/data_mds.py
new file mode 100644
index 0000000..2cf8e91
--- /dev/null
+++ b/libs/data_mds.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+ Star Inc. multiprocessing data switching
+ ===
+ To switch data in multiprocessing tasks.
+
+ LICENSE: MPL 2.0
+ (c)2019 Star Inc.
+"""
+
+# Initializing
+import json
+
+from tornado.httpserver import HTTPServer
+from tornado.ioloop import IOLoop
+from tornado.web import Application, RequestHandler
+
+switch_data = {}
+auth_code = 0
+
+# Functions
+def mds_exit(null=None, null_=None):
+ exit(0)
+
+def update(path, data):
+ global switch_data
+ try:
+ if type(path) is list:
+ over = query(path)
+ over.get("data").update(data)
+ return {"status" : 200}
+ return {"status" : 400}
+ except:
+ return {"status": 500}
+
+def delete(path, data):
+ global switch_data
+ try:
+ if type(path) is list:
+ over = query(path)
+ over.get("data").pop(data)
+ return {"status" : 200}
+ return {"status" : 400}
+ except:
+ return {"status": 500}
+
+def query(query_data, null=None):
+ global switch_data
+ try:
+ if type(switch_data) is dict and type(query_data) is list:
+ result = switch_data.copy()
+ query_len = len(query_data)
+ source_data = switch_data
+ for count, key in enumerate(query_data):
+ if key in source_data:
+ if count < (query_len - 1):
+ if type(source_data.get(key)) is dict:
+ source_data = source_data.get(key)
+ else:
+ result = 1 #"unknown_type" + type(source_data.get(key))
+ break
+ else:
+ result = source_data.get(key)
+ else:
+ result = 2 #"unknown_key"
+ break
+
+ return {"status" : 200, "data" : result}
+ return {"status" : 400}
+ except:
+ return {"status": 500}
+
+def sync(path, null=None):
+ global switch_data
+ try:
+ switch_data = path
+ return {"status" : 200}
+ except:
+ return {"status": 500}
+
+# Works
+_work = {
+ "EXT": mds_exit,
+ "UPT": update,
+ "DEL": delete,
+ "GET": query,
+ "SYC": sync
+}
+
+class IndexHandler(RequestHandler):
+ def get(self):
+ self.write('''
+ Python MDS Server
+ To switch data in multiprocessing tasks.
+ (c)2019 Star Inc.
+ ''')
+
+ def post(self):
+ global auth_code
+ req_body = self.request.body
+ req_str = req_body.decode('utf8')
+ req_res = json.loads(req_str)
+ if req_res.get("code") == auth_code:
+ result = _work[req_res.get("do")](req_res.get("path"), req_res.get("data"))
+ else:
+ result = {"status" : 401}
+ if not result:
+ result = {"status" : 500}
+ self.write(json.dumps(result))
+
+# Main
+def listen(code):
+ global auth_code
+ auth_code = code
+ app = Application([('/',IndexHandler)])
+ server = HTTPServer(app)
+ server.listen(2019)
+ IOLoop.current().start()
diff --git a/libs/thread_control.py b/libs/thread_control.py
index ce20338..ff8c7d4 100644
--- a/libs/thread_control.py
+++ b/libs/thread_control.py
@@ -17,9 +17,6 @@ class Yuuki_Thread:
print("{} add Threading\n".format(threading.current_thread()))
class Yuuki_Multiprocess:
- def __init__(self):
- self.dataManager = multiprocessing.Manager()
-
def add(self, Yuuki_Func, args=()):
added_multiprocess = multiprocessing.Process(name=Yuuki_Func.__name__, target=Yuuki_Func, args=args)
added_multiprocess.start()
diff --git a/libs/yuuki.py b/libs/yuuki.py
index 796b554..b989e86 100644
--- a/libs/yuuki.py
+++ b/libs/yuuki.py
@@ -7,6 +7,8 @@ import socket, \
random, requests, \
platform, traceback
+from git import Repo
+
from .core.TalkService import *
from .connection import Yuuki_Connect
@@ -19,7 +21,8 @@ class Yuuki_Settings:
config = {
"name": "Yuuki",
- "version": "v6.5.1_RC4",
+ "version": "v6.5.2",
+ "version_check": True,
"project_url": "https://tinyurl.com/syb-yuuki",
"man_page": "https://tinyurl.com/yuuki-manual",
"privacy_page": "OpenSource - Licensed under MPL 2.0",
@@ -38,11 +41,6 @@ class Yuuki_Settings:
class Yuuki:
def __init__(self, Yuuki_Settings, Yuuki_Connection, threading=False):
- # Enforce Disable Threading in v6.5.1_RC4
- threading = False
-
- global _, YuukiVariable
-
# Static Variable
self.YuukiConfigs = Yuuki_Settings.config
@@ -62,16 +60,39 @@ class Yuuki:
self.Connect = Yuuki_Connect(Yuuki_Connection)
- # Dynamic Variable
+ # Version Check
+ git_result = "Unknown"
+ origin_url = "https://github.com/star-inc/star_yuuki_bot.git"
- self.data = Yuuki_Data(self.Threading)
+ if self.YuukiConfigs["version_check"]:
+ try:
+ GitRemote = Repo('.').remote()
+ UpdateStatus = GitRemote.fetch()[0]
+ if UpdateStatus.flags == 64:
+ git_result = "New version found."
+ elif UpdateStatus.flags == 4:
+ git_result = "This is the latest version."
+ except:
+ git_result = "Something was wrong."
- if self.Threading:
- YuukiVariable = self.Thread_Control.dataManager.dict()
- else:
- YuukiVariable = {}
+ # Announce Dog
+ print(
+ "\n{} {}\n"
+ "\t===\n\n"
+ "<*> {}\n\n"
+ "More Information:\n"
+ "{}\n\n\t\t\t\t\t"
+ "{}\n\t{}\n" .format(
+ self.YuukiConfigs["name"],
+ self.YuukiConfigs["version"],
+ git_result,
+ origin_url,
+ self.YuukiConfigs["copyright"],
+ "\t==" * 5
+ )
+ )
- # Initialize
+ # LINE Login
(self.client, self.listen) = self.Connect.connect()
self.connectHeader = Yuuki_Connection.connectHeader
@@ -79,17 +100,25 @@ class Yuuki:
for access in self.YuukiConfigs["helper_LINE_ACCESS_KEYs"]:
self.Connect.helperConnect(access)
+ # Dynamic Variable
+
+ self.data = Yuuki_Data(self.Threading)
+
+ self.data.updateData(["Global","Power"], True)
+ self.data.updateData(["Global","GroupJoined"], self.client.getGroupIdsJoined())
+ self.data.updateData(["Global","SecurityService"], self.YuukiConfigs["SecurityService"])
+
+ # Initialize
+
self.MyMID = self.client.getProfile().mid
self.revision = self.client.getLastOpRevision()
self.AllAccountIds = [self.MyMID] + self.Connect.helper_ids
- if len(self.data.getData("LimitInfo")) != 2:
- self.data.updateData(self.data.Data, "LimitInfo", self.data.LimitType)
+ if len(self.data.getData(["LimitInfo"])) != 2:
+ self.data.updateData(["LimitInfo"], self.data.LimitType)
- YuukiVariable["Power"] = True
- YuukiVariable["GroupJoined"] = self.client.getGroupIdsJoined()
- YuukiVariable["SecurityService"] = self.YuukiConfigs["SecurityService"]
+ global _
_ = self.i18n._
@@ -110,7 +139,12 @@ class Yuuki:
def exit(self, restart=False):
print("System Exit")
- YuukiVariable["Power"] = False
+ self.data.updateData(["Global", "Power"], False)
+ if self.Threading:
+ try:
+ self.data._mdsShake("EXT", "")
+ except:
+ pass
if restart:
if platform.system() == "Windows":
with open("cache.bat", "w") as c:
@@ -180,7 +214,7 @@ class Yuuki:
if 3 in status:
group_status[OpType.NOTIFIED_KICKOUT_FROM_GROUP] = True
- self.data.updateData(self.data.getGroup(groupId), "SEGroup", group_status)
+ self.data.updateData(["Group", groupId, "SEGroup"], group_status)
@staticmethod
def errorReport():
@@ -224,22 +258,16 @@ class Yuuki:
if self.data.getGroup(GroupID)["GroupTicket"].get(userId) is not None:
GroupTicket = self.data.getGroup(GroupID)["GroupTicket"].get(userId)
else:
- self.data.updateData(self.data.getGroup(GroupID), "GroupTicket", self.data.GroupType["GroupTicket"])
+ assert "Error JSON data type - GroupTicket"
if GroupTicket == "" or renew:
GroupTicket = self.getClient(userId).reissueGroupTicket(GroupID)
- self.data.updateData(self.data.getGroup(GroupID)["GroupTicket"], userId, GroupTicket)
+ self.data.updateData(["Group", GroupID, "GroupTicket", userId], GroupTicket)
return GroupTicket
- def limitReset(self, reconnect=False):
+ def limitReset(self):
for userId in self.AllAccountIds:
- if reconnect:
- if userId not in self.data.getLimit("Kick"):
- self.data.updateData(self.data.getData("LimitInfo")["KickLimit"], userId, self.KickLimit)
- if userId not in self.data.getLimit("Cancel"):
- self.data.updateData(self.data.getData("LimitInfo")["CancelLimit"], userId, self.CancelLimit)
- else:
- self.data.updateData(self.data.getData("LimitInfo")["KickLimit"], userId, self.KickLimit)
- self.data.updateData(self.data.getData("LimitInfo")["CancelLimit"], userId, self.CancelLimit)
+ self.data.updateData(["LimitInfo", "KickLimit", userId], self.KickLimit)
+ self.data.updateData(["LimitInfo", "KickLimit", userId], self.CancelLimit)
@staticmethod
def dictShuffle(dict_object, requirement=None):
@@ -257,7 +285,7 @@ class Yuuki:
def cancelSomeone(self, groupInfo, userId, exceptUserId=None):
if len(self.Connect.helper) >= 1:
members = [member.mid for member in groupInfo.members if member.mid in self.AllAccountIds]
- accounts = self.dictShuffle(self.data.getLimit("Cancel"), members)
+ accounts = self.dictShuffle(self.data.getData(["LimitInfo", "CancelLimit"]), members)
if len(accounts) == 0:
return "None"
if exceptUserId:
@@ -268,10 +296,10 @@ class Yuuki:
return "None"
helper = self.MyMID
- Limit = self.data.getLimit("Cancel")[helper]
+ Limit = self.data.getData(["LimitInfo", "CancelLimit", helper])
if Limit > 0:
self.getClient(helper).cancelGroupInvitation(self.Seq, groupInfo.id, [userId])
- self.data.updateData(self.data.getData("LimitInfo")["CancelLimit"], helper, Limit - 1)
+ self.data.updateData(["LimitInfo", "CancelLimit", helper], Limit - 1)
else:
self.sendText(groupInfo.id, _("Cancel Limit."))
return helper
@@ -279,7 +307,7 @@ class Yuuki:
def kickSomeone(self, groupInfo, userId, exceptUserId=None):
if len(self.Connect.helper) >= 1:
members = [member.mid for member in groupInfo.members if member.mid in self.AllAccountIds]
- accounts = self.dictShuffle(self.data.getLimit("Kick"), members)
+ accounts = self.dictShuffle(self.data.getData(["LimitInfo", "KickLimit"]), members)
if len(accounts) == 0:
return "None"
if exceptUserId:
@@ -290,10 +318,10 @@ class Yuuki:
return "None"
helper = self.MyMID
- Limit = self.data.getLimit("Kick")[helper]
+ Limit = self.data.getData(["LimitInfo", "KickLimit", helper])
if Limit > 0:
self.getClient(helper).kickoutFromGroup(self.Seq, groupInfo.id, [userId])
- self.data.updateData(self.data.getData("LimitInfo")["KickLimit"], helper, Limit - 1)
+ self.data.updateData(["LimitInfo", "KickLimit", helper], Limit - 1)
else:
self.sendText(groupInfo.id, _("Kick Limit."))
return helper
@@ -384,7 +412,7 @@ class Yuuki:
NOTIFIED_INVITE_INTO_GROUP (13)
"""
GroupInvite = []
- BlockedIgnore = ncMessage.param2 in self.data.getData("BlackList")
+ BlockedIgnore = ncMessage.param2 in self.data.getData(["BlackList"])
if self.checkInInvitationList(ncMessage) and not BlockedIgnore:
GroupID = ncMessage.param1
Inviter = ncMessage.param2
@@ -396,7 +424,10 @@ class Yuuki:
GroupInvite = [Catched.mid for Catched in GroupInfo.invitee]
self.getClient(self.MyMID).acceptGroupInvitation(self.Seq, GroupID)
if len(GroupMember) >= self.YuukiConfigs["GroupMebers_Demand"]:
- YuukiVariable["GroupJoined"].append(GroupID)
+ GroupList = self.data.getData(["Global", "GroupJoined"])
+ NewGroupList = GroupList.copy()
+ NewGroupList.append(GroupID)
+ self.data.updateData(["Global", "GroupJoined"], NewGroupList)
self.sendText(GroupID, _("Helllo^^\nMy name is %s ><\nNice to meet you OwO") % self.YuukiConfigs["name"])
self.sendText(GroupID, _("Type:\n\t%s/Help\nto get more information\n\nMain Admin of the Group:\n%s") %
(self.YuukiConfigs["name"], self.sybGetGroupCreator(GroupInfo).displayName,))
@@ -409,7 +440,7 @@ class Yuuki:
self.getClient(self.MyMID).leaveGroup(self.Seq, GroupID)
# Log
self.data.updateLog("JoinGroup", (self.data.getTime(), GroupID, "Not Join", Inviter))
- if ncMessage.param1 in YuukiVariable["GroupJoined"] and not BlockedIgnore:
+ if ncMessage.param1 in self.data.getData(["Global", "GroupJoined"]) and not BlockedIgnore:
for userId in self.Connect.helper_ids:
if self.checkInInvitationList(ncMessage, userId) or userId in GroupInvite:
self.getClient(userId).acceptGroupInvitation(self.Seq, ncMessage.param1)
@@ -423,7 +454,7 @@ class Yuuki:
ToDo Type:
RECEIVE_MESSAGE (26)
"""
- BlockedIgnore = (ncMessage.message.to in self.data.getData("BlackList")) or (ncMessage.message.from_ in self.data.getData("BlackList"))
+ BlockedIgnore = (ncMessage.message.to in self.data.getData(["BlackList"])) or (ncMessage.message.from_ in self.data.getData(["BlackList"]))
if ('BOT_CHECK' in ncMessage.message.contentMetadata) or BlockedIgnore:
pass
elif ncMessage.message.toType == MIDType.ROOM:
@@ -462,18 +493,18 @@ class Yuuki:
if ncMessage.message.from_ in self.Admin:
if len(msgSep) == 2:
if msgSep[1].isdigit() and 1 >= int(msgSep[1]) >= 0:
- YuukiVariable["SecurityService"] = bool(msgSep[1])
+ self.data.updateData(["Global", "SecurityService"], bool(msgSep[1]))
self.sendText(self.sendToWho(ncMessage), _("Okay"))
else:
self.sendText(self.sendToWho(ncMessage), _("Enable(True): 1\nDisable(False): 0"))
else:
- self.sendText(self.sendToWho(ncMessage), str(bool(YuukiVariable["SecurityService"])))
+ self.sendText(self.sendToWho(ncMessage), str(bool(self.data.getData(["Global", "SecurityService"]))))
elif self.YuukiConfigs["name"] + '/Switch' == msgSep[0] and len(msgSep) != 1:
if ncMessage.message.toType == MIDType.GROUP:
GroupInfo = self.getClient(self.MyMID).getGroup(ncMessage.message.to)
GroupPrivilege = self.Admin + [self.sybGetGroupCreator(GroupInfo).mid] + self.data.getGroup(GroupInfo.id)["Ext_Admin"]
- if not YuukiVariable["SecurityService"]:
+ if not self.data.getData(["Global", "SecurityService"]):
self.sendText(self.sendToWho(ncMessage),
_("SecurityService of %s was disable") % (self.YuukiConfigs["name"],))
elif ncMessage.message.from_ in GroupPrivilege:
@@ -499,7 +530,7 @@ class Yuuki:
if ncMessage.message.toType == MIDType.GROUP:
GroupInfo = self.getClient(self.MyMID).getGroup(ncMessage.message.to)
GroupPrivilege = self.Admin + [self.sybGetGroupCreator(GroupInfo).mid] + self.data.getGroup(GroupInfo.id)["Ext_Admin"]
- if not YuukiVariable["SecurityService"]:
+ if not self.data.getData(["Global", "SecurityService"]):
self.sendText(self.sendToWho(ncMessage), _("SecurityService of %s was disable") % (self.YuukiConfigs["name"],))
elif ncMessage.message.from_ in GroupPrivilege:
self.configSecurityStatus(ncMessage.message.to, [])
@@ -515,8 +546,11 @@ class Yuuki:
if msgSep[2] in [Member.mid for Member in GroupInfo.members]:
if msgSep[2] in self.data.getGroup(GroupInfo.id)["Ext_Admin"]:
self.sendText(self.sendToWho(ncMessage), _("Added"))
- elif msgSep[2] not in self.data.getData("BlackList"):
- self.data.updateData(self.data.getGroup(GroupInfo.id)["Ext_Admin"], True, msgSep[2])
+ elif msgSep[2] not in self.data.getData(["BlackList"]):
+ origin = self.data.getData(["Group", GroupInfo.id,"Ext_Admin"])
+ ext_admin_list = origin.copy()
+ ext_admin_list.append(msgSep[2])
+ self.data.updateData(["Group", GroupInfo.id,"Ext_Admin"], ext_admin_list)
self.sendText(self.sendToWho(ncMessage), _("Okay"))
else:
self.sendText(self.sendToWho(ncMessage), _("The User(s) was in our blacklist database."))
@@ -524,7 +558,10 @@ class Yuuki:
self.sendText(self.sendToWho(ncMessage), _("Wrong UserID or the guy is not in Group"))
elif msgSep[1] == "delete":
if msgSep[2] in self.data.getGroup(GroupInfo.id)["Ext_Admin"]:
- self.data.updateData(self.data.getGroup(GroupInfo.id)["Ext_Admin"], False, msgSep[2])
+ origin = self.data.getData(["Group", GroupInfo.id,"Ext_Admin"])
+ ext_admin_list = origin.copy()
+ ext_admin_list.remove(msgSep[2])
+ self.data.updateData(["Group", GroupInfo.id,"Ext_Admin"], ext_admin_list)
self.sendText(self.sendToWho(ncMessage), _("Okay"))
else:
self.sendText(self.sendToWho(ncMessage), _("Not Found"))
@@ -547,7 +584,7 @@ class Yuuki:
if ncMessage.message.toType == MIDType.GROUP:
GroupInfo = self.getClient(self.MyMID).getGroup(ncMessage.message.to)
group_status = self.data.getSEGroup(ncMessage.message.to)
- if not YuukiVariable["SecurityService"]:
+ if not self.data.getData(["Global", "SecurityService"]):
status = _("SecurityService of %s was disable") % (
self.YuukiConfigs["name"],
)
@@ -593,7 +630,10 @@ class Yuuki:
for userId in self.Connect.helper_ids:
if userId in [member.mid for member in GroupInfo.members]:
self.getClient(userId).leaveGroup(self.Seq, GroupInfo.id)
- YuukiVariable["GroupJoined"].remove(GroupInfo.id)
+ GroupList = self.data.getData(["Global", "GroupJoined"])
+ NewGroupList = GroupList.copy()
+ NewGroupList.remove(GroupInfo.id)
+ self.data.updateData(["Global", "GroupJoined"], NewGroupList)
elif self.YuukiConfigs["name"] + '/Exit' == ncMessage.message.text:
if ncMessage.message.from_ in self.Admin:
@@ -610,7 +650,7 @@ class Yuuki:
contactInfo = self.getContact(Catched)
if not contactInfo:
msg = _("Not Found")
- elif contactInfo.mid in self.data.getData("BlackList"):
+ elif contactInfo.mid in self.data.getData(["BlackList"]):
msg = "{}\n{}".format(_("The User(s) was in our blacklist database."), contactInfo.mid)
else:
msg = _("Name:%s\nPicture URL:%s/%s\nStatusMessage:\n%s\nLINE System UserID:%s") % \
@@ -641,11 +681,11 @@ class Yuuki:
return
if SEGroup is None:
- Security_Access = YuukiVariable["SecurityService"]
+ Security_Access = self.data.getData(["Global", "SecurityService"])
elif SEGroup[ncMessage.type]:
Security_Access = SEGroup[ncMessage.type]
- if YuukiVariable["SecurityService"]:
+ if self.data.getData(["Global", "SecurityService"]):
if ncMessage.type == OpType.NOTIFIED_UPDATE_GROUP and Security_Access:
if Another == '4':
if not GroupInfo.preventJoinByTicket and Action not in self.Connect.helper_ids:
@@ -679,7 +719,7 @@ class Yuuki:
if Canceler != "None":
self.sendText(GroupID, _("Do not invite anyone...thanks"))
elif ncMessage.type == OpType.NOTIFIED_ACCEPT_GROUP_INVITATION and Security_Access:
- for userId in self.data.getData("BlackList"):
+ for userId in self.data.getData(["BlackList"]):
if userId == Action:
self.Thread_Exec(self.sendText, (GroupID, _("You are our blacklist. Bye~")))
Kicker = self.kickSomeone(GroupInfo, Action)
@@ -715,11 +755,17 @@ class Yuuki:
self.sendText(Root, "Star Yuuki BOT - SecurityService Failure\n\n%s\n%s\n%s\n\n%s" %
(err1, err2, err3, ErrorInfo))
if Another == self.MyMID:
- YuukiVariable["GroupJoined"].remove(GroupID)
+ GroupList = self.data.getData(["Global", "GroupJoined"])
+ NewGroupList = GroupList.copy()
+ NewGroupList.remove(GroupID)
+ self.data.updateData(["Global", "GroupJoined"], NewGroupList)
# Log
self.data.updateLog("KickEvent", (self.data.getTime(), GroupInfo.name, GroupID, Kicker, Action, Another, ncMessage.type*10+3))
- if Action not in self.data.getData("BlackList"):
- self.data.updateData(self.data.getData("BlackList"), True, Action)
+ BlackList = self.data.getData(["BlackList"])
+ if Action not in BlackList:
+ NewBlackList = BlackList.copy()
+ NewBlackList.append(Action)
+ self.data.updateData(["BlackList"], NewBlackList)
# Log
self.data.updateLog("BlackList", (self.data.getTime(), Action, GroupID))
self.Thread_Exec(self.sendText, (Action, _("You had been blocked by our database.")))
@@ -741,17 +787,17 @@ class Yuuki:
cacheOperations = []
ncMessage = Operation()
- if "LastResetLimitTime" not in self.data.getData("Global"):
- self.data.getData("Global")["LastResetLimitTime"] = None
+ if "LastResetLimitTime" not in self.data.getData(["Global"]):
+ self.data.updateData(["Global", "LastResetLimitTime"], None)
- if time.localtime().tm_hour == self.data.getData("Global")["LastResetLimitTime"]:
- self.limitReset(True)
+ if time.localtime().tm_hour == self.data.getData(["Global", "LastResetLimitTime"]):
+ self.limitReset()
- while YuukiVariable["Power"]:
+ while self.data.getData(["Global","Power"]):
try:
- if time.localtime().tm_hour != self.data.getData("Global")["LastResetLimitTime"]:
+ if time.localtime().tm_hour != self.data.getData(["Global", "LastResetLimitTime"]):
self.limitReset()
- self.data.updateData(self.data.getData("Global"), "LastResetLimitTime", time.localtime().tm_hour)
+ self.data.updateData(["Global", "LastResetLimitTime"], time.localtime().tm_hour)
if NoWork >= NoWorkLimit:
NoWork = 0
diff --git a/requirements.txt b/requirements.txt
index 378594b..ff98953 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,11 @@
-certifi==2019.6.16
+certifi==2019.9.11
chardet==3.0.4
+gitdb2==2.0.6
+GitPython==3.0.3
idna==2.8
requests==2.22.0
six==1.12.0
+smmap2==2.0.5
thrift==0.11.0
-urllib3==1.25.3
+tornado==6.0.3
+urllib3==1.25.6