forked from swanson/py-irc-client
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpy-irc
511 lines (462 loc) · 24.3 KB
/
py-irc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
#!/usr/bin/env python3
from tkinter import *
from tkinter import messagebox,ttk
from tkinter.scrolledtext import ScrolledText
from socket import socket
from select import select
import sys,threading,random,time,ssl,configparser,hashlib
class Window(Frame):
def __init__(self, master):
Frame.__init__(self,master)
self.root=master
self.sckt=socket()
self.parser=configparser.ConfigParser()
self.parser.read('settings.ini')
self.grid()
self.tabs={}
self.init_window()
self.getuser_popup()
def getuser_popup(self):# UI for username entry window
self.checkSSL=IntVar()
self.checkSSL.set(0)
self.top=Toplevel()
self.top.transient(root)
w=740
h=540
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.SERVERIP=Entry(self.top,width=70)
self.SERVERIP.place(x=75,y=10)
self.SERVERIP.insert(0,'irc.freenode.net')
self.SERVERLB=Label(self.top,text='IP')
self.SERVERLB.place(x=5,y=10)
self.enterUser=Entry(self.top,width=70)
self.enterUser.place(x=75,y=42)
self.enterUser.focus_force()
self.enterUsername=Label(self.top,text='Nickname')
self.enterUsername.place(x=5,y=42)
self.enterIDENT=Entry(self.top,width=70)
self.enterIDENT.place(x=75,y=74)
self.enterIDENTLb=Label(self.top,text='Identity')
self.enterIDENTLb.place(x=5,y=74)
self.enterREALNAME=Entry(self.top,width=70)
self.enterREALNAME.place(x=75,y=106)
self.enterREALNAMELb=Label(self.top,text='Realname')
self.enterREALNAMELb.place(x=5,y=106)
self.enterPASSWORD=Entry(self.top,show='*',width=70)
self.enterPASSWORD.place(x=75,y=138)
self.enterPASSWORDLb=Label(self.top,text='Password')
self.enterPASSWORDLb.place(x=5,y=138)
self.autoJoin=Entry(self.top,width=77)
self.autoJoin.place(x=10,y=192)
self.autoJoinLb=Label(self.top,text='Auto join channels seperated by ,')
self.autoJoinLb.place(x=5,y=170)
self.sslCHECKBOX=Checkbutton(self.top,variable=self.checkSSL,onvalue=1,offvalue=0,text='SSL')
self.sslCHECKBOX.place(x=5,y=230)
self.sslCHECKBOX.select()
self.usernameButton=Button(self.top,text='Connect',command=self.get_username,height=10,width=38)
self.usernameButton.bind('<Return>',self.get_username)
self.usernameButton.place(x=190, y=290)
if self.parser.has_section('usersettings'):
self.enterUser.insert(0,self.parser.get('UserSettings','nickname'))
self.enterIDENT.insert(0,self.parser.get('UserSettings','identity'))
self.enterREALNAME.insert(0,self.parser.get('UserSettings','realname'))
if self.parser.has_section('AutoJoin'):
self.autoJoin.insert(0,self.parser.get('AutoJoin','channels'))
def init_window(self):#UI for main window
self.n=ttk.Notebook(root)
self.n.enable_traversal()
root.title('IRC Chat')
w=740
h=540
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=30,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=0.005,width=47,wrap=WORD)
self.textEntry.grid(row=2,column=0,padx=(10,0),pady=(0,1),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='Server Info')
self.n.grid(row=0,column=0,sticky=N+S+E+W)
def get_username(self,event=None):#get initial username after hitting enter chat button
self.aliasName=self.enterUser.get()
self.IDENT=self.enterIDENT.get()
self.REALNAME=self.enterREALNAME.get()
self.SERVER=self.SERVERIP.get()
password=self.enterPASSWORD.get()
self.Channels=self.autoJoin.get()
if self.aliasName=='':
messagebox.showinfo(message='You must enter a username',icon='warning')
elif ' 'in self.aliasName:
messagebox.showinfo(message='Username cannot have spaces',icon='warning')
elif not password and self.checkSSL.get()==1:
self.sckt=ssl.wrap_socket(self.sckt)
self.PORT=6697
self.start_recv_loop()
elif password and self.checkSSL.get()==1:
self.sckt=ssl.wrap_socket(self.sckt)
self.PORT=6697
self.start_recv_loop()
self.sckt.send(bytes('PRIVMSG NickServ : IDENTIFY %s\r\n'%password,"UTF-8"))
else:
self.PORT=6667
self.start_recv_loop()
self.user_settings()
def start_recv_loop(self):
self.top.destroy()
self.master.title('Py-IRC-Chat - %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)>0 and message[0]=='/':
self.process_commands(message)
else:
self.post_pm_controls(f'[{self.aliasName}]{message}\n', textboxinc)#post received text to window
self.sckt.send(bytes("PRIVMSG %s %s \r\n"%(tab,':%s'%message),'UTF-8'))
return 'break'
def process_commands(self,message):
format=message.split(' ')
if '/msg' in format:
type='pm'
message=" ".join(format[2:])
tab_name=format[1].lower()
if len(message)<1:
messagebox.showinfo(message='You must enter text after /msg username',icon='warning')
else:
self.add_tab(tab_name,type)
self.tabs[tab_name]['entrybox'].delete('1.0',END)
self.find_window(tab_name,f'[{self.aliasName}]{message}\n')
self.sckt.send(bytes("PRIVMSG %s %s \r\n"%(tab_name, ':%s'%message),"UTF-8"))
elif '/sjoin'in message:
random.seed(round(time.time()/43200))
if random.randint(0,99)<50:
channel_hash=str(hashlib.sha256((format[2].lower()+str(random.random())).encode('utf-8')).hexdigest())
else:
channel_hash=str(hashlib.sha512((format[2].lower()+str(random.random())).encode('utf-8')).hexdigest())
l=len(channel_hash)
while l>30:
channel_hash=channel_hash[:l-1]
l=len(channel_hash)
tab_name='#'+channel_hash
type='channel'
self.add_tab(tab_name,type)
elif '/join'in message:
tab_name=format[1].lower()
type='channel'
self.add_tab(tab_name,type)
n=1
b=0
while b<1:
try:
tab_name=format[n].lower()
self.add_tab(tab_name,type)
except Exception:
b+=1
continue
n+=1
elif '/leave'in message:
self.leave_channel()
elif '/nick'in message:
self.name_change(self.aliasName,message)
elif '/exit'in message:
self.shutdownClient()
elif '/quit'in message:
self.shutdownClient()
else:
messagebox.showinfo(message='Command not found.',icon='warning')
def recv_loop(self,connection): #main loop for incoming messages
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):#look through incoming messages for server info
try:
if line[0]=='PING':#reply PING from server with PONG
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': #look for names
self.build_online_list(line)
elif line[1]=='401': #warns if user/channel doesn't exist
messagebox.showinfo(message='No such user/channel %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:]) #grabs everything after 3rd index and joining the message.
format_user1=line[0].strip(':')
finish_format=format_user1.split('!')
user=finish_format[0]
self.find_window(line[2].lower(),f'*{user} {x}\n') #[ost received text to window
elif line[1]=='PRIVMSG': #if PRIVMSG in line[1] position; message from channel or private message
self.get_incoming_channel(line)
elif line[1]=='JOIN'and self.aliasName not in line[0]:#if JOIN is line[1], new user join channel
self.get_join_leave_name(line)
elif line[1]=='PART'and self.aliasName not in line[0]: #if PART is line[1] a user has left; update online user list
self.get_join_leave_name(line)
elif line[1]=='NICK'and self.aliasName not in line[2]: #if NICK is line[1] a user has changed username; update online user list
self.get_join_leave_name(line)
elif line[1]=='NOTICE'and line[2] == self.aliasName: #if line[1] is NOTICE and line[2] is the users name grab message
get_tab=line[3].split('[')
get_tab_finish=get_tab[1].split(']')
x=' '.join(line[4:]) #grabs everything after 3rd index and join the message.
self.find_window(get_tab_finish[0].lower(),'%s\n'%x)
elif line[1]=='328'or line[1]=='332'or line[1]=='333'or line[1]=='366': #grabs server messages on join. If tab name is in line[3], grab message
x=' '.join(line[3:]) #grabbing everything after the 3rd index and join the message.
self.find_window(line[3].lower(),'%s\n'%x)
elif':'in line[0]: #grabs all messages from server and posts to main tab
x=' '.join(line[3:]) #grabs everything after 1st index and join the message.
self.post_pm_controls('%s\n'%x, self.tabs['Server Info']['textbox'])
else: #grabs names coming through as a seperate list, rebuilds it, and runs it back to be reiterated
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: #if no data in indexes of the incoming messages
pass
def get_incoming_channel(self,line):
if'#'in line[2]: #message from channel
channel='' #get incoming sender
incomg_msg=line[0].split('!') #split the message at [!]
channel+=incomg_msg[0].lstrip(':') # Strip [:] out
x=' '.join(line[3:]) #grabs everything after 3rd index and join message.
self.find_window(line[2].lower(),f'[{channel}]{x.lstrip(":")}\n') #post received text to window
else: #private message from user
type='pm'
message=line[3].lstrip(':')
x=' '.join(line[4:]) #grabs everything after 3rd index and joins message.
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(),f'[{user}]{message} {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): #tab generator for creating channels/pms
#create channel tab
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] Online')
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='Close tab',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): #get active tab and close on click
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): #gets name of the tab so message gets to correct tab
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') #if incoming user in current tabs change the state of tab to normal if hidden
self.post_pm_controls(message,self.tabs[tab_name]['textbox'])#post received text to window
def name_change(self,user,line): #handles name change if a user changes their name.
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((f'*You are now known as {new_user}\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(f'*User {user} is now known as {new_user[1]}\n',incbox)
def get_join_leave_name(self,line): #gets name of user if they join, leave, or change name
tab=line[2].split(':') #format the incoming name, remove ':', and get channel
user=''#temp storage for incoming sender name
incomg_msg=line[0].split('!') #split at the '!'
user+=incomg_msg[0].lstrip(":")#remove ':' from string
if(line[1]=='JOIN'): #check if message is someone joining
self.add_online_user(user,tab[1])
elif(line[1]=='PART'): #check if message is someone leaving
self.remove_online_user(user,tab[0])
elif(line[1]=='NICK'): #check if message is someone changing their name
self.name_change(user,line)
def add_online_user(self,user,tab): #adds users as they join
inctab=self.tabs[tab]['textbox'] #tells which tab to update
self.tabs[tab]['onlineusers'].insert(END,user) #add new user to online user Listbox
self.post_pm_controls(f'*User {user} has joined the channel\n',inctab) # Post a message to the window that a user had joined
def remove_online_user(self,user,tab): #remove users when leaving active channel
inctab=self.tabs[tab.lower()] #tells which tab to update
try:
index=inctab['onlineusers'].get(0,'end').index(user)
inctab['onlineusers'].delete(index) #remove the user from the onlinelist and display those left
self.post_pm_controls(f'User {user} has left the channel\n',inctab['textbox'])
except ValueError: #if user is not in dictionary list, post those present
self.post_pm_controls(f'*User {user} has left the channel\n',inctab['textbox'])
try:
index1=inctab['onlineusers'].get(0,'end').index('@%s'%user) #get index if user is admin
inctab['onlineusers'].delete(index1)
self.post_pm_controls(f'*User {user} has left the channel\n',inctab['textbox'])
except ValueError: #if the user is not in dictionary list, post those present
pass
def remove_on_quit(self,line): #remove users as they quit active channel
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(f'*User {user} has quit. Reason: {x}\n',incbox)
def leave_channel(self): #called on /leave from user. Leaves current tab
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):#builds online users list
try:
if self.tabs[line[4].lower()]['onlineusers']=='': #if no users in channel/users dictionary, pass
pass
else:
users=[]#temp storage for incoming names
first_user=line[5].replace(':','') #formats first username in the list
users.append(first_user) #add user to temp list
for items in line[6:]: #get rest of incoming names and add them to dictionaries users list
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): #counts online users.
user_count=self.tabs[tab_name]['onlineusers'].size()
self.tabs[tab_name]['onlineusers'].delete(0)
self.tabs[tab_name]['onlineusers'].insert(0,f'{user_count-1} Online')
def post_pm_controls(self,pm,window): #handles state of the tabed text boxes as well as inserting text into the box
window.config(state=NORMAL)
window.insert(END,time.strftime('[%I:%M %p]')+pm)
window.config(state=DISABLED)
window.see(END)
def shutdownClient(self): #/exit from the user.
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')
def user_settings(self):
if not self.parser.has_section("UserSettings"):
self.parser.add_section('UserSettings')
self.parser.set('UserSettings','NickName',self.aliasName)
self.parser.set('UserSettings','Identity',self.IDENT)
self.parser.set('UserSettings','RealName',self.REALNAME)
if not self.parser.has_section('AutoJoin'):
self.parser.add_section('AutoJoin')
self.parser.set('AutoJoin','Channels',self.Channels)
with open("settings.ini","w") as config:
self.parser.write(config)
if __name__ == '__main__':
root=Tk()
app=Window(root)
root.mainloop()