3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-23 19:19:31 +01:00

Irc: implement basic message queueing (1 message sent per X seconds)

Ref #293.
This commit is contained in:
James Lu 2016-08-21 16:46:57 -07:00
parent 583e4c65c8
commit 7a5b64bdc9

View File

@ -16,7 +16,7 @@ import hashlib
from copy import deepcopy from copy import deepcopy
import inspect import inspect
import re import re
from collections import defaultdict from collections import defaultdict, deque
try: try:
import ircmatch import ircmatch
@ -54,6 +54,8 @@ class Irc():
self.pingfreq = self.serverdata.get('pingfreq') or 90 self.pingfreq = self.serverdata.get('pingfreq') or 90
self.pingtimeout = self.pingfreq * 2 self.pingtimeout = self.pingfreq * 2
self.queue = deque()
self.connected = threading.Event() self.connected = threading.Event()
self.aborted = threading.Event() self.aborted = threading.Event()
@ -108,6 +110,8 @@ class Irc():
self.pseudoclient = None self.pseudoclient = None
self.lastping = time.time() self.lastping = time.time()
self.queue.clear()
# Internal variable to set the place and caller of the last command (in PM # Internal variable to set the place and caller of the last command (in PM
# or in a channel), used by fantasy command support. # or in a channel), used by fantasy command support.
self.called_by = None self.called_by = None
@ -162,6 +166,14 @@ class Irc():
# Set up channel logging for the network # Set up channel logging for the network
self.logSetup() self.logSetup()
def processQueue(self):
"""Loop to process outgoing queue data."""
while not self.aborted.is_set():
if self.queue: # Only process if there's data.
data = self.queue.popleft()
self._send(data)
time.sleep(0.01)
def connect(self): def connect(self):
""" """
Runs the connect loop for the IRC object. This is usually called by Runs the connect loop for the IRC object. This is usually called by
@ -270,6 +282,11 @@ class Irc():
hashtype, fp) hashtype, fp)
if checks_ok: if checks_ok:
self.queue_thread = threading.Thread(name="Queue thread for %s" % self.name,
target=self.processQueue, daemon=True)
self.queue_thread.start()
self.sid = self.serverdata.get("sid") self.sid = self.serverdata.get("sid")
# All our checks passed, get the protocol module to connect and run the listen # All our checks passed, get the protocol module to connect and run the listen
# loop. This also updates any SID values should the protocol module do so. # loop. This also updates any SID values should the protocol module do so.
@ -431,7 +448,7 @@ class Irc():
hook_args) hook_args)
continue continue
def send(self, data): def _send(self, data):
"""Sends raw text to the uplink server.""" """Sends raw text to the uplink server."""
# Safeguard against newlines in input!! Otherwise, each line gets # Safeguard against newlines in input!! Otherwise, each line gets
# treated as a separate command, which is particularly nasty. # treated as a separate command, which is particularly nasty.
@ -439,11 +456,20 @@ class Irc():
data = data.encode("utf-8") + b"\n" data = data.encode("utf-8") + b"\n"
stripped_data = data.decode("utf-8").strip("\n") stripped_data = data.decode("utf-8").strip("\n")
log.debug("(%s) -> %s", self.name, stripped_data) log.debug("(%s) -> %s", self.name, stripped_data)
try: try:
self.socket.send(data) self.socket.send(data)
except (OSError, AttributeError): except (OSError, AttributeError):
log.debug("(%s) Dropping message %r; network isn't connected!", self.name, stripped_data) log.debug("(%s) Dropping message %r; network isn't connected!", self.name, stripped_data)
def send(self, data, queue=True):
"""send() wrapper with optional queueing support."""
if queue:
self.queue.append(data)
else:
self._send(data)
def schedulePing(self): def schedulePing(self):
"""Schedules periodic pings in a loop.""" """Schedules periodic pings in a loop."""
self.proto.ping() self.proto.ping()