2018-01-02 19:51:32 +00:00
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
#
|
2018-01-05 16:05:58 +00:00
|
|
|
|
# IrcMiRCARTBot.py -- IRC<->MiRC2png bot (for EFnet #MiRCART)
|
2019-09-04 14:23:59 +00:00
|
|
|
|
# Copyright (c) 2018, 2019 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
|
2018-11-26 09:35:48 +00:00
|
|
|
|
# This project is licensed under the terms of the MIT licence.
|
2018-01-02 19:51:32 +00:00
|
|
|
|
#
|
|
|
|
|
|
2019-09-03 16:58:50 +00:00
|
|
|
|
import os, sys
|
|
|
|
|
[sys.path.append(os.path.join(os.getcwd(), "..", "..", path)) for path in ["libcanvas", "librtl"]]
|
|
|
|
|
|
|
|
|
|
import base64, json, requests, socket, time, urllib.request
|
2018-06-28 16:18:48 +00:00
|
|
|
|
from getopt import getopt, GetoptError
|
2019-09-03 16:58:50 +00:00
|
|
|
|
from CanvasImportStore import CanvasImportStore
|
|
|
|
|
from ImgurApiKey import ImgurApiKey
|
|
|
|
|
from IrcClient import IrcClient
|
2018-01-07 01:08:35 +00:00
|
|
|
|
from MiRCARTToPngFile import MiRCARTToPngFile
|
2018-01-02 19:51:32 +00:00
|
|
|
|
|
2019-09-03 16:58:50 +00:00
|
|
|
|
class IrcMiRCARTBot(IrcClient):
|
2018-01-05 16:05:58 +00:00
|
|
|
|
"""IRC<->MiRC2png bot"""
|
2019-09-03 16:58:50 +00:00
|
|
|
|
imgurApiKey = ImgurApiKey.imgurApiKey
|
2018-01-02 21:20:20 +00:00
|
|
|
|
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ ContentTooLargeException(Exception): Raised by _urlretrieveReportHook() given download size > 1 MB
|
2018-01-03 14:37:26 +00:00
|
|
|
|
class ContentTooLargeException(Exception):
|
|
|
|
|
pass
|
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _dispatch001(self, message): Dispatch single 001 (RPL_WELCOME)
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def _dispatch001(self, message):
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Registered on {}:{} as {}, {}, {}.".format(self.serverHname, self.serverPort, self.clientNick, self.clientIdent, self.clientGecos))
|
|
|
|
|
self._log("Attempting to join {} on {}:{}...".format(self.clientChannel, self.serverHname, self.serverPort))
|
2018-01-03 03:15:43 +00:00
|
|
|
|
self.queue("JOIN", self.clientChannel)
|
2018-01-02 22:35:01 +00:00
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _dispatch353(self, message): Dispatch single 353 (RPL_NAMREPLY)
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def _dispatch353(self, message):
|
2018-01-02 22:35:01 +00:00
|
|
|
|
if message[4].lower() == self.clientChannel.lower():
|
2018-01-02 22:39:38 +00:00
|
|
|
|
for channelNickSpec in message[5].split(" "):
|
2018-01-02 23:53:42 +00:00
|
|
|
|
if len(channelNickSpec) \
|
|
|
|
|
and channelNickSpec[0] == "@" \
|
2018-01-02 22:39:38 +00:00
|
|
|
|
and len(channelNickSpec[1:]):
|
|
|
|
|
self.clientChannelOps.append(channelNickSpec[1:].lower())
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Authorising {} on {}".format(channelNickSpec[1:].lower(), message[4].lower()))
|
2018-01-02 22:35:01 +00:00
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _dispatchJoin(self, message): Dispatch single JOIN message from server
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def _dispatchJoin(self, message):
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Joined {} on {}:{}.".format(message[2].lower(), self.serverHname, self.serverPort))
|
2018-01-03 01:16:55 +00:00
|
|
|
|
self.clientNextTimeout = None; self.clientChannelRejoin = False;
|
2018-01-02 23:40:37 +00:00
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _dispatchKick(self, message): Dispatch single KICK message from server
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def _dispatchKick(self, message):
|
2018-01-02 23:13:02 +00:00
|
|
|
|
if message[2].lower() == self.clientChannel.lower() \
|
|
|
|
|
and message[3].lower() == self.clientNick.lower():
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Kicked from {} by {}, rejoining in 15 seconds".format(message[2].lower(), message[0]))
|
2018-01-03 01:16:55 +00:00
|
|
|
|
self.clientNextTimeout = time.time() + 15; self.clientChannelRejoin = True;
|
2018-01-02 23:13:02 +00:00
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _dispatchMode(self, message): Dispatch single MODE message from server
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def _dispatchMode(self, message):
|
2018-01-02 22:35:01 +00:00
|
|
|
|
if message[2].lower() == self.clientChannel.lower():
|
|
|
|
|
channelModeType = "+"; channelModeArg = 4;
|
|
|
|
|
channelAuthAdd = ""; channelAuthDel = "";
|
|
|
|
|
for channelModeChar in message[3]:
|
|
|
|
|
if channelModeChar[0] == "-":
|
|
|
|
|
channelModeType = "-"
|
|
|
|
|
elif channelModeChar[0] == "+":
|
|
|
|
|
channelModeType = "+"
|
|
|
|
|
elif channelModeChar[0].isalpha():
|
|
|
|
|
if channelModeChar[0] == "o":
|
|
|
|
|
if channelModeType == "+":
|
|
|
|
|
channelAuthAdd = message[channelModeArg]; channelAuthDel = "";
|
|
|
|
|
elif channelModeType == "-":
|
|
|
|
|
channelAuthAdd = ""; channelAuthDel = message[channelModeArg];
|
|
|
|
|
channelModeArg += 1
|
|
|
|
|
if len(channelAuthAdd) \
|
|
|
|
|
and channelAuthAdd not in self.clientChannelOps:
|
|
|
|
|
channelAuthAdd = channelAuthAdd.lower()
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Authorising {} on {}".format(channelAuthAdd, message[2].lower()))
|
2018-01-02 22:35:01 +00:00
|
|
|
|
self.clientChannelOps.append(channelAuthAdd)
|
|
|
|
|
elif len(channelAuthDel) \
|
|
|
|
|
and channelAuthDel in self.clientChannelOps:
|
|
|
|
|
channelAuthDel = channelAuthDel.lower()
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Deauthorising {} on {}".format(channelAuthDel, message[2].lower()))
|
2018-01-02 22:35:01 +00:00
|
|
|
|
self.clientChannelOps.remove(channelAuthDel)
|
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _dispatchNone(self): Dispatch None message from server
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def _dispatchNone(self):
|
|
|
|
|
self._log("Disconnected from {}:{}.".format(self.serverHname, self.serverPort))
|
|
|
|
|
self.close()
|
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _dispatchPing(self, message): Dispatch single PING message from server
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def _dispatchPing(self, message):
|
2018-01-03 03:15:43 +00:00
|
|
|
|
self.queue("PONG", message[2])
|
2018-01-02 22:35:01 +00:00
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _dispatchPrivmsg(self, message): Dispatch single PRIVMSG message from server
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def _dispatchPrivmsg(self, message):
|
2018-01-02 22:35:01 +00:00
|
|
|
|
if message[2].lower() == self.clientChannel.lower() \
|
|
|
|
|
and message[3].startswith("!pngbot "):
|
2018-10-25 01:06:28 +00:00
|
|
|
|
if (int(time.time()) - self.clientChannelLastMessage) < 5:
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Ignoring request on {} from {} due to rate limit: {}".format(message[2].lower(), message[0], message[3]))
|
2018-01-02 22:35:01 +00:00
|
|
|
|
return
|
|
|
|
|
elif message[0].split("!")[0].lower() not in self.clientChannelOps:
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Ignoring request on {} from {} due to lack of authorisation: {}".format(message[2].lower(), message[0], message[3]))
|
2018-01-02 22:35:01 +00:00
|
|
|
|
return
|
|
|
|
|
else:
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Processing request on {} from {}: {}".format(message[2].lower(), message[0], message[3]))
|
2018-01-02 22:35:01 +00:00
|
|
|
|
asciiUrl = message[3].split(" ")[1]
|
|
|
|
|
asciiTmpFilePath = "tmp.txt"; imgTmpFilePath = "tmp.png";
|
|
|
|
|
if os.path.isfile(asciiTmpFilePath):
|
|
|
|
|
os.remove(asciiTmpFilePath)
|
|
|
|
|
if os.path.isfile(imgTmpFilePath):
|
|
|
|
|
os.remove(imgTmpFilePath)
|
2018-01-03 03:24:18 +00:00
|
|
|
|
try:
|
2018-01-03 14:37:26 +00:00
|
|
|
|
urllib.request.urlretrieve(asciiUrl, asciiTmpFilePath, IrcMiRCARTBot._urlretrieveReportHook)
|
|
|
|
|
except IrcMiRCARTBot.ContentTooLargeException:
|
|
|
|
|
self._log("Download size exceeds quota of 1 MB!")
|
|
|
|
|
self.queue("PRIVMSG", message[2], "4/!\\ Download size exceeds quota of 1 MB!")
|
|
|
|
|
return
|
2018-01-03 03:24:18 +00:00
|
|
|
|
except urllib.error.HTTPError as err:
|
|
|
|
|
self._log("Download failed with HTTP status code {}".format(err.code))
|
|
|
|
|
self.queue("PRIVMSG", message[2], "4/!\\ Download failed with HTTP status code {}!".format(err.code))
|
|
|
|
|
return
|
2018-01-03 14:37:26 +00:00
|
|
|
|
except urllib.error.URLError as err:
|
|
|
|
|
self._log("Invalid URL specified!")
|
|
|
|
|
self.queue("PRIVMSG", message[2], "4/!\\ Invalid URL specified!")
|
|
|
|
|
return
|
|
|
|
|
except ValueError as err:
|
|
|
|
|
self._log("Unknown URL type specified!")
|
|
|
|
|
self.queue("PRIVMSG", message[2], "4/!\\ Unknown URL type specified!")
|
|
|
|
|
return
|
2018-01-07 15:43:41 +00:00
|
|
|
|
|
2019-09-03 16:58:50 +00:00
|
|
|
|
canvasStore = CanvasImportStore(inFile=asciiTmpFilePath)
|
2018-01-11 20:28:53 +00:00
|
|
|
|
numRowCols = 0
|
|
|
|
|
for numRow in range(len(canvasStore.outMap)):
|
|
|
|
|
numRowCols = max(numRowCols, len(canvasStore.outMap[numRow]))
|
|
|
|
|
for numRow in range(len(canvasStore.outMap)):
|
|
|
|
|
if len(canvasStore.outMap[numRow]) != numRowCols:
|
|
|
|
|
for numColOff in range(numRowCols - len(canvasStore.outMap[numRow])):
|
2018-01-30 19:34:02 +00:00
|
|
|
|
canvasStore.outMap[numRow].append([1, 1, 0, " "])
|
|
|
|
|
canvasStore.outMap[numRow].insert(0, [1, 1, 0, " "])
|
|
|
|
|
canvasStore.outMap[numRow].append([1, 1, 0, " "])
|
|
|
|
|
canvasStore.outMap.insert(0, [[1, 1, 0, " "]] * len(canvasStore.outMap[0]))
|
|
|
|
|
canvasStore.outMap.append([[1, 1, 0, " "]] * len(canvasStore.outMap[0]))
|
2019-09-03 16:58:50 +00:00
|
|
|
|
MiRCARTToPngFile(canvasStore.outMap, os.path.join("..", "fonts", "DejaVuSansMono.ttf"), 11).export(imgTmpFilePath)
|
IrcMiRCARTBot.py, MiRCARTCanvasInterface.py: remove Imgur API key from repository (via aaa, alghazi, amomp, anji, arab, astra, astra`, biobag, biobag__, bj0rn, blomp, boomp, bromp, brr, butts, buttvomit, c003y, Caku, chomp, chrono_, cooey, CosbyX, darkmage_, dboard, dehuman, dOm3r, eddb, efukt, ep^, er, era, eraser, erratic, erratic_, gnomp, gromp, interdom3, JEWS, kobach, l1tup, Lions, lul, lulz, lulzee, lulzy, Matthew, MercyX, moomp, mr_vile, muff, munki, n0v, nk9k, ooomp, OVH, pcap, pinchy, plop, pngbot, poccri, poomp, promp, pump-, pumpbull, pyrex, rain, rObOtNiK, rondito, scd, SEEEEN, Shapes, snadge, spidy, spinsane, spoke, spomp, stomp, TACO, tetedupet, toohighto, tromp, twomp, vap0r, vapor, venus, virtuald, vixen, whomp, wreathman, wromp, yoomp, z0z0, zen_, and zoomp.)
2018-05-24 06:52:20 +00:00
|
|
|
|
imgurResponse = self._uploadToImgur(imgTmpFilePath, "MiRCART image", "MiRCART image", self.imgurApiKey)
|
2018-12-03 10:51:20 +00:00
|
|
|
|
if imgurResponse[0] == None:
|
|
|
|
|
self._log("Upload failed with exception `{}'".format(imgurResponse[1]))
|
|
|
|
|
self.queue("PRIVMSG", message[2], "4/!\\ Upload failed with exception `{}'!".format(imgurResponse[1]))
|
|
|
|
|
elif imgurResponse[0] == 200:
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Uploaded as: {}".format(imgurResponse[1]))
|
2018-01-03 03:15:43 +00:00
|
|
|
|
self.queue("PRIVMSG", message[2], "8/!\\ Uploaded as: {}".format(imgurResponse[1]))
|
2018-10-25 01:06:28 +00:00
|
|
|
|
self.clientChannelLastMessage = int(time.time())
|
2018-01-02 22:35:01 +00:00
|
|
|
|
else:
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Upload failed with HTTP status code {}".format(imgurResponse[0]))
|
2018-06-21 07:04:22 +00:00
|
|
|
|
self._log("Message from website: {}".format(imgurResponse[1]))
|
2018-01-03 03:24:18 +00:00
|
|
|
|
self.queue("PRIVMSG", message[2], "4/!\\ Upload failed with HTTP status code {}!".format(imgurResponse[0]))
|
2018-06-21 07:04:22 +00:00
|
|
|
|
self.queue("PRIVMSG", message[2], "4/!\\ Message from website: {}".format(imgurResponse[1]))
|
2018-01-02 22:35:01 +00:00
|
|
|
|
if os.path.isfile(asciiTmpFilePath):
|
|
|
|
|
os.remove(asciiTmpFilePath)
|
|
|
|
|
if os.path.isfile(imgTmpFilePath):
|
|
|
|
|
os.remove(imgTmpFilePath)
|
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _dispatchTimer(self): Dispatch single client timer expiration
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def _dispatchTimer(self):
|
2018-01-02 23:40:37 +00:00
|
|
|
|
if self.clientChannelRejoin:
|
2018-01-03 02:28:05 +00:00
|
|
|
|
self._log("Attempting to join {} on {}:{}...".format(self.clientChannel, self.serverHname, self.serverPort))
|
2018-01-03 03:15:43 +00:00
|
|
|
|
self.queue("JOIN", self.clientChannel)
|
2018-01-03 01:16:55 +00:00
|
|
|
|
self.clientNextTimeout = time.time() + 15; self.clientChannelRejoin = True;
|
2018-01-02 23:40:37 +00:00
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _log(self, msg): Log single message to stdout w/ timestamp
|
2018-01-03 02:28:05 +00:00
|
|
|
|
def _log(self, msg):
|
|
|
|
|
print(time.strftime("%Y/%m/%d %H:%M:%S") + " " + msg)
|
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _uploadToImgur(self, imgFilePath, imgName, imgTitle, apiKey): Upload single file to Imgur
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def _uploadToImgur(self, imgFilePath, imgName, imgTitle, apiKey):
|
2018-01-26 21:38:28 +00:00
|
|
|
|
with open(imgFilePath, "rb") as requestImage:
|
|
|
|
|
requestImageData = requestImage.read()
|
2018-01-02 21:38:10 +00:00
|
|
|
|
requestData = { \
|
|
|
|
|
"image": base64.b64encode(requestImageData), \
|
|
|
|
|
"key": apiKey, \
|
|
|
|
|
"name": imgName, \
|
|
|
|
|
"title": imgTitle, \
|
|
|
|
|
"type": "base64"}
|
|
|
|
|
requestHeaders = { \
|
|
|
|
|
"Authorization": "Client-ID " + apiKey}
|
|
|
|
|
responseHttp = requests.post("https://api.imgur.com/3/upload.json", data=requestData, headers=requestHeaders)
|
2018-12-03 10:51:20 +00:00
|
|
|
|
try:
|
|
|
|
|
responseDict = json.loads(responseHttp.text)
|
|
|
|
|
except json.decoder.JSONDecodeError as err:
|
|
|
|
|
return [None, err]
|
2018-01-02 21:38:10 +00:00
|
|
|
|
if responseHttp.status_code == 200:
|
|
|
|
|
return [200, responseDict.get("data").get("link")]
|
|
|
|
|
else:
|
2018-06-21 07:04:22 +00:00
|
|
|
|
return [responseHttp.status_code, responseHttp.text]
|
2018-01-02 21:20:20 +00:00
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ _urlretrieveReportHook(count, blockSize, totalSize): Limit downloads to 1 MB
|
2018-01-03 14:37:26 +00:00
|
|
|
|
def _urlretrieveReportHook(count, blockSize, totalSize):
|
2018-01-04 15:24:06 +00:00
|
|
|
|
if (totalSize > pow(2,20)):
|
2018-01-03 14:37:26 +00:00
|
|
|
|
raise IrcMiRCARTBot.ContentTooLargeException
|
|
|
|
|
# }}}
|
2018-10-25 01:06:28 +00:00
|
|
|
|
# {{{ connect(self, localAddr=None, preferFamily=0, timeout=None): Connect to server and (re)initialise w/ optional timeout
|
|
|
|
|
def connect(self, localAddr=None, preferFamily=0, timeout=None):
|
2018-01-03 02:33:57 +00:00
|
|
|
|
self._log("Connecting to {}:{}...".format(self.serverHname, self.serverPort))
|
2018-10-25 01:06:28 +00:00
|
|
|
|
if super().connect(localAddr=localAddr, preferFamily=preferFamily, timeout=timeout):
|
2018-01-03 02:33:57 +00:00
|
|
|
|
self._log("Connected to {}:{}.".format(self.serverHname, self.serverPort))
|
|
|
|
|
self._log("Registering on {}:{} as {}, {}, {}...".format(self.serverHname, self.serverPort, self.clientNick, self.clientIdent, self.clientGecos))
|
2018-10-25 01:06:28 +00:00
|
|
|
|
self.clientChannelLastMessage = 0; self.clientChannelOps = [];
|
2018-01-03 02:33:57 +00:00
|
|
|
|
self.clientChannelRejoin = False
|
2018-10-25 01:06:28 +00:00
|
|
|
|
self.clientHasPing = False
|
2018-01-03 02:33:57 +00:00
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
return False
|
|
|
|
|
# }}}
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# {{{ dispatch(self): Read, parse, and dispatch single line from server
|
2018-01-03 02:33:57 +00:00
|
|
|
|
def dispatch(self):
|
|
|
|
|
while True:
|
|
|
|
|
if self.clientNextTimeout:
|
|
|
|
|
timeNow = time.time()
|
|
|
|
|
if self.clientNextTimeout <= timeNow:
|
|
|
|
|
self._dispatchTimer()
|
2018-10-25 01:06:28 +00:00
|
|
|
|
if self.unqueue() == False:
|
2018-01-03 02:33:57 +00:00
|
|
|
|
self._dispatchNone(); break;
|
2018-10-25 01:06:28 +00:00
|
|
|
|
else:
|
|
|
|
|
serverMessage = self.readline()
|
|
|
|
|
if serverMessage == None:
|
|
|
|
|
self._dispatchNone(); break;
|
|
|
|
|
elif serverMessage == "":
|
|
|
|
|
if self.clientHasPing:
|
|
|
|
|
self._dispatchNone(); break;
|
|
|
|
|
else:
|
|
|
|
|
self.clientHasPing = True
|
|
|
|
|
self.queue("PING", str(time.time()))
|
|
|
|
|
self._log("Ping...")
|
|
|
|
|
continue
|
|
|
|
|
if serverMessage[1] == "001":
|
2018-01-03 02:33:57 +00:00
|
|
|
|
self._dispatch001(serverMessage)
|
|
|
|
|
elif serverMessage[1] == "353":
|
|
|
|
|
self._dispatch353(serverMessage)
|
|
|
|
|
elif serverMessage[1] == "JOIN":
|
|
|
|
|
self._dispatchJoin(serverMessage)
|
|
|
|
|
elif serverMessage[1] == "KICK":
|
|
|
|
|
self._dispatchKick(serverMessage)
|
|
|
|
|
elif serverMessage[1] == "MODE":
|
|
|
|
|
self._dispatchMode(serverMessage)
|
|
|
|
|
elif serverMessage[1] == "PING":
|
|
|
|
|
self._dispatchPing(serverMessage)
|
2018-10-25 01:06:28 +00:00
|
|
|
|
elif serverMessage[1] == "PONG":
|
|
|
|
|
self._log("Pong.")
|
|
|
|
|
self.clientHasPing = False
|
2018-01-03 02:33:57 +00:00
|
|
|
|
elif serverMessage[1] == "PRIVMSG":
|
|
|
|
|
self._dispatchPrivmsg(serverMessage)
|
|
|
|
|
# }}}
|
2018-01-03 01:33:12 +00:00
|
|
|
|
|
|
|
|
|
#
|
2018-01-06 00:44:45 +00:00
|
|
|
|
# __init__(self, serverHname, serverPort="6667", clientNick="pngbot", clientIdent="pngbot", clientGecos="pngbot", clientChannel="#MiRCART"): initialisation method
|
2018-01-02 21:20:20 +00:00
|
|
|
|
def __init__(self, serverHname, serverPort="6667", clientNick="pngbot", clientIdent="pngbot", clientGecos="pngbot", clientChannel="#MiRCART"):
|
|
|
|
|
super().__init__(serverHname, serverPort, clientNick, clientIdent, clientGecos)
|
|
|
|
|
self.clientChannel = clientChannel
|
|
|
|
|
|
2018-01-02 19:51:32 +00:00
|
|
|
|
#
|
|
|
|
|
# Entry point
|
2018-06-28 16:18:48 +00:00
|
|
|
|
def main(optdict, *argv):
|
|
|
|
|
_IrcMiRCARTBot = IrcMiRCARTBot(*argv)
|
2018-01-02 19:51:32 +00:00
|
|
|
|
while True:
|
2018-10-25 01:06:28 +00:00
|
|
|
|
if "-l" in optdict:
|
|
|
|
|
localAddr = optdict["-l"]
|
|
|
|
|
else:
|
|
|
|
|
localAddr = None
|
2018-06-28 16:18:48 +00:00
|
|
|
|
if "-4" in optdict:
|
|
|
|
|
preferFamily = socket.AF_INET
|
|
|
|
|
elif "-6" in optdict:
|
|
|
|
|
preferFamily = socket.AF_INET6
|
|
|
|
|
else:
|
|
|
|
|
preferFamily = 0
|
2018-10-25 01:06:28 +00:00
|
|
|
|
if _IrcMiRCARTBot.connect(localAddr=localAddr, preferFamily=preferFamily, timeout=15):
|
2018-01-03 01:16:55 +00:00
|
|
|
|
_IrcMiRCARTBot.dispatch()
|
|
|
|
|
_IrcMiRCARTBot.close()
|
|
|
|
|
time.sleep(15)
|
2018-01-02 19:51:32 +00:00
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2018-10-25 01:06:28 +00:00
|
|
|
|
optlist, argv = getopt(sys.argv[1:], "46l:")
|
2018-06-28 16:18:48 +00:00
|
|
|
|
optdict = dict(optlist)
|
2019-02-06 18:10:35 +00:00
|
|
|
|
if len(argv) < 1 or len(argv) > 6:
|
|
|
|
|
print("usage: {} [-4|-6] [-l <local hostname>] " \
|
2018-01-02 22:12:26 +00:00
|
|
|
|
"<IRC server hostname> " \
|
|
|
|
|
"[<IRC server port; defaults to 6667>] " \
|
|
|
|
|
"[<IRC bot nick name; defaults to pngbot>] " \
|
|
|
|
|
"[<IRC bot user name; defaults to pngbot>] " \
|
|
|
|
|
"[<IRC bot real name; defaults to pngbot>] " \
|
2018-01-02 19:51:32 +00:00
|
|
|
|
"[<IRC bot channel name; defaults to #MiRCART>] ".format(sys.argv[0]), file=sys.stderr)
|
|
|
|
|
else:
|
2018-06-28 16:18:48 +00:00
|
|
|
|
main(optdict, *argv)
|
2018-01-02 19:51:32 +00:00
|
|
|
|
|
2018-01-04 15:24:06 +00:00
|
|
|
|
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120
|