mirror of
https://github.com/krislamo/Flea
synced 2024-12-16 03:00:35 +00:00
Added Control Plugin
Added Control Plugin: authentication and basic control of IRC commands; Move settings and packet info into the IRC class; Minor fix of irclib's Whois function
This commit is contained in:
parent
ec0e9a3485
commit
80e6787d50
12
README.md
12
README.md
@ -1,11 +1,11 @@
|
|||||||
# Flea
|
# Flea
|
||||||
Flea aims to be a modular Python IRC bot. This software was inspired from older
|
Flea aims to be a modular Python IRC bot. This software was inspired from older
|
||||||
IRC bots I wrote.
|
IRC bots I wrote.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
Flea is released under the
|
Flea is released under the
|
||||||
[GNU AGPLv3](https://www.gnu.org/licenses/why-affero-gpl.html), please **direct
|
[GNU AGPLv3](https://www.gnu.org/licenses/why-affero-gpl.html), please **direct
|
||||||
your attention to the LICENSE file in the root of the repository** before
|
your attention to the LICENSE file in the root of the repository** before
|
||||||
continuing.
|
continuing.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
@ -14,7 +14,7 @@ Flea was written in [Python 2.7](http://www.python.org/download/releases/2.7/)
|
|||||||
## Quick Start
|
## Quick Start
|
||||||
1. Edit the *settings.conf* file to appropriate settings on the server you would
|
1. Edit the *settings.conf* file to appropriate settings on the server you would
|
||||||
like to use
|
like to use
|
||||||
|
|
||||||
2. Run the terminal/console in the root of the project and type:
|
2. Run the terminal/console in the root of the project and type:
|
||||||
*python Flea.py*
|
*python Flea.py*
|
||||||
|
|
||||||
|
@ -14,10 +14,14 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
|
# Built-in to Python 2.7
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
class irc:
|
class irc:
|
||||||
debug = False
|
debug = False
|
||||||
|
|
||||||
|
config = {}
|
||||||
|
pack = {}
|
||||||
sock = socket.socket()
|
sock = socket.socket()
|
||||||
|
|
||||||
# IRC Parser. Parses by line
|
# IRC Parser. Parses by line
|
||||||
@ -114,7 +118,7 @@ class irc:
|
|||||||
self.msg("NOTICE "+user+" :\001VERSION "+version+"\001")
|
self.msg("NOTICE "+user+" :\001VERSION "+version+"\001")
|
||||||
|
|
||||||
def Whois(self, query):
|
def Whois(self, query):
|
||||||
self.msg("WHOIS "+query+"\r\n")
|
self.msg("WHOIS "+query)
|
||||||
|
|
||||||
def SetMode(self, channel, nick, mode):
|
def SetMode(self, channel, nick, mode):
|
||||||
self.msg("MODE "+channel+" "+mode+" "+nick)
|
self.msg("MODE "+channel+" "+mode+" "+nick)
|
||||||
|
60
core/main.py
60
core/main.py
@ -23,6 +23,7 @@ import socket
|
|||||||
import ssl
|
import ssl
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
# Allows reimporting modules
|
# Allows reimporting modules
|
||||||
@ -63,6 +64,9 @@ def PluginsImport():
|
|||||||
# Path to /plugins/ under /Flea/
|
# Path to /plugins/ under /Flea/
|
||||||
plugins = current+"/plugins/"
|
plugins = current+"/plugins/"
|
||||||
|
|
||||||
|
# List of plugins
|
||||||
|
plugin_list = []
|
||||||
|
|
||||||
# If /plugins/ exists change directory to it
|
# If /plugins/ exists change directory to it
|
||||||
if os.path.exists(plugins):
|
if os.path.exists(plugins):
|
||||||
os.chdir(plugins)
|
os.chdir(plugins)
|
||||||
@ -73,33 +77,36 @@ def PluginsImport():
|
|||||||
# Only import directory plugins (no single files)
|
# Only import directory plugins (no single files)
|
||||||
if os.path.isdir(plugins+item):
|
if os.path.isdir(plugins+item):
|
||||||
print "[Plugins] Initializing "+item
|
print "[Plugins] Initializing "+item
|
||||||
__import__(item+".main")
|
plugin = __import__(item+".main")
|
||||||
|
plugin_list.append(plugin)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
os.chdir(current)
|
os.chdir(current)
|
||||||
return True
|
return plugin_list
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
# Create irclib irc object
|
||||||
|
irc = irclib.irc()
|
||||||
|
|
||||||
# Parse main settings.conf file
|
# Parse main settings.conf file
|
||||||
config = cfgParser("settings.conf")
|
irc.config = cfgParser("settings.conf")
|
||||||
|
|
||||||
# Keep track of modules for a rollback
|
# Keep track of modules for a rollback
|
||||||
importctrl = ImportRollback()
|
importctrl = ImportRollback()
|
||||||
|
|
||||||
# Import /plugins/
|
# Import /plugins/
|
||||||
if config["plugins"]:
|
if irc.config["plugins"]:
|
||||||
if not PluginsImport():
|
plugins = PluginsImport()
|
||||||
|
if not plugins:
|
||||||
print "[Plugins] Failed to load."
|
print "[Plugins] Failed to load."
|
||||||
|
|
||||||
# Create irclib irc object
|
|
||||||
irc = irclib.irc()
|
|
||||||
|
|
||||||
# Set debug to true/false inside irc() object
|
# Set debug to true/false inside irc() object
|
||||||
irc.debug = config["debug"]
|
irc.debug = irc.config["debug"]
|
||||||
|
|
||||||
# Create socket object
|
# Create socket object
|
||||||
irc.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
irc.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
@ -108,8 +115,8 @@ def main():
|
|||||||
irc.sock = ssl.wrap_socket(irc.sock)
|
irc.sock = ssl.wrap_socket(irc.sock)
|
||||||
|
|
||||||
# Connect to IRC server
|
# Connect to IRC server
|
||||||
irc.sock.connect((config["host"], config["port"]))
|
irc.sock.connect((irc.config["host"], irc.config["port"]))
|
||||||
print "Connecting to "+config["host"]+':'+str(config["port"])
|
print "Connecting to "+irc.config["host"]+':'+str(irc.config["port"])
|
||||||
|
|
||||||
# Display SSL information to the user
|
# Display SSL information to the user
|
||||||
ssl_info = irc.sock.cipher()
|
ssl_info = irc.sock.cipher()
|
||||||
@ -119,10 +126,10 @@ def main():
|
|||||||
print "[SSL] Bits: "+str(ssl_info[2])
|
print "[SSL] Bits: "+str(ssl_info[2])
|
||||||
|
|
||||||
# Send User/Nick message to establish user on the server
|
# Send User/Nick message to establish user on the server
|
||||||
irc.User(config["ident"], config["mode"],
|
irc.User(irc.config["ident"], irc.config["mode"],
|
||||||
config["unused"], config["realname"])
|
irc.config["unused"], irc.config["realname"])
|
||||||
|
|
||||||
irc.Nick(config["nick"])
|
irc.Nick(irc.config["nick"])
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# Buffer to store data from server
|
# Buffer to store data from server
|
||||||
@ -152,24 +159,29 @@ def main():
|
|||||||
|
|
||||||
# Print line, parse it and respond
|
# Print line, parse it and respond
|
||||||
print line
|
print line
|
||||||
pack = irc.Parser(line)
|
irc.pack = irc.Parser(line)
|
||||||
|
|
||||||
|
# Run all plugins main() function
|
||||||
|
if irc.config["plugins"]:
|
||||||
|
for plugin in plugins:
|
||||||
|
plugin.main.main(irc)
|
||||||
|
|
||||||
# Ping Pong, keep the connection alive.
|
# Ping Pong, keep the connection alive.
|
||||||
if pack["cmd"] == "PING":
|
if irc.pack["cmd"] == "PING":
|
||||||
irc.Pong(pack["text"])
|
irc.Pong(irc.pack["text"])
|
||||||
|
|
||||||
# Send user mode message after command 001
|
# Send user mode message after command 001
|
||||||
elif pack["cmd"] == "001":
|
elif irc.pack["cmd"] == "001":
|
||||||
irc.Mode(config["nick"], config["mode"])
|
irc.Mode(irc.config["nick"], irc.config["mode"])
|
||||||
|
|
||||||
elif pack["cmd"] == "NOTICE":
|
elif irc.pack["cmd"] == "NOTICE":
|
||||||
if pack["ident"] == "NickServ":
|
if irc.pack["ident"] == "NickServ":
|
||||||
# Send password after NickServ informs you
|
# Send password after NickServ informs you
|
||||||
# that your nick is registered
|
# that your nick is registered
|
||||||
pattern = r"[Tt]his nickname is registered"
|
pattern = r"[Tt]his nickname is registered"
|
||||||
if re.search(pattern, pack["text"]):
|
if re.search(pattern, irc.pack["text"]):
|
||||||
irc.Identify(config["password"])
|
irc.Identify(irc.config["password"])
|
||||||
irc.Join("#Flea")
|
irc.Join(irc.config["channel"])
|
||||||
|
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
0
plugins/Control/__init__.py
Normal file
0
plugins/Control/__init__.py
Normal file
206
plugins/Control/main.py
Normal file
206
plugins/Control/main.py
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
# Init
|
||||||
|
controlchan = ''
|
||||||
|
chans = {}
|
||||||
|
access = []
|
||||||
|
queue = []
|
||||||
|
|
||||||
|
|
||||||
|
def chkcontrol(irc):
|
||||||
|
global access
|
||||||
|
global queue
|
||||||
|
|
||||||
|
nick = irc.pack["nick"]
|
||||||
|
|
||||||
|
for person in access:
|
||||||
|
if nick == person:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if queue.count(nick) == 0:
|
||||||
|
queue.append(nick)
|
||||||
|
irc.Whois(nick)
|
||||||
|
|
||||||
|
def noaccess(irc):
|
||||||
|
msg = "You don't have access to that."
|
||||||
|
irc.Notice(msg, irc.pack["nick"])
|
||||||
|
|
||||||
|
def main(irc):
|
||||||
|
global controlchan
|
||||||
|
global access
|
||||||
|
global chans
|
||||||
|
global queue
|
||||||
|
|
||||||
|
# Set control channel
|
||||||
|
controlchan = irc.config["channel"]
|
||||||
|
|
||||||
|
# NOTICEs are used to "control" Flea
|
||||||
|
if irc.pack["cmd"] == "NOTICE":
|
||||||
|
|
||||||
|
# Nick must match the nick in settings
|
||||||
|
# e.g. control = Kris
|
||||||
|
if irc.pack["nick"] == irc.config["control"]:
|
||||||
|
|
||||||
|
# Split message by spaces, for functions with
|
||||||
|
# required parameters. e.g. "<cmd> <param1> <param2>"
|
||||||
|
if irc.pack["text"].find(' ') != -1:
|
||||||
|
command = irc.pack["text"].lower().split(' ')
|
||||||
|
|
||||||
|
# Command Flea to join a channel
|
||||||
|
if command[0] == "join":
|
||||||
|
if chkcontrol(irc):
|
||||||
|
irc.Join(command[1])
|
||||||
|
else:
|
||||||
|
noaccess(irc)
|
||||||
|
|
||||||
|
# Command Flea to part
|
||||||
|
elif command[0] == "part":
|
||||||
|
if chkcontrol(irc):
|
||||||
|
irc.Part(command[1],
|
||||||
|
"Fleabot https://github.com/Kris619/Flea")
|
||||||
|
else:
|
||||||
|
noaccess(irc)
|
||||||
|
|
||||||
|
# Single word commands
|
||||||
|
else:
|
||||||
|
if irc.pack["text"] == "acc":
|
||||||
|
if chkcontrol(irc):
|
||||||
|
irc.Notice("You already have access to Control.",
|
||||||
|
irc.pack["nick"])
|
||||||
|
else:
|
||||||
|
noaccess(irc)
|
||||||
|
|
||||||
|
if irc.pack["text"] == "quit":
|
||||||
|
if chkcontrol(irc):
|
||||||
|
irc.Quit("Fleabot https://github.com/Kris619/Flea")
|
||||||
|
quit()
|
||||||
|
else:
|
||||||
|
noaccess(irc)
|
||||||
|
|
||||||
|
# Check if commanding Nick is identified
|
||||||
|
elif irc.pack["cmd"] == "307":
|
||||||
|
if irc.pack["text"] == "is identified for this nick":
|
||||||
|
|
||||||
|
# Check if Nick is in the queue for access list
|
||||||
|
if queue.count(irc.pack["params"][1]) == 1:
|
||||||
|
|
||||||
|
# Remove Nick from queue
|
||||||
|
queue.remove(irc.pack["params"][1])
|
||||||
|
|
||||||
|
# Check if user is set to control in settings
|
||||||
|
# e.g. control = Kris
|
||||||
|
if irc.pack["params"][1] == irc.config["control"]:
|
||||||
|
|
||||||
|
|
||||||
|
# Is control user inside the control channel?
|
||||||
|
if chans[controlchan].count(irc.pack["params"][1]) == 1:
|
||||||
|
|
||||||
|
# Grant access
|
||||||
|
access.append(irc.pack["params"][1])
|
||||||
|
|
||||||
|
print irc.pack["params"][1]+" added to Access"
|
||||||
|
|
||||||
|
irc.Notice(
|
||||||
|
"You have been given access to Control.",
|
||||||
|
irc.pack["params"][1])
|
||||||
|
else:
|
||||||
|
irc.Notice(
|
||||||
|
"You are not in the Control channel: "+controlchan,
|
||||||
|
irc.pack["params"][1])
|
||||||
|
|
||||||
|
# Keep track of users in every channel
|
||||||
|
# "353" lists users to a channel
|
||||||
|
elif irc.pack["cmd"] == "353":
|
||||||
|
|
||||||
|
# If channel is in dictionary of channels
|
||||||
|
if chans.keys().count(irc.pack["params"][2]) == 1:
|
||||||
|
|
||||||
|
# Split list of channel users by space
|
||||||
|
# "+Kris @Flea" > ["+Kris", "@Flea"]
|
||||||
|
if irc.pack["text"].find(' ') != -1:
|
||||||
|
chan_nicks = irc.pack["text"].split(' ')
|
||||||
|
|
||||||
|
for aNick in chan_nicks:
|
||||||
|
if aNick != '':
|
||||||
|
|
||||||
|
# Remove prefix; e.g. "+Kris" > "Kris"
|
||||||
|
if re.search("^[~&@%+]", aNick):
|
||||||
|
aNick = aNick[1:]
|
||||||
|
|
||||||
|
# Add nick to it's channel
|
||||||
|
chans[irc.pack["params"][2]].append(aNick)
|
||||||
|
|
||||||
|
# Track users joining channels
|
||||||
|
elif irc.pack["cmd"] == "JOIN":
|
||||||
|
|
||||||
|
# Check to see if it is the bot that joined
|
||||||
|
if irc.pack["nick"] == irc.config["nick"]:
|
||||||
|
# Create channel user list if it doesn't exist
|
||||||
|
if chans.keys().count(irc.pack["text"]) == 0:
|
||||||
|
chans[irc.pack["text"]] = []
|
||||||
|
|
||||||
|
# Another user joined
|
||||||
|
else:
|
||||||
|
# Add user to channel; chans["#Channel"].append("Kris")
|
||||||
|
chans[irc.pack["text"]].append(irc.pack["nick"])
|
||||||
|
|
||||||
|
# Track users parting from the channel
|
||||||
|
elif irc.pack["cmd"] == "PART":
|
||||||
|
# Remove nick from channel they parted from
|
||||||
|
chans[irc.pack["params"][0]].remove(irc.pack["nick"])
|
||||||
|
|
||||||
|
# If someone parted the control channel
|
||||||
|
# check if it was someone on the access list
|
||||||
|
if irc.pack["params"][0] == controlchan:
|
||||||
|
for usr in access:
|
||||||
|
if usr == irc.pack["nick"]:
|
||||||
|
# Someone on the access list left.
|
||||||
|
access.remove(irc.pack["nick"])
|
||||||
|
print irc.pack["nick"]+" removed from Access"
|
||||||
|
|
||||||
|
# Track users parting from the channel
|
||||||
|
elif irc.pack["cmd"] == "QUIT":
|
||||||
|
|
||||||
|
# Remove user from channels
|
||||||
|
for channel in chans.keys():
|
||||||
|
if chans[channel].count(irc.pack["nick"]) == 1:
|
||||||
|
chans[channel].remove(irc.pack["nick"])
|
||||||
|
|
||||||
|
# Remove access if user quitting had it
|
||||||
|
for usr in access:
|
||||||
|
if usr == irc.pack["nick"]:
|
||||||
|
access.remove(irc.pack["nick"])
|
||||||
|
print irc.pack["nick"]+" removed from Access"
|
||||||
|
|
||||||
|
# Track users being kicked from the channel
|
||||||
|
elif irc.pack["cmd"] == "KICK":
|
||||||
|
|
||||||
|
# Remove nick from channel they were kicked from
|
||||||
|
chans[irc.pack["params"][0]].remove(irc.pack["params"][1])
|
||||||
|
|
||||||
|
# If someone was kicked from the control channel
|
||||||
|
# check if it was someone on the access list
|
||||||
|
if irc.pack["params"][0] == controlchan:
|
||||||
|
if irc.pack["params"][1] == irc.config["nick"]:
|
||||||
|
print "Access list is erased, control channel is gone"
|
||||||
|
access = []
|
||||||
|
else:
|
||||||
|
for usr in access:
|
||||||
|
if usr == irc.pack["params"][1]:
|
||||||
|
# Someone on the access list was kicked.
|
||||||
|
access.remove(irc.pack["params"][1])
|
||||||
|
print irc.pack["params"][1]+" removed from Access"
|
||||||
|
|
||||||
|
# Track users changing their nick
|
||||||
|
elif irc.pack["cmd"] == "NICK":
|
||||||
|
|
||||||
|
for channel in chans.keys():
|
||||||
|
if channel.count(irc.pack["nick"]) == 1:
|
||||||
|
channel.remove(irc.pack["nick"])
|
||||||
|
channel.append(irc.pack["text"])
|
||||||
|
|
||||||
|
# Remove access to users changing their nick
|
||||||
|
for usr in access:
|
||||||
|
if access.count(irc.pack["nick"]) == 1:
|
||||||
|
access.remove(irc.pack["nick"])
|
||||||
|
print irc.pack["nick"]+" removed from Access"
|
@ -1,5 +1,5 @@
|
|||||||
debug = true
|
debug = true
|
||||||
plugins = false
|
plugins = true
|
||||||
|
|
||||||
host = irc.example.net
|
host = irc.example.net
|
||||||
port = 7001
|
port = 7001
|
||||||
@ -11,3 +11,5 @@ mode = +B
|
|||||||
unused = *
|
unused = *
|
||||||
realname = your_name
|
realname = your_name
|
||||||
|
|
||||||
|
control = your_nick
|
||||||
|
channel = #MyChannel
|
Loading…
Reference in New Issue
Block a user