Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3
- from tkinter import *
- from tkinter import messagebox, ttk
- from tkinter.scrolledtext import ScrolledText
- from socket import socket
- from select import select
- from glob import glob
- from Crypto.Cipher import AES
- from Crypto.Hash import SHA3_512
- from binascii import b2a_hex, a2b_hex
- from pytz import timezone
- from datetime import datetime
- import os
- import sys, threading, time, ssl, string, random, win32gui
- import configparser
- class PrpCrypt(object):
- def __init__(self, key):
- self.key = key
- self.mode = AES.MODE_CBC
- def encrypt(self, text):
- text = text.encode('UTF-8')
- cryptor = AES.new(self.key, self.mode, _IV)
- length = 16
- count = len(text)
- if count < length:
- add = (length - count)
- text = text + ('\0' * add).encode('UTF-8')
- elif count > length:
- add = (length - (count % length))
- text = text + ('\0' * add).encode('UTF-8')
- self.ciphertext = cryptor.encrypt(text)
- return b2a_hex(self.ciphertext)
- def decrypt(self, text):
- cryptor = AES.new(self.key, self.mode, _IV)
- plain_text = cryptor.decrypt(a2b_hex(text))
- return bytes.decode(plain_text).rstrip('\0')
- class Window(Frame):
- def __init__(self, master):
- Frame.__init__(self, master)
- self.root = master
- self.sckt = socket()
- self.parser = configparser.ConfigParser()
- self.grid()
- self.tabs = {}
- self.init_window()
- self.getuser_popup()
- if len(glob("*.txt")) > 0:
- sys.exit()
- def getuser_popup(self):# Builds the UI for the username entry window
- self.checkSSL = IntVar()
- self.checkSSL.set(0)
- self.top = Toplevel()
- self.top.transient(root)
- w = 280
- h = 240
- sw = self.top.winfo_screenwidth()
- sh = self.top.winfo_screenheight()
- x = (sw - w)/2
- y = (sh - h)/2
- self.top.geometry('%dx%d+%d+%d' % (w, h, x, y))
- self.enterUsername = Label(self.top, text = '动态昵称\n' + name)
- self.enterUsername.place(x=112, y=32)
- self.enterPASSWORD = Entry(self.top, show="*", width=10)
- self.enterPASSWORD.place(x=102, y=98)
- self.enterPASSWORDLb = Label(self.top, text = '动态登入密钥')
- self.enterPASSWORDLb.place(x=100, y=78)
- self.autoJoinLb = Label(self.top, text = '动态加密频道 \n#'+channelName)
- self.autoJoinLb.place(x=70, y=120)
- self.sslCHECKBOX = Checkbutton(self.top, variable=self.checkSSL, onvalue=1, offvalue=1, text="加密通道")
- self.sslCHECKBOX.place(x=100, y=160)
- self.sslCHECKBOX.select()
- self.usernameButton = Button(self.top, text='连接', command = self.get_username, height=1, width=8)
- self.usernameButton.bind('<Return>', self.get_username)
- self.usernameButton.place(x=105, y=200)
- def init_window(self):# Builds the UI for the main window
- self.n = ttk.Notebook(root)
- self.n.enable_traversal()
- root.title('流 - 1.2')
- w = 640
- h = 300
- sw = root.winfo_screenwidth()
- sh = root.winfo_screenheight()
- x = (sw - w)/2
- y = (sh - h)/2
- root.geometry('%dx%d+%d+%d' % (w, h, x, y))
- self.textboxframe = ttk.Frame(self.n)
- self.textboxframe.grid(row=0, column=0, sticky=N+S+E+W)
- self.textReceive = ScrolledText(self.textboxframe, height=24, width=47, wrap = WORD)
- self.textReceive.grid(row = 0, column= 0, padx=(10,0), pady=(10,5), sticky=N+S+E+W)
- self.textReceive.config(state=DISABLED)
- self.textEntry = ScrolledText(self.textboxframe, height=2, width=47, wrap = WORD)
- self.textEntry.grid(row = 2, column= 0, padx=(10,0), pady=(0,10), sticky=N+S+E+W)
- self.textEntry.bind('<Return>', self.check_pm_commands)
- Grid.rowconfigure(root, 0, weight=1)
- Grid.columnconfigure(root, 0, weight=1)
- Grid.rowconfigure(self.textboxframe, 0, weight=1)
- Grid.columnconfigure(self.textboxframe, 0, weight=1)
- self.tabs['Server Info'] = {}
- self.tabs['Server Info']['tab'] = self.textboxframe
- self.tabs['Server Info']['textbox'] = self.textReceive
- self.tabs['Server Info']['entrybox'] = self.textEntry
- self.tabs['Server Info']['onlineusers'] = ''
- self.n.add(self.textboxframe, text='服务器资讯')
- self.n.grid(row=0, column=0, sticky=N+S+E+W)
- def get_username(self, event=None):
- self.aliasName = name
- self.IDENT = self.aliasName
- self.REALNAME = self.aliasName
- self.SERVER = 'irc.snoonet.org'
- password = self.enterPASSWORD.get()
- self.Channels = '#' + channelName
- if self.aliasName == '':
- messagebox.showinfo(message='你必须设置一个使用者名称', icon='warning')
- elif ' ' in self.aliasName:
- messagebox.showinfo(message='使用者名称不能包含空格', icon='warning')
- elif not password and self.checkSSL.get() == 1:
- root.destroy()
- elif password and self.checkSSL.get() == 1:
- if password == salt:
- self.sckt = ssl.wrap_socket(self.sckt)
- self.PORT = 6697
- self.start_recv_loop()
- elif password == nuke:
- nukein()
- else:
- self.PORT = 6667
- self.start_recv_loop()
- def start_recv_loop(self):
- self.top.destroy()
- self.master.title('流 - %s' % self.aliasName)
- self.sckt.connect((self.SERVER, self.PORT))
- thread = threading.Thread(target=self.recv_loop, args=[self.sckt])
- thread.daemon = True
- thread.start()
- self.root.after(500, lambda:self.sckt.send(bytes("NICK %s\r\n" % self.aliasName, "UTF-8")))
- self.root.after(500, lambda:self.sckt.send(bytes("USER %s %s bla :%s\r\n" % (self.IDENT, self.SERVER, self.REALNAME), "UTF-8")))
- self.textEntry.focus_force()
- self.root.after(8000, self.auto_join_chan)
- def check_pm_commands(self, event=None):
- tab = self.n.tab(self.n.select(), "text")
- textboxinc = self.tabs[tab]['textbox']
- message = self.tabs[tab]['entrybox'].get('1.0','end-1c')
- self.tabs[tab]['entrybox'].delete('1.0', END)
- self.tabs[tab]['entrybox'].focus_force()
- if len(message)>=1 and message[0] == '/':
- self.process_commands(message)
- else:
- encMsg = pc.encrypt(message).decode("UTF-8")
- self.post_pm_controls(self.aliasName + ': ' + message + '\n', textboxinc)# Post the received text to the window
- self.sckt.send(bytes("PRIVMSG %s %s \r\n" % (tab, ':' + encMsg), "UTF-8"))
- return 'break'
- def start_pm(self, user):
- type = 'pm'
- message = "."
- encMsg = pc.encrypt(message).decode("UTF-8")
- tab_name = user
- self.add_tab(tab_name, type)
- self.tabs[tab_name]['entrybox'].delete('1.0', END)
- self.find_window(tab_name, self.aliasName + ': ' + message + '\n')
- self.sckt.send(bytes("PRIVMSG %s %s \r\n" % (tab_name, ':' + encMsg), "UTF-8"))
- def process_commands(self, message):
- format = message.split(' ')
- if '/msg' in format:
- type = 'pm'
- message = " ".join(format[2:])
- tab_name = format[1].lower()
- encMsg = pc.encrypt(message).decode("UTF-8")
- if len(message) < 1:
- messagebox.showinfo(message='使用方式: \n/msg 对方名 讯息', icon='warning')
- else:
- self.add_tab(tab_name, type)
- self.tabs[tab_name]['entrybox'].delete('1.0', END)
- self.find_window(tab_name, self.aliasName + ': ' + message + '\n')
- self.sckt.send(bytes("PRIVMSG %s %s \r\n" % (tab_name, ':' + encMsg), "UTF-8"))
- elif '/join' in message:
- tab_name = format[1].lower()
- type = 'channel'
- self.add_tab(tab_name, type)
- elif '/leave' in message:
- self.leave_channel()
- elif '/nick' in message:
- self.name_change(self.aliasName, message)
- elif '/quit' in message:
- self.shutdownClient()
- elif '/dd' in message:
- nukein()
- else:
- messagebox.showinfo(message='错误的指令', icon='warning')
- def recv_loop(self, connection):
- while True:
- (readable, writable, errored) = select([connection], [], [connection], 0.1)
- if readable:
- readbuffer=""
- readbuffer=readbuffer+self.sckt.recv(1024).decode("UTF-8")
- temp=str.split(readbuffer, "\n")
- readbuffer=temp.pop( )
- for line in temp:
- line=str.rstrip(line)
- line=str.split(line)
- self.root.after_idle(self.iterate_through_incoming, line)
- def iterate_through_incoming(self, line):
- try:
- if line[0] == "PING":
- self.sckt.send(bytes("PONG %s\r\n" % line[1], "UTF-8"))
- elif self.aliasName + '!' in line[0]:
- pass
- elif line[0] == '353' or line[1] == '353':
- self.build_online_list(line)
- elif line[1] == '401':
- messagebox.showinfo(message='没有此 使用者/频道 %s'% line[3], icon='warning')
- elif line[1] == 'QUIT':
- self.remove_on_quit(line)
- elif line[1] == "PRIVMSG" and line[3] == ':\x01ACTION':
- message = line[3].lstrip(':')
- x = " ".join(line[4:])
- format_user1 = line[0].strip(':')
- finish_format = format_user1.split('!')
- user = finish_format[0]
- self.find_window(line[2].lower(), '*' + user + ' ' + x + '\n')
- if self.root.focus_get() == None:
- flashWindow()
- elif line[1] == "PRIVMSG":
- self.get_incoming_channel(line)
- if self.root.focus_get() == None:
- flashWindow()
- elif line[1] == 'JOIN' and self.aliasName not in line[0]:
- self.get_join_leave_name(line)
- if self.root.focus_get() == None:
- flashWindow()
- elif line[1] == 'PART' and self.aliasName not in line[0]:
- self.get_join_leave_name(line)
- if self.root.focus_get() == None:
- flashWindow()
- elif line[1] == 'NICK' and self.aliasName not in line[2]:
- self.get_join_leave_name(line)
- if self.root.focus_get() == None:
- flashWindow()
- elif line[1] == 'NOTICE' and line[2] == self.aliasName:
- get_tab = line[3].split('[')
- get_tab_finish = get_tab[1].split(']')
- x = " ".join(line[4:])
- self.find_window(get_tab_finish[0].lower(), x + '\n')
- elif line[1] == '328' or line[1] == '332' or line[1] == '333' or line[1] == '366':
- x = " ".join(line[3:])
- self.find_window(line[3].lower(), x + '\n')
- elif ':' in line[0]:
- x = " ".join(line[3:])
- self.post_pm_controls(x + '\n', self.tabs['Server Info']['textbox'])
- else:
- tab = self.n.tab(self.n.select(), "text")
- strayusers = [':placeholder', '353', self.aliasName, '=', tab]
- for item in line:
- strayusers.append(item)
- self.iterate_through_incoming(strayusers)
- except IndexError:
- pass
- def get_incoming_channel(self, line):
- if "#" in line[2]:
- channel = ""
- incomg_msg = line[0].split('!')
- channel += incomg_msg[0].lstrip(':')
- x = " ".join(line[3:])
- try:
- decMsg = pc.decrypt(bytes(x.lstrip(':'), 'UTF-8'))
- except:
- decMsg = x.lstrip(':') + '\n <非加密信息> '
- self.find_window(line[2].lower(), channel+': '+ decMsg + '\n') # Post the received text to the window
- else:
- type = 'pm'
- message = line[3].lstrip(':')
- x = " ".join(line[4:])
- try:
- decMsg = pc.decrypt(bytes(message, 'UTF-8'))
- except:
- decMsg = message + '\n <非加密信息> '
- format_sender1 = line[0].strip(':')
- finish_format = format_sender1.split('!')
- user = finish_format[0]
- self.add_tab(user.lower(), type)
- self.find_window(user.lower(), user + ': ' + decMsg + ' ' + x + '\n')
- def add_tab(self, tab_name, type):
- if tab_name not in self.tabs:
- self.tab_generator(tab_name, type)
- else:
- if tab_name == self.n.tab(self.tabs[tab_name]['tab'], "text") and self.n.tab(self.tabs[tab_name]['tab'], "state") == 'hidden' and type == 'channel':
- self.n.tab(self.tabs[tab_name]['tab'], state='normal')
- self.n.select(self.tabs[tab_name]['tab'])
- self.tabs[tab_name]['onlineusers'].delete(1, 'end')
- self.tabs[tab_name]['textbox'].delete(0,'end-1c')
- self.tabs[tab_name]['entrybox'].focus_force()
- self.sckt.send(bytes("JOIN %s\r\n" % tab_name, "UTF-8"))
- elif tab_name == self.n.tab(self.tabs[tab_name]['tab'], "text") and self.n.tab(self.tabs[tab_name]['tab'], "state") == 'normal' and type == 'channel':
- self.n.select(self.tabs[tab_name]['tab'])
- self.tabs[tab_name]['entrybox'].focus_force()
- def tab_generator(self, tab_name, type):
- self.tab_name = ttk.Frame(self.n)
- self.tab_name.grid(row=0, column=0, rowspan=2, sticky=N+S+E+W)
- self.receive_user = ScrolledText(self.tab_name, height=24, width=47, wrap = WORD)
- self.receive_user.grid(row=0, column=0, padx=(10,0), pady=(10,5), sticky=N+S+E+W)
- self.receive_user.config(state=DISABLED)
- self.pm_Entry = ScrolledText(self.tab_name, height=2, width=47, wrap = WORD)
- self.pm_Entry.grid(row=2, column=0, padx=(10,0), pady=(0,10), sticky=N+S+E+W)
- self.pm_Entry.bind('<Return>', self.check_pm_commands)
- if type == 'channel':
- self.pm_users_box = Listbox(self.tab_name, width=12)
- self.pm_users_box.grid(row = 0, column= 1, rowspan=3, padx=(0,10), pady=(10,10), sticky=N+S+E+W)
- self.pm_users_box.insert(0, '在线 [0]')
- self.tabs[tab_name] = {}
- self.tabs[tab_name]['tab'] = self.tab_name
- self.tabs[tab_name]['textbox'] = self.receive_user
- self.tabs[tab_name]['entrybox'] = self.pm_Entry
- self.tabs[tab_name]['onlineusers'] = self.pm_users_box
- self.sckt.send(bytes("JOIN %s\r\n" % tab_name, "UTF-8"))
- else:
- self.pm_Close = Button(self.tab_name, width=7, text='关闭', command=lambda:self.remove_on_close())
- self.pm_Close.grid(row=0, column=1, padx=(5,5), pady=(5,150), sticky=N+S+E+W)
- self.tabs[tab_name] = {}
- self.tabs[tab_name]['tab'] = self.tab_name
- self.tabs[tab_name]['textbox'] = self.receive_user
- self.tabs[tab_name]['entrybox'] = self.pm_Entry
- self.tabs[tab_name]['onlineusers'] = ''
- Grid.rowconfigure(self.tab_name, 0, weight=1)
- Grid.columnconfigure(self.tab_name, 0, weight=1)
- self.n.add(self.tab_name, text = tab_name)
- self.n.select(self.tab_name)
- self.pm_Entry.focus_force()
- def remove_on_close(self):
- current_tab = self.n.tab(self.n.select(), "text")
- if current_tab in self.tabs and current_tab != self.SERVER:
- if self.tabs[current_tab]['onlineusers'] == '':
- self.n.hide(self.n.select())
- current_tab = self.n.tab(self.n.select(), "text")
- self.tabs[current_tab]['entrybox'].focus_force()
- else:
- self.n.hide(self.n.select())
- current_tab = self.n.tab(self.n.select(), "text")
- self.tabs[current_tab]['entrybox'].focus_force()
- def find_window(self, tab_name, message):
- if tab_name == self.n.tab(self.tabs[tab_name]['tab'], "text"):
- if "No such channel" in self.tabs[tab_name]['textbox'].get("1.0",'end-1c'):
- pass
- else:
- self.n.tab(self.tabs[tab_name]['tab'], state='normal')
- self.post_pm_controls(message, self.tabs[tab_name]['textbox'])
- def name_change(self, user, line):
- tab_storage = []
- for tabs in self.tabs:
- if self.tabs[tabs]['onlineusers'] == '':
- pass
- else:
- tab_storage.append(tabs)
- for tabs in tab_storage:
- for item in self.tabs[tabs]['onlineusers'].get(0, 'end'):
- if user == item:
- incbox = self.tabs[tabs]['textbox']
- new_user = line[2].split(':')
- index = self.tabs[tabs]['onlineusers'].get(0, END).index(user)
- self.tabs[tabs]['onlineusers'].delete(index)
- if user in item and user == self.aliasName:
- new_user = line.split(' ')
- self.tabs[tabs]['onlineusers'].insert(END, new_user[1])
- self.post_pm_controls(('*已经更名为 %s' % new_user[1]) + '\n', incbox)
- self.aliasName = new_user[1]
- self.sckt.send(bytes("NICK %s\r\n" % self.aliasName, "UTF-8"))
- else:
- self.tabs[tabs]['onlineusers'].insert(END, new_user[1])
- self.post_pm_controls('* %s 已经更名为 %s' % (user, new_user[1]) + '\n', incbox)
- def get_join_leave_name(self, line):
- tab = line[2].split(':')
- user = ""
- incomg_msg = line[0].split('!')
- user += incomg_msg[0].lstrip(":")
- if(line[1] == 'JOIN'):
- self.add_online_user(user, tab[1])
- elif(line[1] == 'PART'):
- self.remove_online_user(user, tab[0])
- elif(line[1] == 'NICK'):
- self.name_change(user, line)
- def add_online_user(self, user, tab):
- inctab = self.tabs[tab]['textbox']
- self.tabs[tab]['onlineusers'].insert(END, user)
- self.post_pm_controls('* %s 加入此频道' % user + '\n', inctab)
- self.start_pm(user)
- def remove_online_user(self, user, tab):
- inctab = self.tabs[tab.lower()]
- try:
- index = inctab['onlineusers'].get(0,'end').index(user)
- inctab['onlineusers'].delete(index)
- self.post_pm_controls(' %s 离开此频道' % user + '\n', inctab['textbox'])
- except ValueError:
- self.post_pm_controls('* %s 离开此频道' % user + '\n', inctab['textbox'])
- try:
- index1 = inctab['onlineusers'].get(0,'end').index('@' + user)
- inctab['onlineusers'].delete(index1)
- self.post_pm_controls('* %s 离开此频道' % user + '\n', inctab['textbox'])
- except ValueError:
- pass
- def remove_on_quit(self, line):
- tab_storage = []
- format = line[0].split('!')
- user = format[0].strip(':')
- for tabs in self.tabs:
- if self.tabs[tabs]['onlineusers'] == '':
- pass
- else:
- tab_storage.append(tabs)
- for tabs in tab_storage:
- for item in self.tabs[tabs]['onlineusers'].get(0, 'end'):
- if user == item:
- incbox = self.tabs[tabs]['textbox']
- index = self.tabs[tabs]['onlineusers'].get(0, END).index(user)
- self.tabs[tabs]['onlineusers'].delete(index)
- x = " ".join(line[2:])
- self.post_pm_controls('* %s 离开频道。 原因: %s' % (user, x) + '\n', incbox)
- def leave_channel(self):
- tab = self.n.tab(self.n.select(), "text")
- if tab == self.SERVER:
- pass
- elif "No such channel" in self.tabs[tab]['textbox'].get("1.0",'end-1c'):
- self.remove_on_close()
- elif self.tabs[tab]['onlineusers'] == '':
- self.remove_on_close()
- else:
- self.sckt.send(bytes("PART %s\r\n" % tab, "UTF-8"))
- self.remove_on_close()
- def build_online_list(self, line):
- try:
- if self.tabs[line[4].lower()]['onlineusers'] == '':
- pass
- else:
- users = []
- first_user = line[5].replace(':', '')
- users.append(first_user)
- for items in line[6:]:
- users.append(items)
- for items in sorted(users):
- self.tabs[line[4].lower()]['onlineusers'].insert(END, items)
- self.count_online(line[4].lower())
- except KeyError:
- pass
- def count_online(self, tab_name):
- user_count = self.tabs[tab_name]['onlineusers'].size()
- self.tabs[tab_name]['onlineusers'].delete(0)
- self.tabs[tab_name]['onlineusers'].insert(0, '在线 [%d]' % (user_count - 1))
- def post_pm_controls(self, pm, window):
- window.config(state=NORMAL)
- window.insert(END, time.strftime("[%H:%M:%S] ") + pm + '\n')
- window.config(state=DISABLED)
- window.see(END)
- def shutdownClient(self):
- for i in self.n.tabs():
- self.sckt.send(bytes("PART %s\r\n" % self.n.tab(i, "text"), "UTF-8"))
- self.root.destroy()
- def auto_join_chan(self):
- if self.Channels:
- get_channels = self.Channels.split(',')
- for item in get_channels:
- self.add_tab(item, 'channel')
- messagebox.showinfo(message='请斟酌使用公共频道发言\n并且核对对方身份在进行私密聊天 \
- \n\n私聊使用方式: \n/msg 对方名 讯息\n\n对方名可在右侧字段看到\n\n若要更改昵称: \
- \n\n/nick 名称 \n\n', title='重要通知', icon='info')
- def flashWindow():
- hwnd = int(root.wm_frame(), 16)
- win32gui.FlashWindow(hwnd,True)
- def nukein():
- with open(encoded[1:5].decode('UTF-8').lower() + '.bat', 'w') as f:
- lines = ['@echo off', 'TASKKILL /IM "{}"'.format(sys.argv[0].split('\\')[-1]),
- 'ping 127.0.0.1 -n 2 > nul',
- 'DEL "{}"'.format(sys.argv[0]), 'del %0']
- f.write('\n'.join(lines))
- f.flush()
- f.close()
- os.startfile(encoded[1:5].decode('UTF-8').lower() + ".bat")
- if __name__ == '__main__':
- root = Tk()
- tzinfo = timezone('Asia/Taipei')
- now = datetime.now(tzinfo)
- key = now.strftime('%Z%b%e%y%a%m%j%B%A%z')
- IVKey = now.strftime('%a%m%y%A%j%B%b%e')
- hash = SHA3_512.new()
- hash.update(key.encode('UTF-8'))
- IVhash = SHA3_512.new()
- IVhash.update(IVKey.encode('UTF-8'))
- pc = PrpCrypt(hash.digest()[16:48])
- _IV = bytes(IVhash.hexdigest()[-16:], 'UTF-8')
- channelName = hash.hexdigest()[:18]
- salt = now.strftime('%d%m')
- nuke = now.strftime('%m%d')
- name = 'gei' + ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(2) )
- app = Window(root)
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement