Attonement for massacring this library (wip)

This commit is contained in:
Dpeta 2022-03-17 03:14:46 +00:00
parent 959a9c5ad3
commit e6ad257479
4 changed files with 64 additions and 97 deletions

View file

@ -24,27 +24,18 @@ PchumLog = logging.getLogger('pchumLogger')
import logging import logging
import socket import socket
import sys import sys
#import re
#import string
import time import time
#import threading
import os import os
import traceback import traceback
import ostools import ostools
import ssl import ssl
import json
_datadir = ostools.getDataDir() _datadir = ostools.getDataDir()
from oyoyo.parse import * from oyoyo.parse import *
from oyoyo import helpers from oyoyo import helpers
from oyoyo.cmdhandler import CommandError from oyoyo.cmdhandler import CommandError
# Python < 3 compatibility
if sys.version_info < (3,):
class bytes(object):
def __new__(self, b='', encoding='utf8'):
return str(b)
class IRCClientError(Exception): class IRCClientError(Exception):
pass pass
@ -92,26 +83,17 @@ class IRCClient:
""" """
# This should be moved to profiles # This should be moved to profiles
import json
try: with open(_datadir + "server.json", "r") as server_file:
with open(_datadir + "server.json", "r") as server_file: read_file = server_file.read()
read_file = server_file.read() server_file.close()
server_file.close() server_obj = json.loads(read_file)
server_obj = json.loads(read_file) TLS = server_obj['TLS']
TLS = server_obj['TLS'] #print("TLS-status is: " + str(TLS))
#print("TLS-status is: " + str(TLS)) if TLS == False:
if TLS == False: #print("false")
#print("false") self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) else:
else:
self.context = ssl.create_default_context()
self.context.check_hostname = False
self.context.verify_mode = ssl.CERT_NONE
self.bare_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket = self.context.wrap_socket(self.bare_socket)
except:
logging.exception('')
self.context = ssl.create_default_context() self.context = ssl.create_default_context()
self.context.check_hostname = False self.context.check_hostname = False
self.context.verify_mode = ssl.CERT_NONE self.context.verify_mode = ssl.CERT_NONE
@ -160,10 +142,11 @@ class IRCClient:
% repr([(type(arg), arg) for arg in args])) % repr([(type(arg), arg) for arg in args]))
msg = bytes(" ", "UTF-8").join(bargs) msg = bytes(" ", "UTF-8").join(bargs)
logging.info('---> send "%s"' % msg) PchumLog.info('---> send "%s"' % msg)
try: try:
self.socket.send(msg + bytes("\r\n", "UTF-8")) self.socket.sendall(msg + bytes("\r\n", "UTF-8"))
except socket.error as se: except socket.error as se:
PchumLog.debug("socket.error %s" % se)
try: # a little dance of compatibility to get the errno try: # a little dance of compatibility to get the errno
errno = se.errno errno = se.errno
except AttributeError: except AttributeError:
@ -177,7 +160,7 @@ class IRCClient:
""" initiates the connection to the server set in self.host:self.port """ initiates the connection to the server set in self.host:self.port
""" """
logging.info('connecting to %s:%s' % (self.host, self.port)) PchumLog.info('connecting to %s:%s' % (self.host, self.port))
self.socket.connect(("%s" % self.host, self.port)) self.socket.connect(("%s" % self.host, self.port))
if not self.blocking: if not self.blocking:
self.socket.setblocking(0) self.socket.setblocking(0)
@ -196,15 +179,16 @@ class IRCClient:
while not self._end: while not self._end:
try: try:
buffer += self.socket.recv(1024) buffer += self.socket.recv(1024)
#raise socket.timeout
except socket.timeout as e: except socket.timeout as e:
if self._end: if self._end:
break break
logging.debug("timeout in client.py") PchumLog.debug("timeout in client.py")
raise e raise e
except socket.error as e: except socket.error as e:
if self._end: if self._end:
break break
logging.debug("error %s" % e) PchumLog.debug("error %s" % e)
try: # a little dance of compatibility to get the errno try: # a little dance of compatibility to get the errno
errno = e.errno errno = e.errno
except AttributeError: except AttributeError:
@ -228,48 +212,43 @@ class IRCClient:
prefix, command, args = parse_raw_irc_command(el) prefix, command, args = parse_raw_irc_command(el)
try: try:
self.command_handler.run(command, prefix, *args) self.command_handler.run(command, prefix, *args)
except CommandError: except CommandError as e:
# error will have already been loggingged by the handler PchumLog.debug("CommandError %s" % e)
pass
yield True yield True
except socket.timeout as se: except socket.timeout as se:
logging.debug("passing timeout") PchumLog.debug("passing timeout")
raise se raise se
except socket.error as se: except socket.error as se:
logging.debug("problem: %s" % (se)) PchumLog.debug("problem: %s" % (se))
if self.socket: if self.socket:
logging.info('error: closing socket') PchumLog.info('error: closing socket')
self.socket.close() self.socket.close()
raise se raise se
except Exception as e: except Exception as e:
logging.debug("other exception: %s" % e) PchumLog.debug("other exception: %s" % e)
raise e raise e
else: else:
logging.debug("ending while, end is %s" % self._end) PchumLog.debug("ending while, end is %s" % self._end)
if self.socket: if self.socket:
logging.info('finished: closing socket') PchumLog.info('finished: closing socket')
self.socket.close() self.socket.close()
yield False yield False
def close(self): def close(self):
# with extreme prejudice # with extreme prejudice
if self.socket: if self.socket:
logging.info('shutdown socket') PchumLog.info('shutdown socket')
#print("shutdown socket") #print("shutdown socket")
self._end = True self._end = True
self.socket.shutdown(socket.SHUT_WR) self.socket.shutdown(socket.SHUT_WR)
self.socket.close() self.socket.close()
def simple_send(self, message): def simple_send(self, message):
self.socket.send(bytes(message, "UTF-8")) self.socket.sendall(bytes(message, "UTF-8"))
def quit(self, msg): def quit(self, msg):
# I am going mad :) PchumLog.info("QUIT")
# Why does this only work 33% of the time </3 self.socket.sendall(bytes(msg + "\n", "UTF-8"))
# Somehow, kinda fixed :')
logging.info("QUIT")
self.socket.send(bytes(msg + "\n", "UTF-8"))
class IRCApp: class IRCApp:
""" This class manages several IRCClient instances without the use of threads. """ This class manages several IRCClient instances without the use of threads.
@ -296,7 +275,7 @@ class IRCApp:
warning: if you add a client that has blocking set to true, warning: if you add a client that has blocking set to true,
timers will no longer function properly """ timers will no longer function properly """
logging.info('added client %s (ar=%s)' % (client, autoreconnect)) PchumLog.info('added client %s (ar=%s)' % (client, autoreconnect))
self._clients[client] = self._ClientDesc(autoreconnect=autoreconnect) self._clients[client] = self._ClientDesc(autoreconnect=autoreconnect)
def addTimer(self, seconds, cb): def addTimer(self, seconds, cb):
@ -305,7 +284,7 @@ class IRCApp:
( the only advantage to these timers is they dont use threads ) ( the only advantage to these timers is they dont use threads )
""" """
assert callable(cb) assert callable(cb)
logging.info('added timer to call %s in %ss' % (cb, seconds)) PchumLog.info('added timer to call %s in %ss' % (cb, seconds))
self._timers.append((time.time() + seconds, cb)) self._timers.append((time.time() + seconds, cb))
def run(self): def run(self):
@ -322,8 +301,8 @@ class IRCApp:
try: try:
next(clientdesc.con) next(clientdesc.con)
except Exception as e: except Exception as e:
logging.error('client error %s' % e) PchumLog.error('client error %s' % e)
logging.error(traceback.format_exc()) PchumLog.error(traceback.format_exc())
if clientdesc.autoreconnect: if clientdesc.autoreconnect:
clientdesc.con = None clientdesc.con = None
if isinstance(clientdesc.autoreconnect, (int, float)): if isinstance(clientdesc.autoreconnect, (int, float)):
@ -335,7 +314,7 @@ class IRCApp:
found_one_alive = True found_one_alive = True
if not found_one_alive: if not found_one_alive:
logging.info('nothing left alive... quiting') PchumLog.info('nothing left alive... quiting')
self.stop() self.stop()
now = time.time() now = time.time()
@ -343,7 +322,7 @@ class IRCApp:
self._timers = [] self._timers = []
for target_time, cb in timers: for target_time, cb in timers:
if now > target_time: if now > target_time:
logging.info('calling timer cb %s' % cb) PchumLog.info('calling timer cb %s' % cb)
cb() cb()
else: else:
self._timers.append((target_time, cb)) self._timers.append((target_time, cb))

View file

@ -28,13 +28,6 @@ import traceback
from oyoyo import helpers from oyoyo import helpers
from oyoyo.parse import parse_nick from oyoyo.parse import parse_nick
# Python < 3 compatibility
if sys.version_info < (3,):
class bytes(object):
def __new__(self, b='', encoding='utf8'):
return str(b)
def protected(func): def protected(func):
""" decorator to protect functions from being called """ """ decorator to protect functions from being called """
func.protected = True func.protected = True
@ -62,6 +55,7 @@ class CommandHandler(object):
@protected @protected
def get(self, in_command_parts): def get(self, in_command_parts):
PchumLog.debug("in_command_parts: %s" % in_command_parts)
""" finds a command """ finds a command
commands may be dotted. each command part is checked that it does commands may be dotted. each command part is checked that it does
not start with and underscore and does not have an attribute not start with and underscore and does not have an attribute
@ -97,7 +91,10 @@ class CommandHandler(object):
@protected @protected
def run(self, command, *args): def run(self, command, *args):
""" finds and runs a command """ """ finds and runs a command """
logging.debug("processCommand %s(%s)" % (command, args)) arguments_str = ''
for x in args:
arguments_str += str(x) + ' '
PchumLog.debug("processCommand %s(%s)" % (command, arguments_str.strip()))
try: try:
f = self.get(command) f = self.get(command)
@ -105,30 +102,30 @@ class CommandHandler(object):
self.__unhandled__(command, *args) self.__unhandled__(command, *args)
return return
logging.debug('f %s' % f) PchumLog.debug('f %s' % f)
#logging.info(*args) #logging.info(*args)
# Because more than 5 arguments can be passed by channelmodeis # Because more than 5 arguments can be passed by channelmodeis
try: #try:
#if str(command) == 'channelmodeis': #if str(command) == 'channelmodeis':
# This might be stupid :) # This might be stupid :)
# Update: This was very stupid # Update: This was very stupid
#f(*args[0:4]) #f(*args[0:4])
#else: #else:
f(*args) f(*args)
except Exception as e: #except Exception as e:
#logging.error('command raised '+ command + str()) # #logging.error('command raised '+ command + str())
logging.error('command args: ' + str([*args])) # PchumLog.error('command args: ' + str([*args]))
logging.error('command raised %s' % e) # PchumLog.error('command raised %s' % e)
logging.error(traceback.format_exc()) # PchumLog.error(traceback.format_exc())
raise CommandError(command) # raise CommandError(command)
@protected @protected
def __unhandled__(self, cmd, *args): def __unhandled__(self, cmd, *args):
"""The default handler for commands. Override this method to """The default handler for commands. Override this method to
apply custom behavior (example, printing) unhandled commands. apply custom behavior (example, printing) unhandled commands.
""" """
logging.debug('unhandled command %s(%s)' % (cmd, args)) PchumLog.debug('unhandled command %s(%s)' % (cmd, args))
class DefaultCommandHandler(CommandHandler): class DefaultCommandHandler(CommandHandler):
@ -155,7 +152,7 @@ class DefaultBotCommandHandler(CommandHandler):
def help(self, sender, dest, arg=None): def help(self, sender, dest, arg=None):
"""list all available commands or get help on a specific command""" """list all available commands or get help on a specific command"""
logging.info('help sender=%s dest=%s arg=%s' % (sender, dest, arg)) PchumLog.info('help sender=%s dest=%s arg=%s' % (sender, dest, arg))
if not arg: if not arg:
commands = self.getVisibleCommands() commands = self.getVisibleCommands()
commands.sort() commands.sort()

View file

@ -15,18 +15,16 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. # THE SOFTWARE.
import logging import logging, logging.config
import ostools
_datadir = ostools.getDataDir()
logging.config.fileConfig(_datadir + "logging.ini")
PchumLog = logging.getLogger('pchumLogger')
import sys import sys
from oyoyo.ircevents import * from oyoyo.ircevents import *
# Python < 3 compatibility
if sys.version_info < (3,):
class bytes(object):
def __new__(self, b='', encoding='utf8'):
return str(b)
def parse_raw_irc_command(element): def parse_raw_irc_command(element):
""" """
This function parses a raw irc command and returns a tuple This function parses a raw irc command and returns a tuple
@ -46,14 +44,12 @@ def parse_raw_irc_command(element):
<crlf> ::= CR LF <crlf> ::= CR LF
""" """
try: try:
element = element.decode("utf-8") element = element.decode("utf-8")
except: except UnicodeDecodeError as e:
try: PchumLog.debug("utf-8 error %s" % e)
element = element.decode("latin-1") element = element.decode("latin-1", 'replace')
except:
# This shouldn't happen, but if it does:
element = ""
parts = element.strip().split(" ") parts = element.strip().split(" ")
if parts[0].startswith(':'): if parts[0].startswith(':'):
@ -69,7 +65,7 @@ def parse_raw_irc_command(element):
try: try:
command = numeric_events[command] command = numeric_events[command]
except KeyError: except KeyError:
logging.info('unknown numeric event %s' % command) PchumLog.info('unknown numeric event %s' % command)
command = command.lower() command = command.lower()
if args[0].startswith(':'): if args[0].startswith(':'):

7
pesterchum.py Normal file → Executable file
View file

@ -185,15 +185,10 @@ PchumLog = logging.getLogger('pchumLogger')
try: try:
import console import console
_CONSOLE = True
except ImportError: except ImportError:
_CONSOLE = False _CONSOLE = False
logging.warning("Console file not shipped; skipping.") logging.warning("Console file not shipped; skipping.")
except Exception as err:
_CONSOLE = False
# Consider erroring?
logging.error("Failed to load console!", exc_info=err)
else:
_CONSOLE = True
if _datadir: if _datadir:
if not os.path.exists(_datadir): if not os.path.exists(_datadir):