initial
This commit is contained in:
parent
ba860ffc4e
commit
e057eed3ac
|
@ -138,3 +138,9 @@ dmypy.json
|
|||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# config.py
|
||||
config.py
|
||||
|
||||
# ~ files
|
||||
*~
|
||||
|
||||
|
|
39
README.md
39
README.md
|
@ -1,3 +1,40 @@
|
|||
# King-Leonidas
|
||||
|
||||
My IRC bot in python
|
||||
My IRC bot in python
|
||||
|
||||
## Overview
|
||||
|
||||
* `king-leonidas`: The main script.
|
||||
* `config.py`: The settings.
|
||||
* `irc.py`: Generic code to connect to and maintain an IRC connection.
|
||||
* `bot.py`: Stateless IRC bot code that processes lines.
|
||||
|
||||
## Usage
|
||||
|
||||
### Setup
|
||||
|
||||
```
|
||||
python -m venv venv
|
||||
source venv/bin/activate
|
||||
```
|
||||
|
||||
### Launch
|
||||
|
||||
```
|
||||
./king-leonidas
|
||||
```
|
||||
|
||||
### Reload bot.py
|
||||
|
||||
```
|
||||
pkill -HUP king-leonidas
|
||||
```
|
||||
|
||||
## To do
|
||||
|
||||
* join after ident, or SASL
|
||||
* automatically restart on crash
|
||||
* handle should be split into functions that deal with channel messages, privmsgs, etc.
|
||||
* bot state saved to disk?
|
||||
* provide a logfile to write to
|
||||
* would like to be able to trigger a reload using a Control-something signal in the bot itself, rather than pkill in a separate terminal.
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import re
|
||||
|
||||
print("[ + ] Loaded bot.py")
|
||||
|
||||
def handle(state, line, f):
|
||||
print("[IRC] %s" % line)
|
||||
|
||||
# ping/pong
|
||||
m = re.search('^PING :(.*)$', line)
|
||||
if m:
|
||||
print(("PONG %s" % m.group(1)), file=f)
|
||||
return
|
||||
|
||||
# kick anyone who joins
|
||||
m = re.search('^:(.+)!(.+)@(.+) JOIN (.+)$', line)
|
||||
if m:
|
||||
print('KICK %s %s :%s' % (m.group(4), m.group(1), "THIS! IS! SPARTA!"), file=f)
|
||||
return
|
||||
|
||||
# increment a counter
|
||||
m = re.search('^[^ ]+ PRIVMSG ([^ ]+) :\+\+$', line)
|
||||
if m:
|
||||
if 'ctr' not in state:
|
||||
state['ctr'] = 0
|
||||
print('PRIVMSG %s :%s' % (m.group(1), state['ctr']), file=f)
|
||||
state['ctr'] += 1
|
|
@ -0,0 +1,6 @@
|
|||
class Config():
|
||||
username = 'UnHelpfulBot'
|
||||
password = 'Pa55W0Rd*(@#%'
|
||||
server = 'irc.relay.chat'
|
||||
port = '6697'
|
||||
channel = '#chatters'
|
|
@ -0,0 +1,34 @@
|
|||
import sys
|
||||
import socket
|
||||
import ssl
|
||||
import time
|
||||
import importlib
|
||||
|
||||
import bot
|
||||
|
||||
class IRC():
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
self.trigger_reload = False
|
||||
self.state = {}
|
||||
|
||||
def go(self):
|
||||
s0 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s = ssl.wrap_socket(s0)
|
||||
s.connect((self.config.server, int(self.config.port)))
|
||||
f = s.makefile(mode='rw', buffering=1, encoding='utf-8', newline='\r\n')
|
||||
|
||||
print("USER %s %s %s %s" % (self.config.username, self.config.username, self.config.username, self.config.username), file=f)
|
||||
print("NICK %s" % (self.config.username), file=f)
|
||||
print("PRIVMSG NickServ :Identify %s\n" % (self.config.password), file=f)
|
||||
print("JOIN %s" % (self.config.channel), file=f)
|
||||
|
||||
for line in f:
|
||||
if self.trigger_reload:
|
||||
module = importlib.import_module('bot')
|
||||
importlib.reload(module)
|
||||
self.trigger_reload = False
|
||||
try:
|
||||
bot.handle(self.state, line.rstrip(), f)
|
||||
except:
|
||||
print("Unexpected error:", sys.exc_info())
|
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import signal
|
||||
|
||||
from config import Config
|
||||
from irc import IRC
|
||||
|
||||
bot = IRC(Config)
|
||||
|
||||
def sighup_handler(signo, frame):
|
||||
bot.trigger_reload = True
|
||||
|
||||
signal.signal(signal.SIGHUP, sighup_handler)
|
||||
|
||||
bot.go()
|
Loading…
Reference in New Issue