mirror of
https://github.com/weechat/weechat.git
synced 2026-06-28 22:06:38 +02:00
weercd.py: major code cleanup, full PEP8 compliance, replace %-formatting with .format()
All changes:
- import the new division operator and the print function
- replace the %-formatting with .format()
- full PEP8 compliance
- major code cleanup: new function send_cmd() to send an IRC command,
split flood() function into many functions.
The messages sent from a file (or stdin) are formatted with
".format(self=self)", so that attributes from class Client are replaced
with their values. You can use for example these attributes:
{self.nick} current client nick
{self.name} the server name ('weercd')
{self.version} the server version (version of weercd.py)
This commit is contained in:
+285
-189
@@ -35,8 +35,8 @@
|
||||
# - for WeeChat, another home with: `weechat --dir /tmp/weechat`
|
||||
# - on a test machine, because CPU will be used a lot by client to display
|
||||
# messages from weercd
|
||||
# - if possible locally (ie server and client on same machine), to speed up data
|
||||
# exchange between server and client.
|
||||
# - if possible locally (ie server and client on same machine), to speed up
|
||||
# data exchange between server and client.
|
||||
#
|
||||
# Instructions to use this server with WeeChat:
|
||||
# 1. open a terminal and run server:
|
||||
@@ -52,6 +52,8 @@
|
||||
# Yeah, it's stable \o/
|
||||
#
|
||||
|
||||
from __future__ import division, print_function
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import random
|
||||
@@ -62,16 +64,19 @@ import socket
|
||||
import string
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
NAME = 'weercd'
|
||||
VERSION = '0.7'
|
||||
DESCRIPTION = 'The WeeChat IRC testing server.'
|
||||
VERSION = '0.8'
|
||||
|
||||
|
||||
class Client:
|
||||
|
||||
def __init__(self, sock, addr, args, **kwargs):
|
||||
self.sock, self.addr = sock, addr
|
||||
self.args = args
|
||||
self.name = NAME
|
||||
self.version = VERSION
|
||||
self.nick = ''
|
||||
self.nicknumber = 0
|
||||
self.channels = {}
|
||||
@@ -80,40 +85,95 @@ class Client:
|
||||
self.quit, self.endmsg, self.endexcept = False, '', None
|
||||
self.starttime = time.time()
|
||||
self.connect()
|
||||
if not self.quit:
|
||||
if self.args.file:
|
||||
self.send_from_file()
|
||||
else:
|
||||
self.flood()
|
||||
|
||||
def strrand(self, minlength=1, maxlength=50, spaces=False):
|
||||
"""Return string with random length and content."""
|
||||
def run(self):
|
||||
"""Execute the action asked for the client."""
|
||||
if self.quit:
|
||||
return
|
||||
|
||||
# send commands from file (which can be stdin)
|
||||
if self.args.file:
|
||||
self.send_file()
|
||||
return
|
||||
|
||||
# flood the client
|
||||
if self.args.wait > 0:
|
||||
print('Waiting', self.args.wait, 'seconds')
|
||||
time.sleep(self.args.wait)
|
||||
sys.stdout.write('Flooding client..')
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
while not self.quit:
|
||||
self.flood()
|
||||
except Exception as e:
|
||||
if self.quit:
|
||||
self.endmsg = 'quit received'
|
||||
else:
|
||||
self.endmsg = 'connection lost'
|
||||
self.endexcept = e
|
||||
except KeyboardInterrupt:
|
||||
self.endmsg = 'interrupted'
|
||||
else:
|
||||
self.endmsg = 'quit received'
|
||||
|
||||
def fuzzy_str(self, minlength=1, maxlength=50, spaces=False):
|
||||
"""Return a fuzzy string (random length and content)."""
|
||||
length = random.randint(minlength, maxlength)
|
||||
strspace = ''
|
||||
if spaces:
|
||||
strspace = ' '
|
||||
return ''.join(random.choice(string.ascii_uppercase +
|
||||
string.ascii_lowercase +
|
||||
string.digits + strspace) for x in range(length))
|
||||
string.digits + strspace)
|
||||
for x in range(length))
|
||||
|
||||
def fuzzy_host(self):
|
||||
"""Return a fuzzy host name."""
|
||||
return '{0}@{1}'.format(self.fuzzy_str(1, 10), self.fuzzy_str(1, 10))
|
||||
|
||||
def fuzzy_nick(self, with_number=False):
|
||||
"""Return a fuzzy nick name."""
|
||||
if with_number:
|
||||
self.nicknumber += 1
|
||||
return '{0}{1}'.format(self.fuzzy_str(1, 5), self.nicknumber)
|
||||
else:
|
||||
return self.fuzzy_str(1, 10)
|
||||
|
||||
def fuzzy_chan(self):
|
||||
"""Return a fuzzy channel name."""
|
||||
return '#{0}'.format(self.fuzzy_str(1, 25))
|
||||
|
||||
def send(self, data):
|
||||
"""Send one message to client."""
|
||||
if self.args.debug:
|
||||
print('<-- %s' % data)
|
||||
msg = '%s\r\n' % data
|
||||
print('<--', data)
|
||||
msg = data + '\r\n'
|
||||
self.outbytes += len(msg)
|
||||
self.sock.send(msg.encode('UTF-8'))
|
||||
self.outcount += 1
|
||||
|
||||
def send_cmd(self, cmd, data, nick='{self.name}', host='',
|
||||
target='{self.nick}'):
|
||||
"""Send an IRC command to the client."""
|
||||
self.send(':{0}{1}{2} {3}{4}{5}{6}{7}'
|
||||
''.format(nick,
|
||||
'!' if host else '',
|
||||
host,
|
||||
cmd,
|
||||
' ' if target else '',
|
||||
target,
|
||||
' :' if data else '',
|
||||
data).format(self=self))
|
||||
|
||||
def recv(self, data):
|
||||
"""Read one message from client."""
|
||||
"""Read one IRC message from client."""
|
||||
if self.args.debug:
|
||||
print('--> %s' % data)
|
||||
print('-->', data)
|
||||
if data.startswith('PING '):
|
||||
args = data[5:]
|
||||
if args[0] == ':':
|
||||
args = args[1:]
|
||||
self.send('PONG :%s' % args)
|
||||
self.send('PONG :{0}'.format(args))
|
||||
elif data.startswith('NICK '):
|
||||
self.nick = data[5:]
|
||||
elif data.startswith('PART '):
|
||||
@@ -127,7 +187,7 @@ class Client:
|
||||
self.incount += 1
|
||||
|
||||
def read(self, timeout):
|
||||
"""Read data from client."""
|
||||
"""Read raw data received from client."""
|
||||
inr, outr, exceptr = select.select([self.sock], [], [], timeout)
|
||||
if inr:
|
||||
data = self.sock.recv(4096)
|
||||
@@ -144,167 +204,177 @@ class Client:
|
||||
self.lastbuf = data
|
||||
|
||||
def connect(self):
|
||||
"""Tell client that connection is ok."""
|
||||
"""Inform the client that the connection is OK."""
|
||||
try:
|
||||
count = self.args.nickused
|
||||
while self.nick == '':
|
||||
self.read(0.1)
|
||||
if self.nick and count > 0:
|
||||
self.send(':%s 433 * %s :Nickname is already in use.' % (NAME, self.nick))
|
||||
self.send_cmd('433', 'Nickname is already in use.',
|
||||
target='* {self.nick}')
|
||||
self.nick = ''
|
||||
count -= 1
|
||||
self.send(':%s 001 %s :Welcome to the WeeChat IRC server' % (NAME, self.nick))
|
||||
self.send(':%s 002 %s :Your host is %s, running version %s' % (NAME, self.nick, NAME, VERSION))
|
||||
self.send(':%s 003 %s :Are you solid like a rock?' % (NAME, self.nick))
|
||||
self.send(':%s 004 %s :Let\'s see!' % (NAME, self.nick))
|
||||
self.send_cmd('001', 'Welcome to the WeeChat IRC server')
|
||||
self.send_cmd('002', 'Your host is {self.name}, running version '
|
||||
'{self.version}')
|
||||
self.send_cmd('003', 'Are you solid like a rock?')
|
||||
self.send_cmd('004', 'Let\'s see!')
|
||||
except KeyboardInterrupt:
|
||||
self.quit = True
|
||||
self.endmsg = 'interrupted'
|
||||
return
|
||||
|
||||
def chan_randnick(self, channel):
|
||||
def channel_random_nick(self, channel):
|
||||
"""Return a random nick of a channel."""
|
||||
if len(self.channels[channel]) < 2:
|
||||
return None
|
||||
rnick = self.nick
|
||||
while rnick == self.nick:
|
||||
rnick = self.channels[channel][random.randint(0, len(self.channels[channel]) - 1)]
|
||||
rnick = self.channels[channel][
|
||||
random.randint(0, len(self.channels[channel]) - 1)]
|
||||
return rnick
|
||||
|
||||
def flood(self):
|
||||
"""Yay, funny stuff here! Flood client!"""
|
||||
if self.args.wait > 0:
|
||||
print('Wait %f seconds' % self.args.wait)
|
||||
time.sleep(self.args.wait)
|
||||
sys.stdout.write('Flooding client..')
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
while not self.quit:
|
||||
self.read(self.args.sleep)
|
||||
# global actions
|
||||
action = random.randint(1, 2)
|
||||
if action == 1:
|
||||
# join
|
||||
if len(self.channels) < self.args.maxchans:
|
||||
channel = '#%s' % self.strrand(1, 25)
|
||||
if not channel in self.channels:
|
||||
self.send(':%s!%s JOIN :%s' % (self.nick, self.addr[0], channel))
|
||||
self.send(':%s 353 %s = %s :@%s' % (NAME, self.nick, channel, self.nick))
|
||||
self.send(':%s 366 %s %s :End of /NAMES list.' % (NAME, self.nick, channel))
|
||||
self.channels[channel] = [self.nick]
|
||||
elif action == 2 and 'user' in self.args.notice:
|
||||
# notice for user
|
||||
self.send(':%s!%s@%s NOTICE %s :%s' % (self.strrand(1, 10), self.strrand(1, 10),
|
||||
self.strrand(1, 10), self.nick,
|
||||
self.strrand(1, 400, True)))
|
||||
# actions for each channel
|
||||
for channel in self.channels:
|
||||
action = random.randint(1, 50)
|
||||
if action >= 1 and action <= 10:
|
||||
# join
|
||||
if len(self.channels[channel]) < self.args.maxnicks:
|
||||
self.nicknumber += 1
|
||||
newnick = '%s%d' % (self.strrand(1, 5), self.nicknumber)
|
||||
self.send(':%s!%s@%s JOIN :%s' % (newnick, self.strrand(1, 10),
|
||||
self.strrand(1, 10), channel))
|
||||
self.channels[channel].append(newnick)
|
||||
elif action == 11:
|
||||
# part/quit
|
||||
if len(self.channels[channel]) > 0:
|
||||
rnick = self.chan_randnick(channel)
|
||||
if rnick:
|
||||
command = 'QUIT :%s' % self.strrand(1, 30)
|
||||
if random.randint(1, 2) == 1:
|
||||
command = 'PART %s' % channel
|
||||
self.send(':%s!%s@%s %s' % (rnick, self.strrand(1, 10),
|
||||
self.strrand(1, 10), command))
|
||||
self.channels[channel].remove(rnick)
|
||||
elif action == 12:
|
||||
# kick
|
||||
if len(self.channels[channel]) > 0:
|
||||
rnick1 = self.chan_randnick(channel)
|
||||
rnick2 = self.chan_randnick(channel)
|
||||
if rnick1 and rnick2 and rnick1 != rnick2:
|
||||
self.send(':%s!%s@%s KICK %s %s :%s' % (rnick1, self.strrand(1, 10),
|
||||
self.strrand(1, 10), channel, rnick2,
|
||||
self.strrand(1, 50)))
|
||||
self.channels[channel].remove(rnick2)
|
||||
else:
|
||||
# message
|
||||
if len(self.channels[channel]) > 0:
|
||||
rnick = self.chan_randnick(channel)
|
||||
if rnick:
|
||||
msg = self.strrand(1, 400, True)
|
||||
if 'channel' in self.args.notice and random.randint(1, 100) == 100:
|
||||
# notice for channel
|
||||
self.send(':%s!%s@%s NOTICE %s :%s' % (rnick, self.strrand(1, 10),
|
||||
self.strrand(1, 10), channel, msg))
|
||||
else:
|
||||
# add random highlight
|
||||
if random.randint(1, 100) == 100:
|
||||
msg = '%s: %s' % (self.nick, msg)
|
||||
action2 = random.randint(1, 50)
|
||||
if action2 == 1:
|
||||
# action (/me)
|
||||
msg = '\x01ACTION %s\x01' % msg
|
||||
elif action2 == 2:
|
||||
# version
|
||||
msg = '\x01VERSION\x01'
|
||||
self.send(':%s!%s@%s PRIVMSG %s :%s' % (rnick, self.strrand(1, 10),
|
||||
self.strrand(1, 10), channel, msg))
|
||||
# display progress
|
||||
if self.outcount % 1000 == 0:
|
||||
sys.stdout.write('.')
|
||||
sys.stdout.flush()
|
||||
except Exception as e:
|
||||
if self.quit:
|
||||
self.endmsg = 'quit received'
|
||||
else:
|
||||
self.endmsg = 'connection lost'
|
||||
self.endexcept = e
|
||||
return
|
||||
except KeyboardInterrupt:
|
||||
self.endmsg = 'interrupted'
|
||||
return
|
||||
else:
|
||||
self.endmsg = 'quit received'
|
||||
def flood_self_join(self):
|
||||
"""Self join on a new channel."""
|
||||
channel = self.fuzzy_chan()
|
||||
if channel in self.channels:
|
||||
return
|
||||
self.send_cmd('JOIN', channel,
|
||||
nick=self.nick, host=self.addr[0], target='')
|
||||
self.send_cmd('353', '@{self.nick}',
|
||||
target='{0} = {1}'.format(self.nick, channel))
|
||||
self.send_cmd('366', 'End of /NAMES list.',
|
||||
target='{0} {1}'.format(self.nick, channel))
|
||||
self.channels[channel] = [self.nick]
|
||||
|
||||
def send_from_file(self):
|
||||
def flood_user_notice(self):
|
||||
"""Notice for the user."""
|
||||
self.send_cmd('NOTICE', self.fuzzy_str(1, 400, spaces=True),
|
||||
nick=self.fuzzy_nick(), host=self.fuzzy_host())
|
||||
|
||||
def flood_channel_join(self, channel):
|
||||
"""Join of a user in a channel."""
|
||||
if len(self.channels[channel]) >= self.args.maxnicks:
|
||||
return
|
||||
newnick = self.fuzzy_nick(with_number=True)
|
||||
self.send_cmd('JOIN', channel,
|
||||
nick=newnick, host=self.fuzzy_host(), target='')
|
||||
self.channels[channel].append(newnick)
|
||||
|
||||
def flood_channel_part(self, channel):
|
||||
"""Part or quit of a user in a channel."""
|
||||
if len(self.channels[channel]) == 0:
|
||||
return
|
||||
rnick = self.channel_random_nick(channel)
|
||||
if not rnick:
|
||||
return
|
||||
if random.randint(1, 2) == 1:
|
||||
self.send_cmd('PART', channel,
|
||||
nick=rnick, host=self.fuzzy_host(), target='')
|
||||
else:
|
||||
self.send_cmd('QUIT', self.fuzzy_str(1, 30),
|
||||
nick=rnick, host=self.fuzzy_host(), target='')
|
||||
self.channels[channel].remove(rnick)
|
||||
|
||||
def flood_channel_kick(self, channel):
|
||||
"""Kick of a user in a channel."""
|
||||
if len(self.channels[channel]) == 0:
|
||||
return
|
||||
rnick1 = self.channel_random_nick(channel)
|
||||
rnick2 = self.channel_random_nick(channel)
|
||||
if rnick1 and rnick2 and rnick1 != rnick2:
|
||||
self.send_cmd('KICK', self.fuzzy_str(1, 50),
|
||||
nick=rnick1, host=self.fuzzy_host(),
|
||||
target='{0} {1}'.format(channel, rnick2))
|
||||
self.channels[channel].remove(rnick2)
|
||||
|
||||
def flood_channel_message(self, channel):
|
||||
"""Message from a user in a channel."""
|
||||
if len(self.channels[channel]) == 0:
|
||||
return
|
||||
rnick = self.channel_random_nick(channel)
|
||||
if not rnick:
|
||||
return
|
||||
msg = self.fuzzy_str(1, 400, spaces=True)
|
||||
if 'channel' in self.args.notice and random.randint(1, 100) == 100:
|
||||
# notice for channel
|
||||
self.send_cmd('NOTICE', msg,
|
||||
nick=rnick, host=self.fuzzy_host(), target=channel)
|
||||
else:
|
||||
# add random highlight
|
||||
if random.randint(1, 100) == 100:
|
||||
msg = '{0}: {1}'.format(self.nick, msg)
|
||||
action2 = random.randint(1, 50)
|
||||
if action2 == 1:
|
||||
# CTCP action (/me)
|
||||
msg = '\x01ACTION {0}\x01'.format(msg)
|
||||
elif action2 == 2:
|
||||
# CTCP version
|
||||
msg = '\x01VERSION\x01'
|
||||
self.send_cmd('PRIVMSG', msg,
|
||||
nick=rnick, host=self.fuzzy_host(), target=channel)
|
||||
|
||||
def flood(self):
|
||||
"""Yay, funny stuff here! Flood the client!"""
|
||||
self.read(self.args.sleep)
|
||||
# global actions
|
||||
action = random.randint(1, 2)
|
||||
if action == 1 and len(self.channels) < self.args.maxchans:
|
||||
self.flood_self_join()
|
||||
elif action == 2 and 'user' in self.args.notice:
|
||||
self.flood_user_notice()
|
||||
# actions for each channel
|
||||
for channel in self.channels:
|
||||
action = random.randint(1, 50)
|
||||
if 1 <= action <= 10:
|
||||
self.flood_channel_join(channel)
|
||||
elif action == 11:
|
||||
self.flood_channel_part(channel)
|
||||
elif action == 12:
|
||||
self.flood_channel_kick(channel)
|
||||
else:
|
||||
self.flood_channel_message(channel)
|
||||
# display progress
|
||||
if self.outcount % 1000 == 0:
|
||||
sys.stdout.write('.')
|
||||
sys.stdout.flush()
|
||||
|
||||
def send_file(self):
|
||||
"""Send messages from a file to client."""
|
||||
stdin = self.args.file == sys.stdin
|
||||
count = 0
|
||||
self.read(0.2)
|
||||
try:
|
||||
while True:
|
||||
# display the prompt if we are reading in stdin
|
||||
if stdin:
|
||||
sys.stdout.write('Message to send to client: ')
|
||||
sys.stdout.flush()
|
||||
message = self.args.file.readline()
|
||||
if not message:
|
||||
break
|
||||
message = message.rstrip('\n')
|
||||
if sys.version_info < (3,):
|
||||
message = message.decode('UTF-8')
|
||||
if not message.startswith('//'):
|
||||
if not stdin:
|
||||
# sleep, only if commands come from a file
|
||||
self.read(self.args.sleep)
|
||||
self.send(message.replace('${nick}', self.nick))
|
||||
message = message.rstrip('\n')
|
||||
if message and not message.startswith('//'):
|
||||
self.send(message.format(self=self))
|
||||
count += 1
|
||||
self.read(0.1 if stdin else self.args.sleep)
|
||||
except IOError as e:
|
||||
self.endmsg = 'unable to read file %s' % self.args.file
|
||||
self.endmsg = 'unable to read file {0}'.format(self.args.file)
|
||||
self.endexcept = e
|
||||
return
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
self.endmsg = 'connection lost'
|
||||
self.endexcept = e
|
||||
return
|
||||
except KeyboardInterrupt:
|
||||
self.endmsg = 'interrupted'
|
||||
return
|
||||
finally:
|
||||
sys.stdout.write('\n')
|
||||
sys.stdout.write('%d messages sent from %s, press Enter to exit'
|
||||
% (count, 'stdin' if stdin else 'file'))
|
||||
sys.stdout.write('{0} messages sent from {1}, press Enter to exit'
|
||||
.format(count, 'stdin' if stdin else 'file'))
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
sys.stdin.readline()
|
||||
@@ -312,70 +382,96 @@ class Client:
|
||||
pass
|
||||
|
||||
def stats(self):
|
||||
"""Display some statistics about data exchanged with the client."""
|
||||
msgexcept = ''
|
||||
if self.endexcept:
|
||||
msgexcept = '(%s)' % self.endexcept
|
||||
print(' %s %s' % (self.endmsg, msgexcept))
|
||||
msgexcept = '({0})'.format(self.endexcept)
|
||||
print(self.endmsg, msgexcept)
|
||||
elapsed = time.time() - self.starttime
|
||||
print('Elapsed: %.1fs - packets: in:%d, out:%d (%d/s) - bytes: in:%d, out: %d (%d/s)' % (
|
||||
elapsed, self.incount, self.outcount, self.outcount / elapsed,
|
||||
self.inbytes, self.outbytes, self.outbytes / elapsed))
|
||||
countrate = self.outcount / elapsed
|
||||
bytesrate = self.outbytes / elapsed
|
||||
print('Elapsed: {elapsed:.1f}s - '
|
||||
'packets: in:{self.incount}, out:{self.outcount} '
|
||||
'({countrate:.0f}/s) - '
|
||||
'bytes: in:{self.inbytes}, out: {self.outbytes} '
|
||||
'({bytesrate:.0f}/s)'
|
||||
''.format(self=self,
|
||||
elapsed=elapsed,
|
||||
countrate=countrate,
|
||||
bytesrate=bytesrate))
|
||||
if self.endmsg == 'connection lost':
|
||||
print('Uh-oh! No quit received, client has crashed? Ahah \o/')
|
||||
|
||||
def __del__(self):
|
||||
self.stats()
|
||||
print('Closing connection with %s' % str(self.addr))
|
||||
print('Closing connection with', self.addr)
|
||||
self.sock.close()
|
||||
|
||||
# parse command line arguments
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
fromfile_prefix_chars='@',
|
||||
description=DESCRIPTION,
|
||||
epilog='Note: the environment variable "WEERCD_OPTIONS" can be '
|
||||
'set with some default options, and argument "@file.txt" can be '
|
||||
'used to read some default options in a file.')
|
||||
parser.add_argument('-H', '--host', help='host for socket bind')
|
||||
parser.add_argument('-p', '--port', type=int, default=7777, help='port for socket bind')
|
||||
parser.add_argument('-f', '--file', type=argparse.FileType('r'),
|
||||
help='send messages from file, instead of flooding the client (use "-" for stdin)')
|
||||
parser.add_argument('-c', '--maxchans', type=int, default=5, help='max number of channels to join')
|
||||
parser.add_argument('-n', '--maxnicks', type=int, default=100, help='max number of nicks per channel')
|
||||
parser.add_argument('-u', '--nickused', type=int, default=0,
|
||||
help='send 433 (nickname already in use) this number of times before accepting nick')
|
||||
parser.add_argument('-N', '--notice', metavar='NOTICE_TYPE', choices=['user', 'channel'],
|
||||
default=['user', 'channel'], nargs='*',
|
||||
help='notices to send: "user" (to user), "channel" (to channel)')
|
||||
parser.add_argument('-s', '--sleep', type=float, default=0,
|
||||
help='sleep for select: delay between 2 messages sent to client (float, in seconds)')
|
||||
parser.add_argument('-w', '--wait', type=float, default=0,
|
||||
help='time to wait before flooding client (float, in seconds)')
|
||||
parser.add_argument('-d', '--debug', action='store_true', help='debug output')
|
||||
parser.add_argument('-v', '--version', action='version', version=VERSION)
|
||||
args = parser.parse_args(shlex.split(os.getenv('WEERCD_OPTIONS') or '') + sys.argv[1:])
|
||||
if __name__ == "__main__":
|
||||
# parse command line arguments
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
fromfile_prefix_chars='@',
|
||||
description='The WeeChat IRC testing server.',
|
||||
epilog='Note: the environment variable "WEERCD_OPTIONS" can be '
|
||||
'set with default options. Argument "@file.txt" can be used to read '
|
||||
'default options in a file.')
|
||||
parser.add_argument('-H', '--host', help='host for socket bind')
|
||||
parser.add_argument('-p', '--port', type=int, default=7777,
|
||||
help='port for socket bind')
|
||||
parser.add_argument('-f', '--file', type=argparse.FileType('r'),
|
||||
help='send messages from file, instead of flooding '
|
||||
'the client (use "-" for stdin)')
|
||||
parser.add_argument('-c', '--maxchans', type=int, default=5,
|
||||
help='max number of channels to join')
|
||||
parser.add_argument('-n', '--maxnicks', type=int, default=100,
|
||||
help='max number of nicks per channel')
|
||||
parser.add_argument('-u', '--nickused', type=int, default=0,
|
||||
help='send 433 (nickname already in use) this number '
|
||||
'of times before accepting nick')
|
||||
parser.add_argument('-N', '--notice', metavar='NOTICE_TYPE',
|
||||
choices=['user', 'channel'],
|
||||
default=['user', 'channel'], nargs='*',
|
||||
help='notices to send: "user" (to user), "channel" '
|
||||
'(to channel)')
|
||||
parser.add_argument('-s', '--sleep', type=float, default=0,
|
||||
help='sleep for select: delay between 2 messages sent '
|
||||
'to client (float, in seconds)')
|
||||
parser.add_argument('-w', '--wait', type=float, default=0,
|
||||
help='time to wait before flooding client (float, '
|
||||
'in seconds)')
|
||||
parser.add_argument('-d', '--debug', action='store_true',
|
||||
help='debug output')
|
||||
parser.add_argument('-v', '--version', action='version', version=VERSION)
|
||||
args = parser.parse_args(shlex.split(os.getenv('WEERCD_OPTIONS') or '') +
|
||||
sys.argv[1:])
|
||||
|
||||
print('%s %s - WeeChat IRC testing server' % (NAME, VERSION))
|
||||
print('Options: %s' % vars(args))
|
||||
# welcome message, with options
|
||||
print(NAME, VERSION, '- WeeChat IRC testing server')
|
||||
print('Options:', vars(args))
|
||||
|
||||
while True:
|
||||
servsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
servsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
servsock.bind((args.host or '', args.port))
|
||||
servsock.listen(1)
|
||||
except Exception as e:
|
||||
print('Socket error: %s' % e)
|
||||
sys.exit(1)
|
||||
print('Listening on port %s (ctrl-C to exit)' % args.port)
|
||||
clientsock = None
|
||||
addr = None
|
||||
try:
|
||||
clientsock, addr = servsock.accept()
|
||||
except KeyboardInterrupt:
|
||||
servsock.close()
|
||||
sys.exit(0)
|
||||
print('Connection from %s' % str(addr))
|
||||
client = Client(clientsock, addr, args)
|
||||
del client
|
||||
if args.file:
|
||||
break
|
||||
# main loop
|
||||
while True:
|
||||
servsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
servsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
servsock.bind((args.host or '', args.port))
|
||||
servsock.listen(1)
|
||||
except Exception as e:
|
||||
print('Socket error: {0}'.format(e))
|
||||
sys.exit(1)
|
||||
print('Listening on port', args.port, '(ctrl-C to exit)')
|
||||
clientsock = None
|
||||
addr = None
|
||||
try:
|
||||
clientsock, addr = servsock.accept()
|
||||
except KeyboardInterrupt:
|
||||
servsock.close()
|
||||
sys.exit(0)
|
||||
print('Connection from', addr)
|
||||
client = Client(clientsock, addr, args)
|
||||
client.run()
|
||||
del client
|
||||
# no loop if message were sent from a file
|
||||
if args.file:
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user