-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserverparser.py
143 lines (127 loc) · 5.96 KB
/
serverparser.py
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
# Copyright Beatrice Tohni 2021
""" This file is part of wiggleVerse.
wiggleVerse is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
wiggleVerse is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with wiggleVerse. If not, see <https://www.gnu.org/licenses/>."""
import re
import logging
class ServerParser:
def __init__(self, nick, set_nick_callback):
"""We supress certain response codes for readability:
004: Server mode strings
005: Server capability report
317: User away time in /whois TODO: format this sometime
323: End of /LIST
333: Topic setter/time
366: End of /NAMES list
376: End of /MOTD command
"""
self.supress_codes = ['004', '005', '317', '323', '333', '376']
self.replace_msgs = {
'375': '***SERVER MESSAGE OF THE DAY***',
'321': '***CHANNEL LISTING***',
'331': '<<No topic set>>',
'433': 'Nickname taken. Pick another one with /nick <newnick>'
}
self.whois_codes = ['311', '319', '312', '313', '671', '318']
self.nick = nick
self.set_nick_callback = set_nick_callback
def get_nick(self, host):
nick_format = re.compile(':[\w\-_\[\]^|\\`{}]*!') # Allowable chars: A-Z a-z 0-9 & -_[]{}\^|`
match = nick_format.match(host)
if match:
nick = match.group()
nick = nick[1:len(nick)-1] # remove : and !
return nick
else:
return False
def parse_message(self, message):
# First try to parse numerically coded messages
split_message = message.split(' ')
if len(split_message) < 3:
return message
code_format = re.compile('\d\d\d')
if code_format.match(split_message[1]):
numeric_code = split_message[1]
message_body = ' '.join(split_message[3:])
if message_body[0] == ':':
message_body = message_body[1:] # Remove extra colons
if numeric_code in self.replace_msgs:
message_body = self.replace_msgs[numeric_code]
elif numeric_code == '001': # update nick on registration
self.set_nick_callback(split_message[2])
elif numeric_code == '372': # MOTD body
message_body = message_body[2:] # Remove '- '
elif numeric_code == '353': # /names list
nick_list = ' '.join(split_message[5:])
message_body = f'Users in {split_message[4]}: {nick_list[1:]}'
elif numeric_code == '332': # /topic reply
channel = split_message[3]
topic = ' '.join(split_message[4:])
topic = topic[1:]
message_body = f'Topic for {channel}: {topic}'
elif self.whois_codes.count(numeric_code) == 1: #/whois reply
info = ' '.join(split_message[4:])
message_body = f'[iNFO] {info}'
elif self.supress_codes.count(numeric_code) == 1: # Supress some cruft
return ''
# message = f'** {numeric_code}: {message_body}' # for debugging
message = f'** {message_body}'
elif split_message[1] == 'NOTICE': # Registered notice
notice = ' '.join(split_message[4:])
message = f'** NOTICE: {notice}'
elif split_message[0] == 'NOTICE': # AUTH notice
notice = ' '.join(split_message[3:])
message = f'** NOTICE: {notice}'
elif split_message[1] == 'JOIN': # JOIN messages
nick = self.get_nick(split_message[0])
if nick:
channel = split_message[2]
message = f'** {nick} has joined {channel[1:]}'
elif split_message[1] == 'PRIVMSG': # chat messages
nick = self.get_nick(split_message[0])
logging.debug(f'nick is {nick}')
if nick:
channel = split_message[2]
message = ' '.join(split_message[3:])
logging.debug(f'{message}')
if channel == self.nick:
message = f'-{nick}- <{nick}> {message[1:]}'
else:
message = f'-{channel}- <{nick}> {message[1:]}'
elif split_message[1] == 'PART': # PART messages
nick = self.get_nick(split_message[0])
if nick:
channel = split_message[2]
try:
message = split_message[3]
message = ': ' + message[1:]
except IndexError:
message = ''
message = f'** {nick} has left {channel}{message}'
elif split_message[1] == 'MODE': # chat messages
nick = self.get_nick(split_message[0])
if nick:
target = split_message[2]
mode = ' '.join(split_message[3:])
message = f'** {nick} has set {mode} on {target}'
elif split_message[1] == 'NICK': # nick changes
nick = self.get_nick(split_message[0])
if nick:
new_nick = split_message[2]
if nick == self.nick: # Our user is changing nickname
self.nick = new_nick[1:]
self.set_nick_callback(new_nick[1:])
message = f'** You have changed nick to {new_nick[1:]}'
else: # other user changing nick
message = f'** {nick} changed nick to {new_nick[1:]}'
else:
logging.debug(f'other msg: {message}')
return message