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