├── ChatFns.py ├── README.txt ├── client.pyw ├── host.pyw └── notif.wav /ChatFns.py: -------------------------------------------------------------------------------- 1 | from Tkinter import * 2 | from socket import * 3 | import urllib 4 | import re 5 | import pygame 6 | import win32gui 7 | 8 | def getmixerargs(): 9 | pygame.mixer.init() 10 | freq, size, chan = pygame.mixer.get_init() 11 | return freq, size, chan 12 | def initMixer(): 13 | BUFFER = 3072 # audio buffer size, number of samples since pygame 1.8. 14 | FREQ, SIZE, CHAN = getmixerargs() 15 | pygame.mixer.init(FREQ, SIZE, CHAN, BUFFER) 16 | def playsound(soundfile): 17 | """Play sound through default mixer channel in blocking manner. 18 | This will load the whole sound into memory before playback 19 | """ 20 | pygame.init() 21 | pygame.mixer.init() 22 | sound = pygame.mixer.Sound(soundfile) 23 | clock = pygame.time.Clock() 24 | sound.play() 25 | while pygame.mixer.get_busy(): 26 | clock.tick(1000) 27 | def playmusic(soundfile): 28 | """Stream music with mixer.music module in blocking manner. 29 | This will stream the sound from disk while playing. 30 | """ 31 | pygame.init() 32 | pygame.mixer.init() 33 | clock = pygame.time.Clock() 34 | pygame.mixer.music.load(soundfile) 35 | pygame.mixer.music.play() 36 | while pygame.mixer.music.get_busy(): 37 | clock.tick(1000) 38 | def stopmusic(): 39 | """stop currently playing music""" 40 | pygame.mixer.music.stop() 41 | 42 | #HOW TO PLAY SONG: 43 | initMixer() 44 | #playmusic(filename) 45 | 46 | 47 | 48 | def FlashMyWindow(title): 49 | ID = win32gui.FindWindow(None, title) 50 | win32gui.FlashWindow(ID,True) 51 | 52 | def FlashMyWindow2(title2): 53 | ID2 = win32gui.FindWindow(None, title2) 54 | win32gui.FlashWindow(ID2,True) 55 | 56 | def GetExternalIP(): 57 | url = "http://checkip.dyndns.org" 58 | request = urllib.urlopen(url).read() 59 | return str(re.findall(r"\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}", request)) 60 | 61 | def GetInternalIP(): 62 | return str(gethostbyname(getfqdn())) 63 | 64 | def FilteredMessage(EntryText): 65 | """ 66 | Filter out all useless white lines at the end of a string, 67 | returns a new, beautifully filtered string. 68 | """ 69 | EndFiltered = '' 70 | for i in range(len(EntryText)-1,-1,-1): 71 | if EntryText[i]!='\n': 72 | EndFiltered = EntryText[0:i+1] 73 | break 74 | for i in range(0,len(EndFiltered), 1): 75 | if EndFiltered[i] != "\n": 76 | return EndFiltered[i:]+'\n' 77 | return '' 78 | 79 | def LoadConnectionInfo(ChatLog, EntryText): 80 | if EntryText != '': 81 | ChatLog.config(state=NORMAL) 82 | if ChatLog.index('end') != None: 83 | ChatLog.insert(END, EntryText+'\n') 84 | ChatLog.config(state=DISABLED) 85 | ChatLog.yview(END) 86 | 87 | def LoadMyEntry(ChatLog, EntryText): 88 | if EntryText != '': 89 | ChatLog.config(state=NORMAL) 90 | if ChatLog.index('end') != None: 91 | LineNumber = float(ChatLog.index('end'))-1.0 92 | ChatLog.insert(END, "You: " + EntryText) 93 | ChatLog.tag_add("You", LineNumber, LineNumber+0.4) 94 | ChatLog.tag_config("You", foreground="#FF8000", font=("Arial", 12, "bold")) 95 | ChatLog.config(state=DISABLED) 96 | ChatLog.yview(END) 97 | 98 | 99 | def LoadOtherEntry(ChatLog, EntryText): 100 | if EntryText != '': 101 | ChatLog.config(state=NORMAL) 102 | if ChatLog.index('end') != None: 103 | try: 104 | LineNumber = float(ChatLog.index('end'))-1.0 105 | except: 106 | pass 107 | ChatLog.insert(END, "Other: " + EntryText) 108 | ChatLog.tag_add("Other", LineNumber, LineNumber+0.6) 109 | ChatLog.tag_config("Other", foreground="#04B404", font=("Arial", 12, "bold")) 110 | ChatLog.config(state=DISABLED) 111 | ChatLog.yview(END) 112 | 113 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | The codes are free for all, you can use it for whatever means you want. 2 | 3 | This chat program requires you to have python 2.x installed, python 3.x won't work. 4 | 5 | FIRST: CONFIGURE YOUR PROGRAM! 6 | 1) install win32gui at http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/ 7 | 8 | 2) install pygame (http://www.pygame.org/download.shtml) 9 | 10 | 3) In client.pyw file, go to line 8, replace 'YOUR EXTERNAL IP ADDRESS HERE' with your external 11 | ip address. You can find it on http://www.whatismyip.com/ 12 | 13 | 4) Login on your default gateway, and enable DMZ, and set DMZ Host IP Address to be the INTERNAL IP ADDRESS of 14 | YOUR computer, assuming you are the host. (if you don't know how to do this, watch the tutorial on my channel 15 | or send me a message) 16 | 17 | NEXT, HOW TO MAKE IT RUN? 18 | On your computer, open the host.pyw file. On your partner's computer, open the client.pyw file. 19 | If it says connected, then you are ready to go! 20 | 21 | -------------------------------------------------------------------------------- /client.pyw: -------------------------------------------------------------------------------- 1 | import thread 2 | from ChatFns import * 3 | 4 | #---------------------------------------------------# 5 | #---------INITIALIZE CONNECTION VARIABLES-----------# 6 | #---------------------------------------------------# 7 | WindowTitle = 'JChat v0.1 - Client' 8 | HOST = "YOUR EXTERNAL IP ADDRESS HERE" 9 | PORT = 8011 10 | s = socket(AF_INET, SOCK_STREAM) 11 | 12 | 13 | 14 | 15 | #---------------------------------------------------# 16 | #------------------ MOUSE EVENTS -------------------# 17 | #---------------------------------------------------# 18 | def ClickAction(): 19 | #Write message to chat window 20 | EntryText = FilteredMessage(EntryBox.get("0.0",END)) 21 | LoadMyEntry(ChatLog, EntryText) 22 | 23 | #Scroll to the bottom of chat windows 24 | ChatLog.yview(END) 25 | 26 | #Erace previous message in Entry Box 27 | EntryBox.delete("0.0",END) 28 | 29 | #Send my mesage to all others 30 | s.sendall(EntryText) 31 | 32 | #---------------------------------------------------# 33 | #----------------- KEYBOARD EVENTS -----------------# 34 | #---------------------------------------------------# 35 | def PressAction(event): 36 | EntryBox.config(state=NORMAL) 37 | ClickAction() 38 | def DisableEntry(event): 39 | EntryBox.config(state=DISABLED) 40 | 41 | 42 | #---------------------------------------------------# 43 | #-----------------GRAPHICS MANAGEMENT---------------# 44 | #---------------------------------------------------# 45 | 46 | #Create a window 47 | base = Tk() 48 | base.title(WindowTitle) 49 | base.geometry("400x500") 50 | base.resizable(width=FALSE, height=FALSE) 51 | 52 | #Create a Chat window 53 | ChatLog = Text(base, bd=0, bg="white", height="8", width="50", font="Arial",) 54 | ChatLog.insert(END, "Connecting to your partner..\n") 55 | ChatLog.config(state=DISABLED) 56 | 57 | #Bind a scrollbar to the Chat window 58 | scrollbar = Scrollbar(base, command=ChatLog.yview, cursor="heart") 59 | ChatLog['yscrollcommand'] = scrollbar.set 60 | 61 | #Create the Button to send message 62 | SendButton = Button(base, font=30, text="Send", width="12", height=5, 63 | bd=0, bg="#FFBF00", activebackground="#FACC2E", 64 | command=ClickAction) 65 | 66 | #Create the box to enter message 67 | EntryBox = Text(base, bd=0, bg="white",width="29", height="5", font="Arial") 68 | EntryBox.bind("", DisableEntry) 69 | EntryBox.bind("", PressAction) 70 | 71 | #Place all components on the screen 72 | scrollbar.place(x=376,y=6, height=386) 73 | ChatLog.place(x=6,y=6, height=386, width=370) 74 | EntryBox.place(x=128, y=401, height=90, width=265) 75 | SendButton.place(x=6, y=401, height=90) 76 | 77 | 78 | #---------------------------------------------------# 79 | #----------------CONNECTION MANAGEMENT--------------# 80 | #---------------------------------------------------# 81 | 82 | def ReceiveData(): 83 | try: 84 | s.connect((HOST, PORT)) 85 | LoadConnectionInfo(ChatLog, '[ Succesfully connected ]\n---------------------------------------------------------------') 86 | except: 87 | LoadConnectionInfo(ChatLog, '[ Unable to connect ]') 88 | return 89 | 90 | while 1: 91 | try: 92 | data = s.recv(1024) 93 | except: 94 | LoadConnectionInfo(ChatLog, '\n [ Your partner has disconnected ] \n') 95 | break 96 | if data != '': 97 | LoadOtherEntry(ChatLog, data) 98 | if base.focus_get() == None: 99 | FlashMyWindow(WindowTitle) 100 | playsound('notif.wav') 101 | 102 | else: 103 | LoadConnectionInfo(ChatLog, '\n [ Your partner has disconnected ] \n') 104 | break 105 | #s.close() 106 | 107 | thread.start_new_thread(ReceiveData,()) 108 | 109 | base.mainloop() 110 | 111 | 112 | -------------------------------------------------------------------------------- /host.pyw: -------------------------------------------------------------------------------- 1 | import thread 2 | from ChatFns import * 3 | 4 | 5 | 6 | #---------------------------------------------------# 7 | #---------INITIALIZE CONNECTION VARIABLES-----------# 8 | #---------------------------------------------------# 9 | #Initiate socket and bind port to host PC 10 | WindowTitle = 'JChat v0.1 - Host' 11 | s = socket(AF_INET, SOCK_STREAM) 12 | HOST = gethostname() 13 | PORT = 8011 14 | conn = '' 15 | s.bind((HOST, PORT)) 16 | 17 | 18 | 19 | #---------------------------------------------------# 20 | #------------------ MOUSE EVENTS -------------------# 21 | #---------------------------------------------------# 22 | def ClickAction(): 23 | #Write message to chat window 24 | EntryText = FilteredMessage(EntryBox.get("0.0",END)) 25 | LoadMyEntry(ChatLog, EntryText) 26 | 27 | #Scroll to the bottom of chat windows 28 | ChatLog.yview(END) 29 | 30 | #Erace previous message in Entry Box 31 | EntryBox.delete("0.0",END) 32 | 33 | #Send my mesage to all others 34 | conn.sendall(EntryText) 35 | 36 | 37 | 38 | 39 | 40 | #---------------------------------------------------# 41 | #----------------- KEYBOARD EVENTS -----------------# 42 | #---------------------------------------------------# 43 | def PressAction(event): 44 | EntryBox.config(state=NORMAL) 45 | ClickAction() 46 | def DisableEntry(event): 47 | EntryBox.config(state=DISABLED) 48 | 49 | 50 | 51 | 52 | #---------------------------------------------------# 53 | #-----------------GRAPHICS MANAGEMENT---------------# 54 | #---------------------------------------------------# 55 | 56 | #Create a window 57 | base = Tk() 58 | base.title(WindowTitle) 59 | base.geometry("400x500") 60 | base.resizable(width=FALSE, height=FALSE) 61 | 62 | #Create a Chat window 63 | ChatLog = Text(base, bd=0, bg="white", height="8", width="50", font="Arial",) 64 | ChatLog.insert(END, "Waiting for your partner to connect..\n") 65 | ChatLog.config(state=DISABLED) 66 | 67 | #Bind a scrollbar to the Chat window 68 | scrollbar = Scrollbar(base, command=ChatLog.yview, cursor="heart") 69 | ChatLog['yscrollcommand'] = scrollbar.set 70 | 71 | #Create the Button to send message 72 | SendButton = Button(base, font=30, text="Send", width="12", height=5, 73 | bd=0, bg="#FFBF00", activebackground="#FACC2E", 74 | command=ClickAction) 75 | 76 | #Create the box to enter message 77 | EntryBox = Text(base, bd=0, bg="white",width="29", height="5", font="Arial") 78 | EntryBox.bind("", DisableEntry) 79 | EntryBox.bind("", PressAction) 80 | 81 | #Place all components on the screen 82 | scrollbar.place(x=376,y=6, height=386) 83 | ChatLog.place(x=6,y=6, height=386, width=370) 84 | EntryBox.place(x=128, y=401, height=90, width=265) 85 | SendButton.place(x=6, y=401, height=90) 86 | 87 | 88 | 89 | #---------------------------------------------------# 90 | #----------------CONNECTION MANAGEMENT--------------# 91 | #---------------------------------------------------# 92 | def GetConnected(): 93 | s.listen(1) 94 | global conn 95 | conn, addr = s.accept() 96 | LoadConnectionInfo(ChatLog, 'Connected with: ' + str(addr) + '\n---------------------------------------------------------------') 97 | 98 | while 1: 99 | try: 100 | data = conn.recv(1024) 101 | LoadOtherEntry(ChatLog, data) 102 | if base.focus_get() == None: 103 | FlashMyWindow(WindowTitle) 104 | playsound('notif.wav') 105 | except: 106 | LoadConnectionInfo(ChatLog, '\n [ Your partner has disconnected ]\n [ Waiting for him to connect..] \n ') 107 | GetConnected() 108 | 109 | conn.close() 110 | 111 | thread.start_new_thread(GetConnected,()) 112 | 113 | 114 | 115 | base.mainloop() 116 | 117 | 118 | -------------------------------------------------------------------------------- /notif.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JackZProduction/python_chat/5fb4b2827840928b0facea644a7b203adc6b91da/notif.wav --------------------------------------------------------------------------------