mirror of
https://github.com/jlu5/PyLink.git
synced 2024-12-24 11:42:51 +01:00
Automode plugin stub (#204)
This supports adding/removing/listing entries and saving them to a DB, but no modes are set yet.
This commit is contained in:
parent
14b30b26c0
commit
d365f04199
@ -1,2 +1,2 @@
|
||||
# Automatically generated by setup.py
|
||||
__version__ = '0.9-dev1-24-g50d30d4'
|
||||
__version__ = '0.9-dev1-27-g14b30b2'
|
||||
|
@ -403,3 +403,7 @@ relay:
|
||||
games:
|
||||
# Sets the nick of the Games service, if you're using it.
|
||||
nick: Games
|
||||
|
||||
automode:
|
||||
# Sets the nick of the Automode service, if you're using it.
|
||||
nick: ModeBot
|
||||
|
183
plugins/automode.py
Normal file
183
plugins/automode.py
Normal file
@ -0,0 +1,183 @@
|
||||
"""
|
||||
automode.py - Provide simple channel ACL management by giving prefix modes to users matching
|
||||
hostmasks or exttargets.
|
||||
"""
|
||||
import collections
|
||||
import threading
|
||||
import json
|
||||
|
||||
from pylinkirc import utils
|
||||
from pylinkirc.log import log
|
||||
|
||||
mydesc = ("The \x02Automode\x02 plugin provides simple channel ACL management by giving prefix modes "
|
||||
"to users matching hostmasks or exttargets.")
|
||||
|
||||
# Register ourselves as a service.
|
||||
modebot = utils.registerService("Automode", desc=mydesc)
|
||||
reply = modebot.reply
|
||||
|
||||
# Databasing variables.
|
||||
dbname = utils.getDatabaseName('automode')
|
||||
db = collections.defaultdict(dict)
|
||||
exportdb_timer = None
|
||||
|
||||
def loadDB():
|
||||
"""Loads the Automode database, silently creating a new one if this fails."""
|
||||
global db
|
||||
try:
|
||||
with open(dbname, "r") as f:
|
||||
db.update(json.load(f))
|
||||
except (ValueError, IOError, OSError):
|
||||
log.info("Automode: failed to load links database %s; using the one in"
|
||||
"memory.", dbname)
|
||||
|
||||
def exportDB():
|
||||
"""Exports the automode database."""
|
||||
|
||||
log.debug("Automode: exporting database to %s.", dbname)
|
||||
with open(dbname, 'w') as f:
|
||||
# Pretty print the JSON output for better readability.
|
||||
json.dump(db, f, indent=4)
|
||||
|
||||
def scheduleExport(starting=False):
|
||||
"""
|
||||
Schedules exporting of the Automode database in a repeated loop.
|
||||
"""
|
||||
global exportdb_timer
|
||||
|
||||
if not starting:
|
||||
# Export the database, unless this is being called the first
|
||||
# thing after start (i.e. DB has just been loaded).
|
||||
exportDB()
|
||||
|
||||
# TODO: possibly make delay between exports configurable
|
||||
exportdb_timer = threading.Timer(30, scheduleExport)
|
||||
exportdb_timer.name = 'Automode exportDB Loop'
|
||||
exportdb_timer.start()
|
||||
|
||||
def main(irc=None):
|
||||
"""Main function, called during plugin loading at start."""
|
||||
|
||||
# Load the relay links database.
|
||||
loadDB()
|
||||
|
||||
# Schedule periodic exports of the automode database.
|
||||
scheduleExport(starting=True)
|
||||
|
||||
def die(sourceirc):
|
||||
"""Saves the Automode database and quit."""
|
||||
exportDB()
|
||||
|
||||
# Kill the scheduling forexports.
|
||||
global exportdb_timer
|
||||
if exportdb_timer:
|
||||
log.debug("Automode: cancelling exportDB timer thread %s due to die()", threading.get_ident())
|
||||
exportdb_timer.cancel()
|
||||
|
||||
def setacc(irc, source, args):
|
||||
"""<channel> <mask> <mode list OR literal ->
|
||||
|
||||
Assigns the given prefix mode characters to the given mask for the channel given. Extended targets are supported for masks - use this to your advantage!
|
||||
|
||||
Examples:
|
||||
SET #channel *!*@localhost ohv
|
||||
SET #channel $account v
|
||||
SET #channel $oper:Network?Administrator qo
|
||||
SET #staffchan $channel:#mainchan:op o
|
||||
"""
|
||||
irc.checkAuthenticated(source)
|
||||
try:
|
||||
channel, mask, modes = args
|
||||
except ValueError:
|
||||
reply(irc, "Error: Invalid arguments given. Needs 3: channel, mask, mode list.")
|
||||
return
|
||||
else:
|
||||
if not utils.isChannel(channel):
|
||||
reply(irc, "Error: Invalid channel name %s." % channel)
|
||||
return
|
||||
|
||||
# Store channels case insensitively
|
||||
channel = irc.toLower(channel)
|
||||
|
||||
# Database entries for any network+channel pair are automatically created using
|
||||
# defaultdict. Note: string keys are used here instead of tuples so they can be
|
||||
# exported easily as JSON.
|
||||
dbentry = db[irc.name+channel]
|
||||
|
||||
# Otherwise, update the modes as is.
|
||||
dbentry[mask] = modes
|
||||
reply(irc, "Done. \x02%s\x02 now has modes \x02%s\x02 in \x02%s\x02." % (mask, modes, channel))
|
||||
|
||||
modebot.add_cmd(setacc, 'setaccess')
|
||||
modebot.add_cmd(setacc, 'set')
|
||||
modebot.add_cmd(setacc, featured=True)
|
||||
|
||||
def delacc(irc, source, args):
|
||||
"""<channel> <mask>
|
||||
|
||||
Removes the Automode entry for the given mask on the given channel, if one exists.
|
||||
"""
|
||||
irc.checkAuthenticated(source)
|
||||
|
||||
try:
|
||||
channel, mask = args
|
||||
except ValueError:
|
||||
reply(irc, "Error: Invalid arguments given. Needs 2: channel, mask")
|
||||
return
|
||||
|
||||
dbentry = db.get(irc.name+channel)
|
||||
|
||||
if dbentry is None:
|
||||
reply(irc, "Error: no Automode access entries exist for \x02%s\x02." % channel)
|
||||
return
|
||||
|
||||
if mask in dbentry:
|
||||
del dbentry[mask]
|
||||
reply(irc, "Done. Removed the Automode access entry for \x02%s\x02 in \x02%s\x02." % (mask, channel))
|
||||
else:
|
||||
reply(irc, "Error: No Automode access entry for \x02%s\x02 exists in \x02%s\x02." % (mask, channel))
|
||||
|
||||
# Remove channels if no more entries are left.
|
||||
if not dbentry:
|
||||
log.debug("Automode: purging empty channel pair %s/%s", irc.name, channel)
|
||||
del db[irc.name+channel]
|
||||
|
||||
return
|
||||
modebot.add_cmd(delacc, 'delaccess')
|
||||
modebot.add_cmd(delacc, 'del')
|
||||
modebot.add_cmd(delacc, featured=True)
|
||||
|
||||
def listacc(irc, source, args):
|
||||
"""<channel>
|
||||
|
||||
Lists all Automode entries for the given channel."""
|
||||
irc.checkAuthenticated(source)
|
||||
try:
|
||||
channel = irc.toLower(args[0])
|
||||
except IndexError:
|
||||
reply(irc, "Error: Invalid arguments given. Needs 1: channel.")
|
||||
return
|
||||
dbentry = db.get(irc.name+channel)
|
||||
if not dbentry:
|
||||
reply(irc, "Error: No Automode access entries exist for \x02%s\x02." % channel)
|
||||
return
|
||||
|
||||
else:
|
||||
# Iterate over all entries and print them. Do this in private to prevent channel
|
||||
# floods.
|
||||
reply(irc, "Showing Automode entries for \x02%s\x02:" % channel, private=True)
|
||||
for entrynum, entry in enumerate(dbentry.items(), start=1):
|
||||
mask, modes = entry
|
||||
reply(irc, "[%s] \x02%s\x02 has modes +\x02%s\x02" % (entrynum, mask, modes), private=True)
|
||||
reply(irc, "End of Automode entries list.")
|
||||
modebot.add_cmd(listacc, featured=True)
|
||||
modebot.add_cmd(listacc, 'listaccess')
|
||||
|
||||
def save(irc, source, args):
|
||||
"""takes no arguments.
|
||||
|
||||
Saves the Automode database to disk."""
|
||||
irc.checkAuthenticated(source)
|
||||
exportDB()
|
||||
reply(irc, 'Done.')
|
||||
modebot.add_cmd(save)
|
Loading…
Reference in New Issue
Block a user