def add_user(self, user, mtime_avatar, afk=False, color=None): '''Adding user, and defining AFK status''' html_online = self.paths["online"] if color != None: self.usercolors[user] = color filename = "\\" + user + ".png" avatar = self.dirs["avatars"] + filename # Fetch avatar if not isfile(avatar) or (mtime_avatar != None and mtime_avatar > getmtime(avatar) + 0.3): FILE_WRITE(html_online, HTML_USER(user, afk), "a") self.datastream.put(("send", { "datatype": "avatar-fetch", "user": user })) # Add user with avatar else: self.avatar_thumb(user) FILE_WRITE(html_online, HTML_USER_AVATAR(user, self.dirs["thumbs"], afk), "a") if user == self.username: self.datastream.put(("send", {"datatype": "avatar-send"})) wx.CallAfter(self.userlist.LoadURL, html_online)
def add_room(self, event, addtype="send", roomtype=None, roomname=None, roompassword=None): '''Adding room''' if addtype == "send": # If user is adding # Show window and get variables addroom = AddRoomWindow(self) if addroom.proceed: roomtype, roomname, roompassword, roomwhitelist = addroom.roomtype, \ addroom.roomname, addroom.roompassword, addroom.roomwhitelist else: return # Adding room to variable rtype = self.GET_ROOMTYPE(roomtype) room = rtype[roomname] = {} if roompassword: room["password"] = True # Send room data to server if current user created it if addtype == "send": self.room_unique = None room["owner"] = True senddata = { "datatype": "add_room", "type": roomtype, "name": roomname } if roomtype == "private": if roompassword: senddata["password"] = HASH(roompassword) elif roomwhitelist != None: senddata["whitelist"] = roomwhitelist + [self.username] self.datastream.put(("send", senddata)) while self.room_unique == None: sleep(0.01) if not self.room_unique: return # Updating variables and files self.seconds[self.host][roomname] = [] self.lastupdate[self.host] = time() FILE_WRITE(self.paths["lastupdate"], self.lastupdate) FILE_WRITE(self.paths["rooms"], self.chatroomdata) FILE_WRITE(self.paths["chatlog"](roomname), HTML_CHAT) # Adding room in tree ctrl roomitem = self.roomtypes[roomtype] self.chatrooms.AppendItem(roomitem, roomname) if not self.chatrooms.IsExpanded(roomitem): self.chatrooms.Expand(roomitem)
def ACCOUNT_FILES(self, key, username, password): '''Setting up encryption key and account file''' userdir = appdata + username keystr = key.exportKey() accountinfo = b64encode( key.encrypt(str([username, password]), None)[0]) DIR_CREATE(userdir) FILE_WRITE(appdata + "current_key.txt", keystr) FILE_WRITE(appdata + "current_account.txt", accountinfo)
def switch_server(self, event): '''Switching server when clicking a server in the server list.''' server = self.servers.GetStringSelection() addr = server if server else self.host FILE_WRITE(appdata + "new_server.txt", [addr, self.serverdata[addr]]) self.quit(None)
def delete_room(self, event, name=None): '''Deleting room''' if event == None: # If someone else deleted room for roomtype in self.roomtypes: firstroom = self.chatrooms.GetFirstChild( self.roomtypes[roomtype]) room = firstroom[0] if room.IsOk(): while self.chatrooms.GetItemText(room) != name: if room.IsOk(): room = self.chatrooms.GetNextSibling(room) else: break else: continue else: # If this user deleted room room = self.roomhittest # Get room data roomname = self.chatrooms.GetItemText(room) parent = self.chatrooms.GetItemParent(room) roomtype = self.chatrooms.GetItemText(parent).split(" ")[0].lower() # Send room data if this user deleted room if event != None: self.datastream.put(("send", { "datatype": "del_room", "type": roomtype, "name": roomname })) # Delete and save wx.CallAfter(self.chatrooms.Delete, room) if self.currentroom == self.chatrooms.GetItemText(room): wx.CallAfter( self.chatrooms.SelectItem, self.chatrooms.GetFirstChild(self.chatrooms.GetRootItem())[0]) self.lastupdate[self.host] = time() FILE_WRITE(self.paths["lastupdate"], self.lastupdate) FILE_DELETE(self.paths["chatlog"](roomname)) del self.GET_ROOMTYPE(roomtype)[roomname] FILE_WRITE(self.paths["rooms"], self.chatroomdata)
def write_log(self, time, msg, room="GLOBAL CHAT"): '''Function for writing to log file''' date = time.split(" ")[0] if self.lastmsg != date: FILE_WRITE(self.paths["log"], "--- " + date + " ---\n", "a") # Date headline # Save date of last message self.lastmsg = date FILE_WRITE(self.paths["lastmsg"], "'" + self.lastmsg + "'") # Write to log file if room == "GLOBAL CHAT": roommsg = "" else: roommsg = "|" + room FILE_WRITE(self.paths["log"], ("[" + time.split(" ")[1] + roommsg + "] " + msg + "\n").encode(codec), "a")
def _save_avatar(self): '''Save avatar to file''' DIR_CREATE(appdata + "avatars") bitmap = self.image.GetBitmap() if bitmap != wx.NullBitmap: avatar_path = appdata + "avatars\\" + self.username + ".png" FILE_WRITE(avatar_path, "") bitmap.SaveFile(avatar_path, wx.BITMAP_TYPE_PNG)
def add_server(self, event): '''Add server when pressing the "Add server" button. Displays a window for the user to input server settings.''' addserver = AddServerWindow(self, self.serverdata) # Show window if addserver.proceed: addr = addserver.serveraddr port = addserver.serverport self.write_log(now(), "You added server: " + addr) self.serverdata[addr] = port # Add server to list self.chatroomdata[addr] = {"public": {}, "private": {}} self.seconds[addr] = {} # Save and show in list FILE_WRITE(self.paths["rooms"], self.chatroomdata) FILE_WRITE(self.paths["servers"], self.serverdata) self.servers.Append(addr)
def disconnect(self, event, sendmsg=True): self.quitting = self.disconnected = True # Saving settings if self.settings != self.initsettings: FILE_WRITE(self.paths["settings"], self.settings) # Disable widgets if event: html_online = self.paths["online"] self.chatinput.Disable() self.send.Disable() self.menu_connection_disconnect.Enable(False) self.servers.DeselectAll() FILE_WRITE(html_online, HTML_SESSION) self.userlist.LoadURL(html_online) self.conv_info.SetLabel(self.username + " - disconnected") # Unhooking hooks self.hook_remove() # Sending disconnect if sendmsg: msg = {"datatype": "disconnect"} if self.settings != self.initsettings: msg["settings"] = self.settings self._try_send(msg) # Joining threads threads = thread_enum() for thread in [self.thread_stream, self.thread_recv, self.thread_afk]: if thread in threads: thread.join() # Closing socket self.clientsocket.shutdown(SHUT_RDWR) self.clientsocket.close()
def mainfunc(self, event): '''Main function''' self.RESET_COLOR(*self.textboxes) field_oldpass, field_newpass, field_newpass_repeat = self.textboxes old_password = field_oldpass.GetValue() new_password = field_newpass.GetValue() # Error handling if len(old_password) == 0: self.SHOW_ERRORMSG("Please input a password.", field_oldpass) elif len(new_password) == 0: self.SHOW_ERRORMSG("Please input a new password.", field_newpass) elif field_newpass_repeat.GetValue() != new_password: self.SHOW_ERRORMSG("'New password' and 'Repeat new password'\nneed to be identical!", \ field_newpass, field_newpass_repeat) else: # Connect to server if no errors occured if self.CONNECT(self.host, self.port): SENDMSG({"actiontype": "changepass", "user": self.username, \ "old_pass": HASH(old_password), \ "new_pass": HASH(new_password)}, self.clientsocket) response = RECVMSG(self.clientsocket) if response == "PROCEED": # Create files and start main window userdir = appdata + "\\" + self.username + "\\" self.keygen.join() self.ACCOUNT_FILES(key_return(), self.username, new_password) FILE_WRITE(userdir + "oldpass.txt", HASH(old_password)) FILE_WRITE(userdir + "newpass.txt", str(self.servers)) from window_chat import ChatWindow ChatWindow(self.username, new_password, self.host, self.port, self.clientsocket) self.Destroy() else: self.DEFAULT_ERROR(response, self.inputs)
def edit_userlist(self, user, exist=True, afk=None, avatar=None): '''Function for editing user list''' html_online = self.paths["online"] # Loading and parsing HTML users_online = FILE_READ(html_online).split("\n") line_body = users_online.index("\t<body>") + 1 users = users_online[line_body:] # Get all lines containing usernames for line in users: if line.split("</span>")[0].split( ">")[-1] == user: # Find current user if not exist: users.remove(line) else: linepos = users.index(line) sep1 = "<span style='color: " # Change color (AFK) if afk != None: sep2 = "'>" start, temp_color = line.split(sep1) color, end = temp_color.split(sep2) color = "grey" if afk else "black" users[linepos] = start + sep1 + color + sep2 + end # Change avatar if avatar != None: tag_outer = "<div>" html_inner = line.split(tag_outer, 1)[1] html_img = "<img src=" if html_inner.startswith(html_img) and avatar == False: users[linepos] = tag_outer + html_inner.split( "/>", 1)[1] elif html_inner.startswith(sep1) and avatar: users[linepos] = tag_outer + html_img + self.dirs["thumbs"] + \ "\\" + user + ".png />" + html_inner # Update HTML and GUI users_online[line_body:] = users FILE_WRITE(html_online, "\n".join(users_online)) wx.CallAfter(self.userlist.LoadURL, html_online)
def settings_afk(self, event): '''Edit AFK settings''' new_afk = AFKSettings(self.settings["autoafk"], self.settings["afkinterval"]).new_settings if new_afk != None: # Save settings self.settings["autoafk"], self.settings["afkinterval"] = new_afk FILE_WRITE(self.paths["settings"], self.settings) self.autoafk = self.settings["autoafk"] # Start threads if auto-afk if self.settings["autoafk"]: self.afkinit = self.afktimer = self.settings["afkinterval"] if self.thread_afk not in thread_enum(): self.thread_afk = MultiThread(self.afk_countdown) self.thread_afk.daemon = True self.thread_afk.start()
def quit(self, event, sendmsg=True): '''Quitting the application''' self.Hide() # Disconnecting if not self.disconnected: self.disconnect(None, sendmsg) # Handling files if event: FILE_WRITE(appdata + "new_server.txt", [None, None]) DIR_DELETE(self.dirs["chatlogs"]) DIR_DELETE(self.dirs["thumbs"]) FILE_DELETE(self.paths["online"]) # Destroy window self.Destroy()
def set_color(self, event): '''Set and apply color to your messages''' # Get color and convert to hex if event: newcolor = self.colorpopup.FindItemById( event.GetId()).GetBackgroundColour() else: newcolor = self.colorpicker.GetColourData().GetColour() newcolor = newcolor.GetAsString(wx.C2S_HTML_SYNTAX) # Save color self.settings["color"] = color = newcolor FILE_WRITE(self.paths["settings"], self.settings) self.datastream.put(("send", {"datatype": "color", "value": color})) # Apply color self.chatinput.SetForegroundColour(color) if event: self.chatinput.SetFocus()
def avatar_change(self, user, avatar): '''Function for creating/changing avatar''' path_avatar = self.dirs["avatars"] + "\\" + user + ".png" time_now = now() # Write to log if user == self.username: self.write_log(time_now, "You changed your avatar.") else: self.write_log(time_now, user + " changed their avatar.") # Save avatar if type(avatar) == wx.Bitmap: avatar.SaveFile(path_avatar, wx.BITMAP_TYPE_PNG) else: FILE_WRITE(path_avatar, avatar, "wb") self.avatar_thumb(user) # Create thumbnail for user list # Update user list self.edit_userlist(user, avatar=True) wx.CallAfter(self.userlist.LoadURL, self.paths["online"])
def toggle_seconds(self, event): '''Toggle if seconds sould be displayed in the conversation window''' file_html = self.paths["chatlog"](self.currentroom) roomseconds = self.seconds[self.host][self.currentroom] # Get HTML of conversation window htmldoc = FILE_READ(file_html) self.settings["seconds"] = self.tool_seconds.IsToggled( ) # Update setting # Parse the HTML and inject/extract the seconds splithtml = htmldoc.split("title=\"") newhtml = splithtml[0] for x in range(len(roomseconds)): splitdate = splithtml[1:][x].split("\">") newhtml += "title=\"" + splitdate[0] + "\">" if self.tool_seconds.IsToggled(): self.settings["seconds"] = True newhtml += splitdate[1].split("</td>")[0] + ":" + str( roomseconds[x]) else: self.settings["seconds"] = False newhtml += ":".join( splitdate[1].split("</td>")[0].split(":")[:-1]) newhtml += "</td>" + "</td>".join( splitdate[1].split("</td>")[1:]) + "\">" + "\">".join( splitdate[2:]) newhtml = newhtml[:-2] + newhtml[-2:].replace("\">", "") # Update and reload HTML file FILE_WRITE(file_html, newhtml) self.chattext.LoadURL(file_html)
def change_password(self, event): '''Changing password''' FILE_WRITE(appdata + "new_server.txt", [self.host, self.serverdata[self.host]]) self.quit(None) ChangePassWindow(self.host, self.port, self.username, self.password, self.servers.GetItems())
def __init__(self, username, password, host, port, clientsocket): wx.Frame.__init__(self, None, title=__appname__ + " " + __version__) # Making args class-namespaced self.host = host self.port = port self.username = username self.password = password self.clientsocket = clientsocket # Path variables self.userdir = appdata + self.username + "\\" self.dirs = { "avatars": appdata + "avatars", "chatlogs": self.userdir + "chatlogs", "chatlogs_server": lambda: self.userdir + "chatlogs\\" + self.host, "thumbs": self.userdir + "thumbs" } self.paths = { "avatar": self.dirs["avatars"] + "\\" + self.username + ".png", "chatlog": lambda roomname: self.dirs["chatlogs_server"]() + "\\" + roomname + ".html", "contacts": self.userdir + "contacts.txt", "lastmsg": self.userdir + "lastmsg.txt", "lastupdate": self.userdir + "lastupdate.txt", "log": self.userdir + "log.log", "online": self.userdir + "online.html", "rooms": self.userdir + "rooms.txt", "servers": self.userdir + "servers.txt", "settings": self.userdir + "settings.txt" } # Misc variables self.new_server = [None, None] self.currentroom = "GLOBAL CHAT" self.roomaccess = [] self.seconds = {} self.roomtypes = {} self.usercolors = {} self.datastream = Queue() # self.commands = ["afk", "die", "exit", "help"] self.colordata = self.roomhittest = None self.disconnected = self.quitting = self.reconnecting = False self.autoafk = True self.banned_html = ["body", "caption", "form", "frame", "head", "html", "iframe", "link", "script", "style", \ "table", "tbody", "td", "tfoot", "thead", "tr"] # Loading values file_room = self.paths["rooms"] self.chatroomdata = FILE_LOAD(file_room, {}) self.serverdata = FILE_LOAD(self.paths["servers"], {self.host: port}) self.lastupdate = FILE_LOAD(self.paths["lastupdate"], {self.host: time()}) # Getting startup information from server self.userdata = eval(RECVMSG(self.clientsocket)) # Checking if room file needs to be updated if (self.host not in self.lastupdate) or (self.host not in self.chatroomdata) or \ (self.userdata["mtime-rooms"] > self.lastupdate[self.host] + 0.1): self._try_send("SEND-ROOMS") self.chatroomdata[self.host] = eval(RECVMSG(self.clientsocket)) FILE_WRITE(file_room, self.chatroomdata) self.lastupdate[self.host] = time() FILE_WRITE(self.paths["lastupdate"], self.lastupdate) else: self._try_send("DONT-SEND-ROOMS") self.chatroomdata = eval(FILE_READ(file_room)) # Managing settings settings = self.paths["settings"] action_settings = self.startup_data("settings") if action_settings == "FETCH": response = RECVMSG(self.clientsocket) if response == "NO-SETTINGS": self.settings = defaultsettings self._try_send(self.settings) else: self.settings = eval(response) self.new_settings() FILE_WRITE(settings, self.settings) else: self.settings = eval(FILE_READ(settings)) self.new_settings() if self.userdata["mtime-settings"] == None: self._try_send(self.settings) self.initsettings = deepcopy(self.settings) self.afkinit = self.afktimer = self.settings["afkinterval"] # Creating structure of "seconds" variable for server in self.chatroomdata: self.seconds[server] = {} self.seconds[server]["GLOBAL CHAT"] = [] for room in self.GET_ROOMTYPE("public").keys() + self.GET_ROOMTYPE("private").keys(): self.seconds[server][room] = [] # Setting up folders and files DIR_CREATE(self.dirs["avatars"]) DIR_CREATE(self.dirs["chatlogs"]) DIR_CREATE(self.dirs["chatlogs_server"]()) DIR_CREATE(self.dirs["thumbs"]) FILE_WRITE(self.paths["chatlog"](self.currentroom), HTML_CHAT) FILE_WRITE(self.paths["online"], HTML_SESSION) # Panel self.panel = wx.Panel(self) # Popup menu: Colors self.colorpopup = wx.Menu() colors = ["white", "grey", "black", "red", (255, 127, 0), "yellow", "green", "cyan", "blue", "navy", "purple"] for color in colors: coloritem = wx.MenuItem(self.colorpopup, wx.ID_ANY, " ") coloritem.SetBackgroundColour(color) self.colorpopup.AppendItem(coloritem) self.Bind(wx.EVT_MENU, self.set_color, coloritem) self.colorpopup.AppendSeparator() colorwheel = self.colorpopup.Append(wx.ID_ANY, "Color wheel...") self.Bind(wx.EVT_MENU, self.color_dialog, colorwheel) # Popup menu: Rooms self.roommenu = wx.Menu() room_delete = wx.MenuItem(self.roommenu, wx.ID_ANY, "Delete room") self.roommenu.AppendItem(room_delete) self.Bind(wx.EVT_MENU, self.delete_room, room_delete) # Menu bar menubar = wx.MenuBar() menu_settings = wx.Menu() menu_settings_afk = menu_settings.Append(wx.ID_ANY, "AFK...") menu_settings_avatar = menu_settings.Append(wx.ID_ANY, "Avatar...") menu_settings_emotes = menu_settings.Append(wx.ID_ANY, "Emotes...") if basename(split(getcwd())[0]) == "CharlieChat Dev": menu_settings_messages = menu_settings.Append(wx.ID_ANY, "Messages...") # @UnusedVariable menu_settings_sounds = menu_settings.Append(wx.ID_ANY, "Sounds...") # @UnusedVariable menu_settings_text = menu_settings.Append(wx.ID_ANY, "Text...") # @UnusedVariable menu_account = wx.Menu() menu_account_switchuser = menu_account.Append(wx.ID_ANY, "Switch user...") menu_account_register = menu_account.Append(wx.ID_ANY, "Register new user...") menu_account_changepass = menu_account.Append(wx.ID_ANY, "Change password...") menu_account_delete = menu_account.Append(wx.ID_ANY, "Delete account") menu_connection = wx.Menu() self.menu_connection_disconnect = menu_connection.Append(wx.ID_ANY, "Disconnect") menu_connection_restart = menu_connection.Append(wx.ID_ANY, "Restart connection") menubar.Append(menu_settings, "Settings") menubar.Append(menu_account, "Account") menubar.Append(menu_connection, "Connection") self.SetMenuBar(menubar) # Toolbar self.toolbar = self.CreateToolBar() self.tool_sounds = self.toolbar.AddCheckLabelTool(1, "Seconds", wx.Bitmap("images/speaker.png")) self.tool_seconds = self.toolbar.AddCheckLabelTool(2, "Sounds", wx.Bitmap("images/seconds.png")) self.tool_afk = self.toolbar.AddCheckLabelTool(3, "AFK", wx.Bitmap("images/afk.png")) self.toolbar.Realize() self.toolbar.SetToolShortHelp(1, "Toggle sounds") self.toolbar.SetToolShortHelp(2, "Toggle display of seconds in chat window") self.toolbar.SetToolShortHelp(3, "Toggle whether you are shown as AFK or not") # Sizers box = wx.BoxSizer() grid = wx.FlexGridSizer(2, 1, 10, 10) header = wx.FlexGridSizer(1, 2, 10, 10) windows = wx.FlexGridSizer(1, 3, 10, 10) chat = wx.FlexGridSizer(0, 1, 10, 10) chatbuttons = wx.FlexGridSizer(1, 2, 10, 10) roomsettings = wx.FlexGridSizer(5, 1, 10, 10) conversation = wx.GridSizer(1, 0, 5, 5) # Widgets webcam = wx.ToggleButton(self.panel, label="Webcam") voice = wx.ToggleButton(self.panel, label="Voice") self.chattext = WebView.New(self.panel) self.add_msg("", HTML_WELCOME, now(), "black", self.currentroom, False) FILE_WRITE(self.paths["chatlog"](self.currentroom), HTML_LINE, "a") self.chatinput = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE | wx.TE_PROCESS_ENTER) self.send = wx.Button(self.panel, label="SEND", size=(-1, 50)) colorbutton = wx.BitmapButton(self.panel, bitmap=wx.Image("images/colorwheel.png", \ wx.BITMAP_TYPE_PNG).ConvertToBitmap(), size=(50, 50)) usercontainer = wx.Notebook(self.panel) users_online = PanelUsermode(self, usercontainer, self.paths["online"]) self.users_contacts = PanelUsermode(self, usercontainer, "contacts") usercontainer.AddPage(users_online, "Online") usercontainer.AddPage(self.users_contacts, "Contacts") self.conv_info = wx.StaticText(self.panel, label=self.host + ": " + self.username) self.reconnect = wx.StaticText(self.panel, label="Reconnecting") self.servers = wx.ListBox(self.panel, style=wx.LB_SINGLE) server_add = wx.Button(self.panel, label="Add server") self.chatrooms = wx.TreeCtrl(self.panel, style=wx.TR_HAS_BUTTONS | wx.TR_HIDE_ROOT | \ wx.TR_ROW_LINES | wx.TR_MULTIPLE) room_search = wx.SearchCtrl(self.panel) room_add = wx.Button(self.panel, label="Add room") # Fonts font = self.conv_info.GetFont() font.SetPointSize(14) self.conv_info.SetFont(font) font.SetPointSize(12) font.SetWeight(wx.BOLD) self.send.SetFont(font) font = self.chatinput.GetFont() font.SetPointSize(11) self.chatinput.SetFont(font) font = self.reconnect.GetFont() font.SetWeight(wx.BOLD) self.reconnect.SetFont(font) # Add servers to list widget if self.host not in self.serverdata: self.serverdata[self.host] = self.port FILE_WRITE(self.paths["servers"], self.serverdata) self.servers.Append(self.host) for lbl_server in self.serverdata: self.servers.Append(lbl_server) self.servers.SetSelection(self.servers.GetItems().index(self.host)) # Global room root = self.chatrooms.AddRoot("") globalroom = self.chatrooms.AppendItem(root, "GLOBAL CHAT") self.chatrooms.SetItemBold(globalroom) # Loop: roomtypes for lbl_roomtype in self.GET_SERVER(): roomtype = self.chatrooms.AppendItem(root, lbl_roomtype.title() + " rooms") self.chatrooms.SetItemBold(roomtype) self.roomtypes[lbl_roomtype] = roomtype # Loop: rooms for lbl_room in self.GET_ROOMTYPE(lbl_roomtype): self.chatrooms.AppendItem(roomtype, lbl_room) # Update HTML for each room FILE_WRITE(self.paths["chatlog"](lbl_room), HTML_CHAT) self.chatrooms.ExpandAll() self.chatrooms.SelectItem(globalroom) # Add widgets to sizers conversation.AddMany([webcam, voice]) chat.AddMany([conversation, (self.chattext, 1, wx.EXPAND), (self.chatinput, 1, wx.EXPAND), (chatbuttons, 1, wx.EXPAND)]) header.AddMany([self.conv_info, (self.reconnect, 0, wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM)]) chatbuttons.AddMany([(self.send, 1, wx.EXPAND), colorbutton]) roomsettings.AddMany([(self.servers, 1, wx.EXPAND), (server_add, 1, wx.EXPAND), (self.chatrooms, 1, wx.EXPAND), \ (room_search, 1, wx.EXPAND), (room_add, 1, wx.EXPAND)]) windows.AddMany([(usercontainer, 1, wx.EXPAND), (chat, 1, wx.EXPAND), (roomsettings, 1, wx.EXPAND)]) grid.AddMany([(header, 1, wx.EXPAND), (windows, 1, wx.EXPAND)]) box.Add(grid, 1, wx.ALL | wx.EXPAND, 20) self.panel.SetSizer(box) # Define growables and ratios chat.AddGrowableRow(1, 10) # Chat height chat.AddGrowableRow(2, 2) # Input height chat.AddGrowableCol(0) # Chat width windows.AddGrowableRow(0) # Users height windows.AddGrowableCol(0, 3) # Users width windows.AddGrowableCol(1, 10) # Chat + input + buttons width windows.AddGrowableCol(2, 1) # Chatrooms width roomsettings.AddGrowableCol(0) # Chatrooms width roomsettings.AddGrowableRow(0, 1) # Chatrooms height roomsettings.AddGrowableRow(2, 5) # Chatrooms height chatbuttons.AddGrowableCol(0) # Send button width header.AddGrowableCol(1) # Reconnect text grid.AddGrowableCol(0) # Conversation info width grid.AddGrowableRow(1) # Widgets height # Window size self.SetClientSize((1050, 518)) self.SetMinSize((454, 413)) # Binding events self.Bind(wx.EVT_MENU, self.settings_afk, menu_settings_afk) self.Bind(wx.EVT_MENU, self.settings_avatar, menu_settings_avatar) self.Bind(wx.EVT_MENU, self.settings_emotes, menu_settings_emotes) self.Bind(wx.EVT_MENU, self.switch_user, menu_account_switchuser) self.Bind(wx.EVT_MENU, self.register_user, menu_account_register) self.Bind(wx.EVT_MENU, self.change_password, menu_account_changepass) self.Bind(wx.EVT_MENU, self.delete_user, menu_account_delete) self.Bind(wx.EVT_MENU, self.disconnect, self.menu_connection_disconnect) self.Bind(wx.EVT_MENU, self.switch_server, menu_connection_restart) self.Bind(wx.EVT_TOOL, self.toggle_seconds, self.tool_seconds) self.Bind(wx.EVT_TOOL, self.toggle_sounds, self.tool_sounds) self.Bind(wx.EVT_TOOL, self.toggle_afk, self.tool_afk) self.Bind(wx.EVT_LISTBOX, self.switch_server, self.servers) self.Bind(wx.EVT_BUTTON, self.add_server, server_add) self.Bind(wx.EVT_TREE_SEL_CHANGING, self.switch_room, self.chatrooms) self.chatrooms.Bind(wx.EVT_RIGHT_DOWN, self.popup_room) self.Bind(wx.EVT_TEXT, self.search_rooms, room_search) room_search.Bind(wx.EVT_KEY_DOWN, ERASE_TEXT) self.Bind(wx.EVT_BUTTON, self.add_room, room_add) self.Bind(wx.EVT_TOGGLEBUTTON, self.toggle_webcam, webcam) self.Bind(wx.EVT_TOGGLEBUTTON, self.toggle_voice, voice) self.Bind(EVT_WEBVIEW_NAVIGATING, self.url_navigate, self.chattext) self.Bind(wx.EVT_BUTTON, self.popup_color, colorbutton) self.chatinput.Bind(wx.EVT_KEY_DOWN, self.chat_hotkeys) self.Bind(wx.EVT_BUTTON, self.msg_send, self.send) self.Bind(wx.EVT_CLOSE, self.quit) # Hiding reconnect (only show when actually reconnecting) self.reconnect.Hide() # self.contactlist.Hide() # Set focus to text input (start writing instantly) self.chatinput.SetFocus() # Applying settings self.apply_settings() self.chatinput.SetForegroundColour(self.settings["color"]) # Loading contacts action_contacts = self.startup_data("contacts") if action_contacts == "FETCH": response = RECVMSG(self.clientsocket) if response == "NO-CONTACTS": if not isfile(self.paths["contacts"]): with open(self.paths["contacts"], "w"): pass with open(self.paths["contacts"]) as contactfile: self._try_send(contactfile.read()) else: with open(self.paths["contacts"], "w") as contactfile: contactfile.write(response) else: if self.userdata["mtime-contacts"] == None: with open(self.paths["contacts"]) as contactfile: self._try_send(contactfile.read()) self.load_contacts() # Starting threads self.thread_stream = MultiThread(self.data_actions) self.thread_recv = MultiThread(self.msg_recv) self.thread_afk = MultiThread(self.afk_countdown) self.thread_stream.daemon = True self.thread_recv.daemon = True self.thread_afk.daemon = True self.thread_stream.start() self.thread_recv.start() if self.settings["autoafk"]: self.thread_afk.start() self.init_voice() MultiThread(self.empty_voicebuffer).start() # Load timestamp of last message (determine if log file needs new date header) self.lastmsg = FILE_LOAD(self.paths["lastmsg"], "'" + now().split(" ")[0] + "'") # Add users to list of connected users self.add_user(self.username, self.userdata["mtime-avatar"]) for user in self.userdata["users"]: self.add_user(user, self.userdata["users"][user]["mtime-avatar"], user in self.userdata["afks"], \ self.userdata["users"][user]["color"]) # Set icon (REMOVE set_appname WHEN .exe) set_appname() self.SetIcon(wx.Icon("images/testicon.ico")) self.hook_establish() # Showing window self.Center() self.Show()
with open(tempfiles + "\\" + f, "wb") as updatefile: updatefile.write("".join(filecontent)) # Update bytes and percent progress currentbytes += sum([len(x) for x in filecontent]) percent = int(float(currentbytes) / totalbytes * 100) progress.SetTitle(title.format(str(percent))) except (ftperror, EOFError): updatefiles.append(f) # Re-add file to loop if something goes wrong except socketerror: connect() ftp.close() FILE_WRITE(appdata + "\\last_update.txt", datetime.now().strftime("%d-%m-%Y %H:%M:%S")) # Deleting local files/dirs if not on server if not __version__.endswith(" [DEV]"): for f in updatefiles: move(tempfiles + "\\" + f, f) DIR_DELETE("tempfiles") currentdir = getcwd() programdirs = ["core", "images", "lib", "ui", "util", "windows"] for pdir in programdirs: for path, folders, files in walk(currentdir + "\\" + pdir): for f in files: filepath = relpath(path + "\\" + f)
def switch_user(self, event): '''Switching user''' FILE_WRITE(appdata + "new_server.txt", [self.host, self.serverdata[self.host]]) self.quit(None) AccountWindow("switch user", self.host, self.port, self.username, self.password, ["username", "password"])
from windows.window_chat import ChatWindow from windows.wizard.page_start import PageStart # File paths current_account = appdata + "current_account.txt" current_key = appdata + "current_key.txt" new_server = appdata + "new_server.txt" last_update = appdata + "\\last_update.txt" # Creating instances Connect = Connect() DIR_CREATE(appdata) if not isfile(last_update): FILE_WRITE(last_update, datetime.now().strftime("%d-%m-%Y %H:%M:%S")) FILE_DELETE(new_server) # Creating error file # sys.stderr = open(appdata + "error.log", "a") # Starting application app = App() if isfile(current_account) and isfile(current_key): while host != None and port != None: # Connecting if Connect.CONNECT(host, port, False): key = RSA.importKey(FILE_READ(current_key)) username, password = eval(key.decrypt(b64decode(FILE_READ(current_account)))) # Changing password when connecting
def register_user(self, event): '''Registering new user''' FILE_WRITE(appdata + "new_server.txt", [self.host, self.serverdata[self.host]]) self.quit(None) AccountWindow("register", self.host, self.port, self.username, self.password, \ ["username", "password", "repeat password"])
def data_actions(self): '''Handling all data sent and received''' # nolog = ["add_room", "afk", "avatar-change", "avatar-fetch", "avatar-send", "color", \ # "del_room", "del_user", "noaccess", "roompass", "voice", "webcam"] # log = ["chat", "command", "connect", "disconnect"] while True: if self.quitting: return sleep(0.01) # Preventing CPU gobbling if not self.datastream.empty(): data_raw = self.datastream.get() # Get next message from datastream data = data_raw[1] datatype = data["datatype"] ### SENDING MESSAGE ### if data_raw[0] == "send": time_now = now() # Write log if datatype == "add_room": self.write_log(time_now, "You added " + data["type"] + " room: " + data["name"]) elif datatype in self.log_commands: self.write_log(time_now, self.username + ": " + data["msg"], self.currentroom) self._try_send(data) if datatype in self.log_commands: # Commands if data["msg"] in ["/" + c for c in self.commands]: if data["msg"] == "/help": self.add_msg("", "You need help!", time_now, "black", self.currentroom) elif data["msg"] == "/afk": self.afktimer = 0 self.afk_actions(True) # Chat messages else: self.add_msg(self.username, data["msg"], time_now, self.settings["color"], self.currentroom) ### RECEIVING MESSAGE ### elif data_raw[0] == "recv": print datatype # User connecting # if datatype == "connect": self.write_log(data["time"], data["user"] + " connected.") self.add_user(data["user"], data["mtime-avatar"], color=data["color"]) self.add_msg("", data["user"] + " connected.", data["time"], "black", self.currentroom) # Sending avatar to server # elif datatype == "avatar-send": if data["value"] == True: self._try_send({"datatype": "avatar-send", "value": FILE_READ(self.paths["avatar"], True)}) # Fetching avatar from server # elif datatype == "avatar-fetch": if data["value"] != False: FILE_WRITE(self.dirs["avatars"] + "\\" + data["user"] + ".png", data["value"], "wb") self.avatar_thumb(data["user"]) self.edit_userlist(data["user"], avatar=True) # Changing avatar # elif datatype == "avatar-change": if data["value"] == "delete": self.avatar_delete(data["user"]) else: self.avatar_change(data["user"], data["value"]) elif datatype == "contact-exists": if data["value"]: with open(self.paths["contacts"], "a") as contactfile: contactfile.write(data["contact"] + "\n") self.users_contacts.widget.Append([data["contact"]]) self.users_contacts.contact_name.Clear() # Changing text color elif datatype == "color": self.usercolors[data["user"]] = data["value"] # Chat message # elif datatype == "chat": room = data["room"] if "room" in data else "GLOBAL CHAT" self.write_log(data["time"], data["user"] + ": " + data["msg"], room) self.add_msg(data["user"], data["msg"], data["time"], self.usercolors[data["user"]], room) # Command # elif datatype == "command": self.write_log(data["time"], data["user"] + ": " + data["msg"]) if data["msg"] == "/help": self.add_msg("", data["user"] + " needs help!", data["time"], "black", self.currentroom) # AFK # elif datatype == "afk": if data["status"]: self.write_log(data["time"], data["user"] + " is AFK.") self.add_msg("", data["user"] + " is AFK.", data["time"], "black", self.currentroom) else: self.write_log(data["time"], data["user"] + " is back.") self.add_msg("", data["user"] + " is back.", data["time"], "black", self.currentroom) self.afk_actions(data["status"], data["user"]) # Adding room # elif datatype == "add_room": self.write_log(data["time"], data["user"] + " added " + data["type"] + " room: " + data["name"]) self.add_room(None, "recv", data["type"], data["name"], "password" in data) # Is room unique? # elif datatype == "room_unique": self.room_unique = data["value"] # Was room password correct? # elif datatype == "roompass": self.roomprompt = data["proceed"] # Deleting room # elif datatype == "del_room": self.write_log(data["time"], data["user"] + " deleted " + data["type"] + " room: " + data["name"]) self.delete_room(None, data["name"]) elif datatype == "webcam": webcam.recv_camstream(data["data"]) elif datatype == "voice": voice.recv_voice(data["data"]) # User disconnecting # elif datatype == "disconnect": self.write_log(data["time"], data["user"] + " disconnected.") self.edit_userlist(data["user"], False) self.add_msg("", data["user"] + " disconnected.", data["time"], "black", self.currentroom) # Flash window and play sound (if window doesn't have focus) if (datatype not in ["add_room", "avatar-change", "avatar-fetch", "avatar-send", \ "del_room", "roompass", "room_unique", "voice", "webcam"]): flash_window(self.GetHandle(), self.settings["sounds"])
def settings_emotes(self, event): '''Edit emote settings''' new_emotes = EmoteSettings(self.settings["notemotes"]).new_settings if new_emotes != None: self.settings["notemotes"] = new_emotes FILE_WRITE(self.paths["settings"], self.settings)
def add_msg(self, user, msg, time, color, room, space=True): '''Adding message to conversation (HTML file)''' private = self.GET_ROOMTYPE("private") access = True if room in private and "password" in private[ room] and room not in self.roomaccess: access = False if access: # Check if you have access to room (should always happen - this is in case of permission errors) # Display seconds or not, depending on setting self.seconds[self.host][room].append(time.split(":")[-1]) if self.settings["seconds"]: timestamp = time.split(" ")[1] else: timestamp = ":".join(time.split(" ")[1].split(":")[:-1]) msg = msg.replace("\n", " <br /> ") # Replace new line with HTML break for tag in self.banned_html: msg = msg.replace("<" + tag, "<" + tag).replace("</" + tag + ">", "</" + \ tag + ">").replace("</ " + tag + ">", "</ " + tag + ">") msgsplit = msg.split(" ") for wordnum, word in enumerate(msgsplit): # Adding HTML links if word.startswith("http://") or word.startswith( "https://") or word.startswith("ftp://"): msgsplit[ wordnum] = "<a href='" + word + "'>" + word + "</a>" elif word.startswith("www."): msgsplit[ wordnum] = "<a href='http://" + word + "'>" + word + "</a>" # Adding emotes settings_emotes = self.settings["notemotes"] if settings_emotes != "ALL": if len(word ) > 0 and word[0] in "cCsSxXToO0:;=-^/\\([{<>|?": for name, pattern in emote_patterns.items(): imgpath = getcwd( ) + "\\images\\emotes\\" + name + ".png" if name not in settings_emotes and match( pattern, word) and isfile(imgpath): msgsplit[ wordnum] = "<img src='" + imgpath + "' title='" + name.replace( "_", " ").title() + "' />" break msg = " ".join(msgsplit) # Update HTML file htmlfile = self.paths["chatlog"](room) html = "<tr style='color:" + color + "'>\n <td " if space: html += "valign='top'>" + user + "</td>\n <td " else: html += "colspan=2 " html += "class='msg'>" + msg + "</td>\n <td valign='top' title='" + time.split( " ")[1] + "'>" + timestamp + "</td>\n</tr>\n" FILE_WRITE(htmlfile, html.encode(codec), "a") # Load HTML file (if message was sent to current room) if self.currentroom == room: wx.CallAfter(self.chattext.LoadURL, htmlfile) else: # If permission error: send noaccess to server self.datastream.put(("send", { "datatype": "noaccess", "room": room }))