#!/usr/bin/python3 # coding=UTF-8 import socket, \ os, time, \ json, ntpath, \ random, requests, \ platform, traceback from .core.TalkService import * from .connection import Yuuki_Connect from .data import Yuuki_Data from .i18n import Yuuki_LangSetting from .thread_control import Yuuki_Multiprocess class Yuuki_Settings: """ Yuuki Custom Settings """ config = { "name": "Yuuki", "version": "v6.5.1_RC4", "project_url": "https://tinyurl.com/syb-yuuki", "man_page": "https://tinyurl.com/yuuki-manual", "privacy_page": "OpenSource - Licensed under MPL 2.0", "copyright": "(c)2019 Star Inc.", "Seq": 0, "Admin": [], "SecurityService": False, "Hour_KickLimit": 10, "Hour_CancelLimit": 10, "Default_Language": "en", "GroupMebers_Demand": 100, "helper_LINE_ACCESS_KEYs": [] } 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 self.Threading = threading self.Thread_Control = Yuuki_Multiprocess() self.Seq = self.YuukiConfigs["Seq"] self.Admin = self.YuukiConfigs["Admin"] self.KickLimit = self.YuukiConfigs["Hour_KickLimit"] self.CancelLimit = self.YuukiConfigs["Hour_CancelLimit"] self.i18n = Yuuki_LangSetting(self.YuukiConfigs["Default_Language"]) self.LINE_Media_server = "https://obs.line-apps.com" self.Connect = Yuuki_Connect(Yuuki_Connection) # Dynamic Variable self.data = Yuuki_Data(self.Threading) if self.Threading: YuukiVariable = self.Thread_Control.dataManager.dict() else: YuukiVariable = {} # Initialize (self.client, self.listen) = self.Connect.connect() self.connectHeader = Yuuki_Connection.connectHeader for access in self.YuukiConfigs["helper_LINE_ACCESS_KEYs"]: self.Connect.helperConnect(access) 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) YuukiVariable["Power"] = True YuukiVariable["GroupJoined"] = self.client.getGroupIdsJoined() YuukiVariable["SecurityService"] = self.YuukiConfigs["SecurityService"] _ = self.i18n._ # Basic Func def getClient(self, userId): if self.Threading: if userId == self.MyMID: (client, _) = self.Connect.connect() return client else: return self.Connect.helperThreadConnect(userId) else: Accounts = [self.client] + self.Connect.helper for count, AccountUserId in enumerate(self.AllAccountIds): if AccountUserId == userId: return Accounts[count] def exit(self, restart=False): print("System Exit") YuukiVariable["Power"] = False 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") sys.exit(0) @staticmethod def sybGetGroupCreator(group): if group.creator is None: contact = group.members[0] else: contact = group.creator return contact @staticmethod def readCommandLine(msgs): replymsg = "" for msg in msgs: replymsg = replymsg + " " + msg return replymsg def checkInInvitationList(self, ncMessage, userId=None): if userId is None: userId = self.MyMID if ncMessage.param3 == userId: inList = True elif "\x1e" in ncMessage.param3: if userId in ncMessage.param3.split("\x1e"): inList = True else: inList = False else: inList = False return inList def changeGroupUrlStatus(self, group, status, userId=None): result = Group() for key in group.__dict__: if key != "members" or key != "invitee": result.__dict__[key] = group.__dict__[key] if status: result.preventJoinByTicket = False else: result.preventJoinByTicket = True if userId is not None: self.getClient(userId).updateGroup(self.Seq, result) else: self.getClient(self.MyMID).updateGroup(self.Seq, result) def configSecurityStatus(self, groupId, status): group_status = self.data.SEGrouptype if 0 in status: group_status[OpType.NOTIFIED_UPDATE_GROUP] = True if 1 in status: group_status[OpType.NOTIFIED_INVITE_INTO_GROUP] = True if 2 in status: group_status[OpType.NOTIFIED_ACCEPT_GROUP_INVITATION] = True if 3 in status: group_status[OpType.NOTIFIED_KICKOUT_FROM_GROUP] = True self.data.updateData(self.data.getGroup(groupId), "SEGroup", group_status) @staticmethod def errorReport(): err1, err2, err3 = sys.exc_info() traceback.print_tb(err3) tb_info = traceback.extract_tb(err3) filename, line, func, text = tb_info[-1] ErrorInfo = "occurred in\n{}\n\non line {}\nin statement {}".format(filename, line, text) return err1, err2, err3, ErrorInfo def cleanMyGroupInvitations(self): for client in [self.getClient(self.MyMID)] + self.Connect.helper: for cleanInvitations in client.getGroupIdsInvited(): client.acceptGroupInvitation(self.Seq, cleanInvitations) client.leaveGroup(self.Seq, cleanInvitations) def getContact(self, userId): if len(userId) == len(self.MyMID) and userId[0] == "u": try: contactInfo = self.getClient(self.MyMID).getContact(userId) except: contactInfo = False else: contactInfo = False return contactInfo @staticmethod def securityForWhere(ncMessage): if ncMessage.type == OpType.NOTIFIED_UPDATE_GROUP: return ncMessage.param1, ncMessage.param2, ncMessage.param3 elif ncMessage.type == OpType.NOTIFIED_INVITE_INTO_GROUP: return ncMessage.param1, ncMessage.param2, ncMessage.param3 elif ncMessage.type == OpType.NOTIFIED_ACCEPT_GROUP_INVITATION: return ncMessage.param1, ncMessage.param2, ncMessage.param3 elif ncMessage.type == OpType.NOTIFIED_KICKOUT_FROM_GROUP: return ncMessage.param1, ncMessage.param2, ncMessage.param3 def getGroupTicket(self, GroupID, userId, renew=False): GroupTicket = "" if "GroupTicket" in self.data.getGroup(GroupID): 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"]) if GroupTicket == "" or renew: GroupTicket = self.getClient(userId).reissueGroupTicket(GroupID) self.data.updateData(self.data.getGroup(GroupID)["GroupTicket"], userId, GroupTicket) return GroupTicket def limitReset(self, reconnect=False): 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) @staticmethod def dictShuffle(dict_object, requirement=None): dict_key = [key for key in dict_object] random.shuffle(dict_key) result = {} for key in dict_key: if requirement is None: result[key] = dict_object[key] else: if key in requirement: result[key] = dict_object[key] return result 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) if len(accounts) == 0: return "None" if exceptUserId: accounts[exceptUserId] = -1 helper = max(accounts, key=accounts.get) else: if exceptUserId == self.MyMID: return "None" helper = self.MyMID Limit = self.data.getLimit("Cancel")[helper] if Limit > 0: self.getClient(helper).cancelGroupInvitation(self.Seq, groupInfo.id, [userId]) self.data.updateData(self.data.getData("LimitInfo")["CancelLimit"], helper, Limit - 1) else: self.sendText(groupInfo.id, _("Cancel Limit.")) return helper 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) if len(accounts) == 0: return "None" if exceptUserId: accounts[exceptUserId] = -1 helper = max(accounts, key=accounts.get) else: if exceptUserId == self.MyMID: return "None" helper = self.MyMID Limit = self.data.getLimit("Kick")[helper] if Limit > 0: self.getClient(helper).kickoutFromGroup(self.Seq, groupInfo.id, [userId]) self.data.updateData(self.data.getData("LimitInfo")["KickLimit"], helper, Limit - 1) else: self.sendText(groupInfo.id, _("Kick Limit.")) return helper @staticmethod def sendToWho(ncMessage): if ncMessage.message.toType == MIDType.USER: return ncMessage.message.from_ elif ncMessage.message.toType == MIDType.ROOM: return ncMessage.message.to elif ncMessage.message.toType == MIDType.GROUP: return ncMessage.message.to def sendText(self, toid, msg): message = Message(to=toid, text=msg) self.getClient(self.MyMID).sendMessage(self.Seq, message) def sendUser(self, toid, userId): message = Message( contentType=ContentType.CONTACT, text='', contentMetadata={ 'mid': userId, 'displayName': 'LINE User', }, to=toid ) self.getClient(self.MyMID).sendMessage(self.Seq, message) def sendMedia(self, send_to, send_type, path): if os.path.exists(path): file_name = ntpath.basename(path) file_size = len(open(path, 'rb').read()) message = Message(to=send_to, text=None) message.contentType = send_type message.contentPreview = None message.contentMetadata = { 'FILE_NAME': str(file_name), 'FILE_SIZE': str(file_size), } if send_type == ContentType.FILE: media_name = file_name else: media_name = 'media' message_id = self.getClient(self.MyMID).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[send_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.sendText(send_to, "Error!") def Thread_Exec(self, Function, args): if self.Threading: self.Thread_Control.add(Function, args) else: Function(*args) # Task def taskDemux(self, catchedNews): for ncMessage in catchedNews: if ncMessage.type == OpType.NOTIFIED_INVITE_INTO_GROUP: self.Thread_Exec(self.JoinGroup, (ncMessage,)) elif ncMessage.type == OpType.NOTIFIED_KICKOUT_FROM_GROUP: self.Thread_Exec(self.Security, (ncMessage,)) elif ncMessage.type == OpType.NOTIFIED_ACCEPT_GROUP_INVITATION: self.Thread_Exec(self.Security, (ncMessage,)) elif ncMessage.type == OpType.NOTIFIED_UPDATE_GROUP: self.Thread_Exec(self.Security, (ncMessage,)) elif ncMessage.type == OpType.RECEIVE_MESSAGE: self.Thread_Exec(self.Commands, (ncMessage,)) def JoinGroup(self, ncMessage): """ ToDo Type: NOTIFIED_INVITE_INTO_GROUP (13) """ GroupInvite = [] BlockedIgnore = ncMessage.param2 in self.data.getData("BlackList") if self.checkInInvitationList(ncMessage) and not BlockedIgnore: GroupID = ncMessage.param1 Inviter = ncMessage.param2 GroupInfo = self.getClient(self.MyMID).getGroup(GroupID) if GroupInfo.members: GroupMember = [Catched.mid for Catched in GroupInfo.members] GroupInfo.invitee = [] if GroupInfo.invitee: 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) 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,)) self.getGroupTicket(GroupID, self.MyMID, True) # Log self.data.updateLog("JoinGroup", (self.data.getTime(), GroupInfo.name, GroupID, Inviter)) else: self.sendText(GroupID, _("Sorry...\nThe number of members is not satisfied (%s needed)") % (self.YuukiConfigs["GroupMebers_Demand"],)) 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: for userId in self.Connect.helper_ids: if self.checkInInvitationList(ncMessage, userId) or userId in GroupInvite: self.getClient(userId).acceptGroupInvitation(self.Seq, ncMessage.param1) self.getGroupTicket(ncMessage.param1, userId, True) # Log self.data.updateLog("JoinGroup", (self.data.getTime(), ncMessage.param1, userId, ncMessage.param2)) self.Security(ncMessage) def Commands(self, ncMessage): """ ToDo Type: RECEIVE_MESSAGE (26) """ 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: self.getClient(self.MyMID).leaveRoom(self.Seq, ncMessage.message.to) elif ncMessage.message.contentType == ContentType.NONE: msgSep = ncMessage.message.text.split(" ") if self.YuukiConfigs["name"] + '/Help' == ncMessage.message.text: self.sendText(self.sendToWho(ncMessage), _("%s\n\t%s\n\nCommands Info:\n%s\n\nPrivacy:\n%s\n\nMore Information:\n%s\n\n%s") % (self.YuukiConfigs["name"], self.YuukiConfigs["version"], self.YuukiConfigs["man_page"], self.YuukiConfigs["privacy_page"], self.YuukiConfigs["project_url"], self.YuukiConfigs["copyright"])) elif self.YuukiConfigs["name"] + '/Version' == ncMessage.message.text: self.sendText(self.sendToWho(ncMessage), self.YuukiConfigs["version"]) elif self.YuukiConfigs["name"] + '/UserID' == ncMessage.message.text: self.sendText(self.sendToWho(ncMessage), _("LINE System UserID:\n") + ncMessage.message.from_) elif self.YuukiConfigs["name"] + '/GetAllHelper' == ncMessage.message.text: 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 ncMessage.message.from_ in GroupPrivilege: for userId in self.Connect.helper_ids: self.sendUser(self.sendToWho(ncMessage), userId) elif self.YuukiConfigs["name"] + '/Speed' == ncMessage.message.text: Time1 = time.time() self.sendText(self.sendToWho(ncMessage), _("Testing...")) Time2 = time.time() self.sendText(self.sendToWho(ncMessage), _("Speed:\n %s com/s") % (Time2 - Time1,)) elif self.YuukiConfigs["name"] + '/SecurityMode' == msgSep[0]: 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.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"]))) 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"]: self.sendText(self.sendToWho(ncMessage), _("SecurityService of %s was disable") % (self.YuukiConfigs["name"],)) elif ncMessage.message.from_ in GroupPrivilege: status = [] unknown_msg = [] unknown_msgtext = "" for count, code in enumerate(msgSep): if code.isdigit() and 3 >= int(code) >= 0: status.append(int(code)) elif count != 0: unknown_msg.append(code.strip()) self.configSecurityStatus(ncMessage.message.to, status) if unknown_msg: unknown_msgtext = ", ".join(unknown_msg) if status: self.sendText(self.sendToWho(ncMessage), _("Okay")) else: self.sendText(self.sendToWho(ncMessage), _("Not Found")) if unknown_msgtext != "": self.sendText(self.sendToWho(ncMessage), _("Notice: Unknown command line argument(s)") + "\n({})".format(unknown_msgtext)) elif self.YuukiConfigs["name"] + '/DisableAll' == ncMessage.message.text: 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"]: self.sendText(self.sendToWho(ncMessage), _("SecurityService of %s was disable") % (self.YuukiConfigs["name"],)) elif ncMessage.message.from_ in GroupPrivilege: self.configSecurityStatus(ncMessage.message.to, []) self.sendText(self.sendToWho(ncMessage), _("Okay")) elif self.YuukiConfigs["name"] + '/ExtAdmin' == msgSep[0]: if ncMessage.message.toType == MIDType.GROUP: GroupInfo = self.getClient(self.MyMID).getGroup(ncMessage.message.to) GroupPrivilege = self.Admin + [self.sybGetGroupCreator(GroupInfo).mid] if len(msgSep) == 3: if ncMessage.message.from_ in GroupPrivilege: if msgSep[1] == "add": 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]) self.sendText(self.sendToWho(ncMessage), _("Okay")) else: self.sendText(self.sendToWho(ncMessage), _("The User(s) was in our blacklist database.")) else: 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]) self.sendText(self.sendToWho(ncMessage), _("Okay")) else: self.sendText(self.sendToWho(ncMessage), _("Not Found")) else: if self.data.getGroup(GroupInfo.id)["Ext_Admin"]: status = "" status_added = [] for member in GroupInfo.members: if member.mid in self.data.getGroup(GroupInfo.id)["Ext_Admin"]: status += "{}\n".format(member.displayName) status_added.append(member.mid) for userId in self.data.getGroup(GroupInfo.id)["Ext_Admin"]: if userId not in status_added: status += "{}: {}\n".format(_("Unknown"), userId) self.sendText(self.sendToWho(ncMessage), status + _("\nExtend Administrator(s)")) else: self.sendText(self.sendToWho(ncMessage), _("Not Found")) elif self.YuukiConfigs["name"] + '/Status' == ncMessage.message.text: 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"]: status = _("SecurityService of %s was disable") % ( self.YuukiConfigs["name"], ) elif group_status is None: status = _("Default without Initialize\nMain Admin of the Group:\n%s") % ( self.sybGetGroupCreator(GroupInfo).displayName, ) else: status = _("SecurityService is Listening on\n\nURL:%s\nInvite:%s\nJoin:%s\nMembers:%s\n\nMain Admin of the Group:\n%s") % ( group_status[OpType.NOTIFIED_UPDATE_GROUP], group_status[OpType.NOTIFIED_INVITE_INTO_GROUP], group_status[OpType.NOTIFIED_ACCEPT_GROUP_INVITATION], group_status[OpType.NOTIFIED_KICKOUT_FROM_GROUP], self.sybGetGroupCreator(GroupInfo).displayName, ) self.sendText(self.sendToWho(ncMessage), status) elif self.YuukiConfigs["name"] + '/GroupBackup' == ncMessage.message.text: 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 ncMessage.message.from_ in GroupPrivilege: GroupMembers = [User.mid for User in GroupInfo.members] GroupInvites = None if GroupInfo.invitee: GroupInvites = [User.mid for User in GroupInfo.invitee] LayoutInfo = { "OriginID": GroupInfo.id, "Members": GroupMembers, "Invites": GroupInvites } self.sendText(ncMessage.message.from_, GroupInfo.name) self.sendText(ncMessage.message.from_, json.dumps(LayoutInfo)) self.sendText(ncMessage.message.to, _("Okay")) elif self.YuukiConfigs["name"] + '/Quit' == ncMessage.message.text: if ncMessage.message.toType == MIDType.GROUP: GroupInfo = self.getClient(self.MyMID).getGroup(ncMessage.message.to) GroupPrivilege = self.Admin + [self.sybGetGroupCreator(GroupInfo).mid] if ncMessage.message.from_ in GroupPrivilege: self.sendText(self.sendToWho(ncMessage), _("Bye Bye")) self.getClient(self.MyMID).leaveGroup(self.Seq, GroupInfo.id) 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) elif self.YuukiConfigs["name"] + '/Exit' == ncMessage.message.text: if ncMessage.message.from_ in self.Admin: self.sendText(self.sendToWho(ncMessage), _("Exit.")) self.exit() elif self.YuukiConfigs["name"] + '/Com' == msgSep[0] and len(msgSep) != 1: if ncMessage.message.from_ in self.Admin: ComMsg = self.readCommandLine(msgSep[1:len(msgSep)]) self.sendText(self.sendToWho(ncMessage), str(eval(ComMsg))) elif ncMessage.message.contentType == ContentType.CONTACT: Catched = ncMessage.message.contentMetadata["mid"] contactInfo = self.getContact(Catched) if not contactInfo: msg = _("Not Found") 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") % \ (contactInfo.displayName, self.LINE_Media_server, contactInfo.pictureStatus, contactInfo.statusMessage, contactInfo.mid) self.sendText(self.sendToWho(ncMessage), msg) def Security(self, ncMessage): """ ToDo Type: NOTIFIED_UPDATE_GROUP (11) NOTIFIED_INVITE_INTO_GROUP (13) NOTIFIED_ACCEPT_GROUP_INVITATION (17) NOTIFIED_KICKOUT_FROM_GROUP (19) """ Security_Access = False (GroupID, Action, Another) = self.securityForWhere(ncMessage) SEGroup = self.data.getSEGroup(GroupID) GroupInfo = self.getClient(self.MyMID).getGroup(GroupID) GroupPrivilege = self.Admin + [self.sybGetGroupCreator(GroupInfo).mid] + self.data.getGroup(GroupInfo.id)["Ext_Admin"] if Action in GroupPrivilege or Another in GroupPrivilege: if ncMessage.type != OpType.NOTIFIED_KICKOUT_FROM_GROUP: return elif Action in GroupPrivilege: return if SEGroup is None: Security_Access = YuukiVariable["SecurityService"] elif SEGroup[ncMessage.type]: Security_Access = SEGroup[ncMessage.type] if YuukiVariable["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: self.Thread_Exec(self.changeGroupUrlStatus, (GroupInfo, False)) self.Thread_Exec(self.sendText, (GroupID, _("DO NOT ENABLE THE GROUP URL STATUS, see you..."))) Kicker = self.kickSomeone(GroupInfo, Action) # Log self.data.updateLog("KickEvent", (self.data.getTime(), GroupInfo.name, GroupID, Kicker, Action, Another, ncMessage.type)) elif ncMessage.type == OpType.NOTIFIED_INVITE_INTO_GROUP and Security_Access: Canceler = "None" if "\x1e" in Another: for userId in Another.split("\x1e"): if userId not in self.AllAccountIds + GroupPrivilege: if GroupInfo.invitee and userId in [user.mid for user in GroupInfo.invitee]: Canceler = self.cancelSomeone(GroupInfo, userId) else: Canceler = self.kickSomeone(GroupInfo, userId) # Log self.data.updateLog("KickEvent", (self.data.getTime(), GroupInfo.name, GroupID, Canceler, Action, userId, ncMessage.type*10)) # Log self.data.updateLog("CancelEvent", (self.data.getTime(), GroupInfo.name, GroupID, Canceler, Action, Another.replace("\x1e", ","))) elif Another not in self.AllAccountIds + GroupPrivilege: if GroupInfo.invitee and Another in [user.mid for user in GroupInfo.invitee]: Canceler = self.cancelSomeone(GroupInfo, Another) else: Canceler = self.kickSomeone(GroupInfo, Another) # Log self.data.updateLog("KickEvent", (self.data.getTime(), GroupInfo.name, GroupID, Canceler, Action, Another, ncMessage.type*10)) # Log self.data.updateLog("CancelEvent", (self.data.getTime(), GroupInfo.name, GroupID, Canceler, Action, Another)) 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"): if userId == Action: self.Thread_Exec(self.sendText, (GroupID, _("You are our blacklist. Bye~"))) Kicker = self.kickSomeone(GroupInfo, Action) # Log self.data.updateLog("KickEvent", (self.data.getTime(), GroupInfo.name, GroupID, Kicker, Kicker, Action, ncMessage.type)) elif ncMessage.type == OpType.NOTIFIED_KICKOUT_FROM_GROUP: if Action in self.Connect.helper_ids: # Log self.data.updateLog("KickEvent", (self.data.getTime(), GroupInfo.name, GroupID, Action, Action, Another, ncMessage.type*10+1)) elif Another in self.AllAccountIds: Kicker = "None" try: Kicker = self.kickSomeone(GroupInfo, Action, Another) # Log self.data.updateLog("KickEvent", (self.data.getTime(), GroupInfo.name, GroupID, Kicker, Action, Another, ncMessage.type*10+2)) assert Kicker != "None", "No Helper Found" if GroupInfo.preventJoinByTicket: self.Thread_Exec(self.changeGroupUrlStatus, (GroupInfo, True, Kicker)) GroupTicket = self.getGroupTicket(GroupID, Kicker) try: self.getClient(Another).acceptGroupInvitationByTicket(self.Seq, GroupID, GroupTicket) except: if GroupInfo.preventJoinByTicket: self.changeGroupUrlStatus(GroupInfo, True, Kicker) GroupTicket = self.getGroupTicket(GroupID, Kicker, True) self.getClient(Another).acceptGroupInvitationByTicket(self.Seq, GroupID, GroupTicket) if GroupInfo.preventJoinByTicket: self.Thread_Exec(self.changeGroupUrlStatus, (GroupInfo, False, Another)) self.getGroupTicket(GroupID, Another, True) except: (err1, err2, err3, ErrorInfo) = self.errorReport() for Root in self.Admin: 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) # 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) # Log self.data.updateLog("BlackList", (self.data.getTime(), Action, GroupID)) self.Thread_Exec(self.sendText, (Action, _("You had been blocked by our database."))) elif Security_Access: self.Thread_Exec(self.sendText, (GroupID, _("DO NOT KICK, thank you ^^"))) Kicker = self.kickSomeone(GroupInfo, Action) # Log self.data.updateLog("KickEvent", (self.data.getTime(), GroupInfo.name, GroupID, Kicker, Action, Another, ncMessage.type)) self.Thread_Exec(self.sendText, (GroupID, _("The one who was been kicked:"))) self.Thread_Exec(self.sendUser, (GroupID, Another)) # Main def Main(self): NoWork = 0 NoWorkLimit = 5 fetchNum = 50 cacheOperations = [] ncMessage = Operation() if "LastResetLimitTime" not in self.data.getData("Global"): self.data.getData("Global")["LastResetLimitTime"] = None if time.localtime().tm_hour == self.data.getData("Global")["LastResetLimitTime"]: self.limitReset(True) while YuukiVariable["Power"]: try: if time.localtime().tm_hour != self.data.getData("Global")["LastResetLimitTime"]: self.limitReset() self.data.updateData(self.data.getData("Global"), "LastResetLimitTime", time.localtime().tm_hour) if NoWork >= NoWorkLimit: NoWork = 0 for ncMessage in cacheOperations: if ncMessage.reqSeq != -1 and ncMessage.revision > self.revision: self.revision = ncMessage.revision break if ncMessage.revision != self.revision: self.revision = self.client.getLastOpRevision() try: cacheOperations = self.listen.fetchOperations(self.revision, fetchNum) except socket.timeout: NoWork += 1 if cacheOperations: NoWork = 0 self.Thread_Exec(self.taskDemux, (cacheOperations,)) if len(cacheOperations) > 1: self.revision = max(cacheOperations[-1].revision, cacheOperations[-2].revision) self.data.syncData() except KeyboardInterrupt: self.exit() except EOFError: pass except: (err1, err2, err3, ErrorInfo) = self.errorReport() try: for ncMessage in cacheOperations: if ncMessage.reqSeq != -1 and ncMessage.revision > self.revision: self.revision = ncMessage.revision break if ncMessage.revision != self.revision: self.revision = self.client.getLastOpRevision() for Root in self.Admin: self.sendText(Root, "Star Yuuki BOT - Something was wrong...\nError:\n%s\n%s\n%s\n\n%s" % (err1, err2, err3, ErrorInfo)) except: print("Star Yuuki BOT - Damage!\nError:\n%s\n%s\n%s\n\n%s" % (err1, err2, err3, ErrorInfo)) self.exit()