import os import irc3 from stat import S_ISFIFO #################################################################################################### @irc3.plugin class Fifo: BLOCK_SIZE = 1024 MAX_BUFFER_SIZE = 800 ################################################################################################ def __init__(self, context): self.context = context self.config = self.context.config self.send_blank_line = self.config.get('send_blank_line', True) self.runpath = self.config.get('runpath', '/home/dr1p/Documents/code/python/krylon/fifo') if not os.path.exists(self.runpath): os.makedirs(self.runpath) self.loop = self.context.loop self.fifos = {} self.buffers = {} self.context.duffer=[] self.create_fifo(None) ################################################################################################ @classmethod def read_fd(cls, fd): while True: try: return os.read(fd, cls.BLOCK_SIZE) except InterruptedError: continue except BlockingIOError: return b"" ################################################################################################ def handle_line(self, line, channel): if not line: return line = line.decode("utf8") if not self.send_blank_line and not line.strip(): return if channel is None: self.context.send_line(line) else: self.context.duffer.append(line) print('+++ fifo line input received +++') ################################################################################################ def data_received(self, data, channel): if not data: return prev = self.buffers.get(channel, b"") lines = (prev + data).splitlines(True) last = lines[-1] for line in lines[:-1]: line = line.rstrip(b'\r\n') self.handle_line(line, channel) if last.endswith(b'\n'): line = last.rstrip(b'\r\n') self.handle_line(line, channel) self.buffers[channel] = b"" return if len(last) > self.MAX_BUFFER_SIZE: self.handle_line(last, channel) self.buffers[channel] = b"" else: self.buffers[channel] = last ################################################################################################ def watch_fd(self, fd, channel): reading = True while reading: data = self.read_fd(fd) reading = len(data) == self.BLOCK_SIZE self.data_received(data, channel) ################################################################################################ def create_fifo(self, channel): if channel is None: path = os.path.join(self.runpath, ':raw') else: path = os.path.join(self.runpath, channel.strip('#&+')) try: mode = os.stat(path).st_mode except OSError: pass else: if not S_ISFIFO(mode): self.context.log.warn( 'file %s created without mkfifo. remove it', path) os.remove(path) if not os.path.exists(path): os.mkfifo(path) fd = os.open(path, os.O_RDWR | os.O_NONBLOCK) self.loop.add_reader(fd, self.watch_fd, fd, channel) self.context.log.debug("%s's fifo is %s %r", channel or ':raw', path, fd) return fd @irc3.event(irc3.rfc.JOIN) ################################################################################################ def join(self, mask=None, channel=None, **kwargs): if mask.nick == self.context.nick: if channel not in self.fifos: self.fifos[channel] = self.create_fifo(channel) ################################################################################################