Implemented RSS feed reader along with updated rss2chan command.

This commit is contained in:
Griatch 2014-02-27 16:07:39 +01:00
parent c0417def6d
commit 97991a2238
8 changed files with 327 additions and 252 deletions

View file

@ -68,7 +68,7 @@ class PlayerCmdSet(CmdSet):
self.add(comms.CmdCdesc()) self.add(comms.CmdCdesc())
self.add(comms.CmdPage()) self.add(comms.CmdPage())
self.add(comms.CmdIRC2Chan()) self.add(comms.CmdIRC2Chan())
self.add(comms.CmdRSS2Chan())
#self.add(comms.CmdIMC2Chan()) #self.add(comms.CmdIMC2Chan())
#self.add(comms.CmdIMCInfo()) #self.add(comms.CmdIMCInfo())
#self.add(comms.CmdIMCTell()) #self.add(comms.CmdIMCTell())
#self.add(comms.CmdRSS2Chan())

View file

@ -21,8 +21,8 @@ from src.commands.default.muxcommand import MuxCommand, MuxPlayerCommand
__all__ = ("CmdAddCom", "CmdDelCom", "CmdAllCom", __all__ = ("CmdAddCom", "CmdDelCom", "CmdAllCom",
"CmdChannels", "CmdCdestroy", "CmdCBoot", "CmdCemit", "CmdChannels", "CmdCdestroy", "CmdCBoot", "CmdCemit",
"CmdCWho", "CmdChannelCreate", "CmdClock", "CmdCdesc", "CmdCWho", "CmdChannelCreate", "CmdClock", "CmdCdesc",
"CmdPage", "CmdIRC2Chan")#, "CmdIMC2Chan", "CmdIMCInfo", "CmdPage", "CmdIRC2Chan", "CmdRSS2Chan")#, "CmdIMC2Chan", "CmdIMCInfo",
#"CmdIMCTell", "CmdRSS2Chan") #"CmdIMCTell")
def find_channel(caller, channelname, silent=False, noaliases=False): def find_channel(caller, channelname, silent=False, noaliases=False):
@ -798,7 +798,7 @@ class CmdIRC2Chan(MuxCommand):
if 'list' in self.switches: if 'list' in self.switches:
# show all connections # show all connections
ircbots = [bot.typeclass for bot in PlayerDB.objects.filter(db_is_bot=True)] ircbots = [bot.typeclass for bot in PlayerDB.objects.filter(db_is_bot=True, username__startswith="ircbot-")]
if ircbots: if ircbots:
from src.utils.evtable import EvTable from src.utils.evtable import EvTable
table = EvTable("{wdbid{n", "{wbotname{n", "{wev-channel{n", "{wirc-channel{n", border="cells", maxwidth=78) table = EvTable("{wdbid{n", "{wbotname{n", "{wev-channel{n", "{wirc-channel{n", border="cells", maxwidth=78)
@ -849,7 +849,7 @@ class CmdIRC2Chan(MuxCommand):
# re-use an existing bot # re-use an existing bot
bot = bot[0].typeclass bot = bot[0].typeclass
if not bot.is_bot: if not bot.is_bot:
self.msg("Player '%s', which is not a bot, already exists." % botname) self.msg("Player '%s' already exists and is not a bot." % botname)
return return
else: else:
bot = create.create_player(botname, None, None, typeclass=bots.IRCBot) bot = create.create_player(botname, None, None, typeclass=bots.IRCBot)
@ -857,6 +857,101 @@ class CmdIRC2Chan(MuxCommand):
irc_network=irc_network, irc_port=irc_port) irc_network=irc_network, irc_port=irc_port)
self.msg("Connection created. Starting IRC bot.") self.msg("Connection created. Starting IRC bot.")
# RSS connection
class CmdRSS2Chan(MuxCommand):
"""
link an evennia channel to an external RSS feed
Usage:
@rss2chan[/switches] <evennia_channel> = <rss_url>
Switches:
/disconnect - this will stop the feed and remove the connection to the
channel.
/remove - "
/list - show all rss->evennia mappings
Example:
@rss2chan rsschan = http://code.google.com/feeds/p/evennia/updates/basic
This creates an RSS reader that connects to a given RSS feed url. Updates
will be echoed as a title and news link to the given channel. The rate of
updating is set with the RSS_UPDATE_INTERVAL variable in settings (default
is every 10 minutes).
When disconnecting you need to supply both the channel and url again so as
to identify the connection uniquely.
"""
key = "@rss2chan"
locks = "cmd:serversetting(RSS_ENABLED) and pperm(Immortals)"
help_category = "Comms"
def func(self):
"Setup the rss-channel mapping"
# checking we have all we need
if not settings.RSS_ENABLED:
string = """RSS is not enabled. You need to activate it in game/settings.py."""
self.msg(string)
return
try:
import feedparser
feedparser # to avoid checker error of not being used
except ImportError:
string = ("RSS requires python-feedparser (https://pypi.python.org/pypi/feedparser). "
"Install before continuing.")
self.msg(string)
return
if 'list' in self.switches:
# show all connections
rssbots = [bot.typeclass for bot in PlayerDB.objects.filter(db_is_bot=True, username__startswith="rssbot-")]
if rssbots:
from src.utils.evtable import EvTable
table = EvTable("{wdbid{n", "{wupdate rate{n", "{wev-channel", "{wRSS feed URL{n", border="cells", maxwidth=78)
for rssbot in rssbots:
table.add_row(rssbot.id, rssbot.db.rss_rate, rssbot.db.ev_channel, rssbot.db.rss_url)
self.caller.msg(table)
else:
self.msg("No rss bots found.")
return
if('disconnect' in self.switches or 'remove' in self.switches or
'delete' in self.switches):
botname = "rssbot-%s" % self.lhs
matches = PlayerDB.objects.filter(db_is_bot=True, db_key=botname)
if not matches:
# try dbref match
matches = PlayerDB.objects.filter(db_is_bot=True, id=self.args.lstrip("#"))
if matches:
matches[0].delete()
self.msg("RSS connection destroyed.")
else:
self.msg("RSS connection/bot could not be removed, does it exist?")
return
if not self.args or not self.rhs:
string = "Usage: @rss2chan[/switches] <evennia_channel> = <rss url>"
self.msg(string)
return
channel = self.lhs
url = self.rhs
botname = "rssbot-%s" % url
# create a new bot
bot = PlayerDB.objects.filter(username__iexact=botname)
if bot:
# re-use existing bot
bot = bot[0].typeclass
if not bot.is_bot:
self.msg("Player '%s' already exists and is not a bot." % botname)
return
else:
bot = create.create_player(botname, None, None, typeclass=bots.RSSBot)
bot.start(ev_channel=channel, rss_url=url, rss_rate=10)
self.msg("RSS reporter created. Fetching RSS.")
#class CmdIMC2Chan(MuxCommand): #class CmdIMC2Chan(MuxCommand):
# """ # """
@ -1077,85 +1172,3 @@ class CmdIRC2Chan(MuxCommand):
# self.msg("You paged {c%s@%s{n (over IMC): '%s'." % (target, destination, message)) # self.msg("You paged {c%s@%s{n (over IMC): '%s'." % (target, destination, message))
# #
# #
## RSS connection
#class CmdRSS2Chan(MuxCommand):
# """
# link an evennia channel to an external RSS feed
#
# Usage:
# @rss2chan[/switches] <evennia_channel> = <rss_url>
#
# Switches:
# /disconnect - this will stop the feed and remove the connection to the
# channel.
# /remove - "
# /list - show all rss->evennia mappings
#
# Example:
# @rss2chan rsschan = http://code.google.com/feeds/p/evennia/updates/basic
#
# This creates an RSS reader that connects to a given RSS feed url. Updates
# will be echoed as a title and news link to the given channel. The rate of
# updating is set with the RSS_UPDATE_INTERVAL variable in settings (default
# is every 10 minutes).
#
# When disconnecting you need to supply both the channel and url again so as
# to identify the connection uniquely.
# """
#
# key = "@rss2chan"
# locks = "cmd:serversetting(RSS_ENABLED) and pperm(Immortals)"
# help_category = "Comms"
#
# def func(self):
# "Setup the rss-channel mapping"
#
# if not settings.RSS_ENABLED:
# string = """RSS is not enabled. You need to activate it in game/settings.py."""
# self.msg(string)
# return
#
# if 'list' in self.switches:
# # show all connections
# connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='rss_')
# if connections:
# table = prettytable.PrettyTable(["Evennia channel", "RSS url"])
# for conn in connections:
# table.add_row([conn.channel.key, conn.external_config.split('|')[0]])
# string = "{wConnections to RSS:{n\n%s" % table
# self.msg(string)
# else:
# self.msg("No connections found.")
# return
#
# if not self.args or not self.rhs:
# string = "Usage: @rss2chan[/switches] <evennia_channel> = <rss url>"
# self.msg(string)
# return
# channel = self.lhs
# url = self.rhs
#
# if('disconnect' in self.switches or 'remove' in self.switches or
# 'delete' in self.switches):
# chanmatch = find_channel(self.caller, channel, silent=True)
# if chanmatch:
# channel = chanmatch.key
#
# ok = rss.delete_connection(channel, url)
# if not ok:
# self.msg("RSS connection/reader could not be removed, does it exist?")
# else:
# self.msg("RSS connection destroyed.")
# return
#
# channel = find_channel(self.caller, channel)
# if not channel:
# return
# interval = settings.RSS_UPDATE_INTERVAL
# if not interval:
# interval = 10*60
# ok = rss.create_connection(channel, url, interval)
# if not ok:
# self.msg("This RSS connection already exists.")
# return
# self.msg("Connection created. Starting RSS reader.")

View file

@ -59,10 +59,10 @@ class BotStarter(Script):
class CmdBotListen(Command): class CmdBotListen(Command):
""" """
This is a catch-all command that absorbs This is a command that absorbs input
all input coming into the bot through its aimed specifically at the bot. The session
session and pipes it into its execute_cmd must prepend its data with bot_data_in for
method. this to trigger.
""" """
key = "bot_data_in" key = "bot_data_in"
def func(self): def func(self):
@ -199,7 +199,7 @@ class RSSBot(Bot):
An RSS relayer. The RSS protocol itself runs a ticker to update its feed at regular An RSS relayer. The RSS protocol itself runs a ticker to update its feed at regular
intervals. intervals.
""" """
def start(self, ev_channel=None, rss_url=None, rss_update_rate=None): def start(self, ev_channel=None, rss_url=None, rss_rate=None):
""" """
Start by telling the portal to start a new RSS session Start by telling the portal to start a new RSS session
@ -220,19 +220,20 @@ class RSSBot(Bot):
self.db.ev_channel = channel self.db.ev_channel = channel
if rss_url: if rss_url:
self.db.rss_url = rss_url self.db.rss_url = rss_url
if rss_update_rate: if rss_rate:
self.db.rss_update_rate = rss_update_rate self.db.rss_rate = rss_rate
# instruct the server and portal to create a new session with # instruct the server and portal to create a new session with
# the stored configuration # the stored configuration
configdict = {"uid": self.dbid, configdict = {"uid": self.dbid,
"url": self.db.rss_url, "url": self.db.rss_url,
"rate": self.db.rss_update_rate} "rate": self.db.rss_rate}
_SESSIONS.start_bot_session("src.server.portal.rss.RSSBotFactory", configdict) _SESSIONS.start_bot_session("src.server.portal.rss.RSSBotFactory", configdict)
def execute_cmd(self, text=None, sessid=None): def execute_cmd(self, text=None, sessid=None):
""" """
Echo RSS input to connected channel Echo RSS input to connected channel
""" """
print "execute_cmd rss:", text
if not self.ndb.ev_channel and self.db.ev_channel: if not self.ndb.ev_channel and self.db.ev_channel:
# cache channel lookup # cache channel lookup
self.ndb.ev_channel = self.db.ev_channel self.ndb.ev_channel = self.db.ev_channel

View file

@ -36,9 +36,10 @@ class IRCBot(irc.IRCClient, Session):
self.join(self.channel) self.join(self.channel)
self.stopping = False self.stopping = False
self.factory.bot = self self.factory.bot = self
self.init_session("ircbot", self.network, self.factory.sessionhandler) address = "%s@%s" % (self.channel, self.network)
self.init_session("ircbot", address, self.factory.sessionhandler)
# we link back to our bot and log in # we link back to our bot and log in
self.uid = self.factory.uid self.uid = int(self.factory.uid)
self.logged_in = True self.logged_in = True
self.factory.sessionhandler.connect(self) self.factory.sessionhandler.connect(self)
logger.log_infomsg("IRC bot '%s' connected to %s at %s:%s." % (self.nickname, self.channel, logger.log_infomsg("IRC bot '%s' connected to %s at %s:%s." % (self.nickname, self.channel,
@ -86,13 +87,14 @@ class IRCBotFactory(protocol.ReconnectingClientFactory):
factor = 1.5 factor = 1.5
maxDelay = 60 maxDelay = 60
def __init__(self, uid=None, botname=None, channel=None, network=None, port=None): def __init__(self, sessionhandler, uid=None, botname=None, channel=None, network=None, port=None):
"Storing some important protocol properties" "Storing some important protocol properties"
self.uid = int(uid) self.sessionhandler = sessionhandler
self.uid = uid
self.nickname = str(botname) self.nickname = str(botname)
self.channel = str(channel) self.channel = str(channel)
self.network = str(network) self.network = str(network)
self.port = int(port) self.port = port
self.bot = None self.bot = None
def buildProtocol(self, addr): def buildProtocol(self, addr):
@ -118,7 +120,8 @@ class IRCBotFactory(protocol.ReconnectingClientFactory):
def start(self): def start(self):
"Connect session to sessionhandler" "Connect session to sessionhandler"
service = internet.TCPClient(self.network, self.port, self) if self.port:
service = internet.TCPClient(self.network, int(self.port), self)
self.sessionhandler.portal.services.addService(service) self.sessionhandler.portal.services.addService(service)

View file

@ -92,8 +92,7 @@ class PortalSessionHandler(SessionHandler):
cls = _MOD_IMPORT(path, clsname) cls = _MOD_IMPORT(path, clsname)
if not cls: if not cls:
raise RuntimeError("ServerConnect: protocol factory '%s' not found." % protocol_path) raise RuntimeError("ServerConnect: protocol factory '%s' not found." % protocol_path)
protocol = cls(**config) protocol = cls(self, **config)
protocol.sessionhandler = self
protocol.start() protocol.start()
def server_disconnect(self, sessid, reason=""): def server_disconnect(self, sessid, reason=""):

View file

@ -7,11 +7,11 @@ to the channel whenever the feed updates.
""" """
import re import re
from twisted.internet import task from twisted.internet import task, threads
from django.conf import settings from django.conf import settings
from src.comms.models import ExternalChannelConnection, ChannelDB from src.comms.models import ExternalChannelConnection, ChannelDB
from src.server.session import Session
from src.utils import logger, utils from src.utils import logger, utils
from src.scripts.models import ScriptDB
RSS_ENABLED = settings.RSS_ENABLED RSS_ENABLED = settings.RSS_ENABLED
RSS_UPDATE_INTERVAL = settings.RSS_UPDATE_INTERVAL RSS_UPDATE_INTERVAL = settings.RSS_UPDATE_INTERVAL
@ -21,17 +21,6 @@ RETAG = re.compile(r'<[^>]*?>')
# holds rss readers they can be shut down at will. # holds rss readers they can be shut down at will.
RSS_READERS = {} RSS_READERS = {}
def msg_info(message):
"""
Send info to default info channel
"""
message = '[%s][RSS]: %s' % (INFOCHANNEL[0].key, message)
try:
INFOCHANNEL[0].msg(message)
except AttributeError:
logger.log_infomsg("MUDinfo (rss): %s" % message)
if RSS_ENABLED: if RSS_ENABLED:
try: try:
import feedparser import feedparser
@ -39,129 +28,208 @@ if RSS_ENABLED:
raise ImportError("RSS requires python-feedparser to be installed. Install or set RSS_ENABLED=False.") raise ImportError("RSS requires python-feedparser to be installed. Install or set RSS_ENABLED=False.")
class RSSReader(object): class RSSReader(Session):
""" """
Reader script used to connect to each individual RSS feed A simple RSS reader using universal feedparser
""" """
def __init__(self, key, url, interval): def __init__(self, factory, url, rate):
"""
The reader needs an rss url and It also needs an interval
for how often it is to check for new updates (defaults
to 10 minutes)
"""
self.key = key
self.url = url self.url = url
self.interval = interval self.rate = rate
self.entries = {} # stored feeds self.factory = factory
self.task = None self.old_entries = {}
# first we do is to load the feed so we don't resend
# old entries whenever the reader starts.
self.update_feed()
# start runner
self.start()
def update_feed(self): def get_new(self):
"Read the url for new updated data and determine what's new." """Returns list of new items."""
feed = feedparser.parse(self.url) feed = feedparser.parse(self.url)
new = [] new_entries = []
for entry in (e for e in feed['entries'] if e['id'] not in self.entries): for entry in feed['entries']:
txt = "[RSS] %s: %s" % (RETAG.sub("", entry['title']), idval = entry['id'] + entry.get("updated", "")
entry['link'].replace('\n','').encode('utf-8')) if idval not in self.old_entries:
self.entries[entry['id']] = txt self.old_entries[idval] = entry
new.append(txt) new_entries.append(entry)
return new return new_entries
def update(self): def disconnect(self, reason=None):
"Disconnect from feed"
if self.factory.task and self.factory.task.running:
self.factory.task.stop()
self.sessionhandler.disconnect(self)
def _callback(self, new_entries, init):
"Called when RSS returns (threaded)"
if not init:
# for initialization we just ignore old entries
for entry in reversed(new_entries):
self.data_in("bot_data_in " + entry)
def data_in(self, text=None, **kwargs):
"Data RSS -> Server"
self.sessionhandler.data_in(self, text=text, **kwargs)
def _errback(self, fail):
"Report error"
print "RSS feed error: %s" % fail.value
def update(self, init=False):
"Request feed"
return threads.deferToThread(self.get_new).addCallback(self._callback, init).addErrback(self._errback)
class RSSBotFactory(object):
""" """
Called every self.interval seconds - tries to get new feed entries, Initializes new bots
and if so, uses the appropriate ExternalChannelConnection to send the
data to subscribing channels.
""" """
new = self.update_feed()
if not new: def __init__(self, sessionhandler, uid=None, url=None, rate=None):
return "Initialize"
conns = ExternalChannelConnection.objects.filter(db_external_key=self.key) self.sessionhandler = sessionhandler
for conn in (conn for conn in conns if conn.channel): self.url = url
for txt in new: self.rate = rate
conn.to_channel("%s:%s" % (conn.channel.key, txt)) self.uid = uid
self.bot = RSSReader(self, url, rate)
self.task = None
def start(self): def start(self):
""" """
Starting the update task and store a reference in the Called by portalsessionhandler
global variable so it can be found and shut down later.
""" """
global RSS_READERS def errback(fail):
self.task = task.LoopingCall(self.update) print fail.value
self.task.start(self.interval, now=False)
RSS_READERS[self.key] = self
# set up session and connect it to sessionhandler
self.bot.init_session("rssbot", self.url, self.sessionhandler)
self.bot.uid = self.uid
self.bot.logged_in = True
self.sessionhandler.connect(self.bot)
# start repeater task
#self.bot.update(init=True)
self.bot.update(init=True)
self.task = task.LoopingCall(self.bot.update)
if self.rate:
self.task.start(self.rate, now=False).addErrback(errback)
def build_connection_key(channel, url): #class RSSReader(object):
"This is used to id the connection" # """
if hasattr(channel, 'key'): # Reader script used to connect to each individual RSS feed
channel = channel.key # """
return "rss_%s>%s" % (url, channel) # def __init__(self, key, url, interval):
# """
# The reader needs an rss url and It also needs an interval
def create_connection(channel, url, interval): # for how often it is to check for new updates (defaults
""" # to 10 minutes)
This will create a new RSS->channel connection # """
""" # self.key = key
if not type(channel) == ChannelDB: # self.url = url
new_channel = ChannelDB.objects.filter(db_key=channel) # self.interval = interval
if not new_channel: # self.entries = {} # stored feeds
logger.log_errmsg("Cannot attach RSS->Evennia: Evennia Channel '%s' not found." % channel) # self.task = None
return False # # first we do is to load the feed so we don't resend
channel = new_channel[0] # # old entries whenever the reader starts.
key = build_connection_key(channel, url) # self.update_feed()
old_conns = ExternalChannelConnection.objects.filter(db_external_key=key) # # start runner
if old_conns: # self.start()
return False #
config = "%s|%i" % (url, interval) # def update_feed(self):
# There is no sendback from evennia to the rss, so we need not define # "Read the url for new updated data and determine what's new."
# any sendback code. # feed = feedparser.parse(self.url)
conn = ExternalChannelConnection(db_channel=channel, # new = []
db_external_key=key, # for entry in (e for e in feed['entries'] if e['id'] not in self.entries):
db_external_config=config) # txt = "[RSS] %s: %s" % (RETAG.sub("", entry['title']),
conn.save() # entry['link'].replace('\n','').encode('utf-8'))
# self.entries[entry['id']] = txt
connect_to_rss(conn) # new.append(txt)
return True # return new
#
# def update(self):
def delete_connection(channel, url): # """
""" # Called every self.interval seconds - tries to get new feed entries,
Delete rss connection between channel and url # and if so, uses the appropriate ExternalChannelConnection to send the
""" # data to subscribing channels.
key = build_connection_key(channel, url) # """
try: # new = self.update_feed()
conn = ExternalChannelConnection.objects.get(db_external_key=key) # if not new:
except Exception: # return
return False # conns = ExternalChannelConnection.objects.filter(db_external_key=self.key)
conn.delete() # for conn in (conn for conn in conns if conn.channel):
reader = RSS_READERS.get(key, None) # for txt in new:
if reader and reader.task: # conn.to_channel("%s:%s" % (conn.channel.key, txt))
reader.task.stop() #
return True # def start(self):
# """
# Starting the update task and store a reference in the
def connect_to_rss(connection): # global variable so it can be found and shut down later.
""" # """
Create the parser instance and connect to RSS feed and channel # global RSS_READERS
""" # self.task = task.LoopingCall(self.update)
global RSS_READERS # self.task.start(self.interval, now=False)
key = utils.to_str(connection.external_key) # RSS_READERS[self.key] = self
url, interval = [utils.to_str(conf) for conf in connection.external_config.split('|')] #
# Create reader (this starts the running task and stores a reference in RSS_TASKS) #
RSSReader(key, url, int(interval)) #def build_connection_key(channel, url):
# "This is used to id the connection"
# if hasattr(channel, 'key'):
def connect_all(): # channel = channel.key
""" # return "rss_%s>%s" % (url, channel)
Activate all rss feed parsers #
""" #
if not RSS_ENABLED: #def create_connection(channel, url, interval):
return # """
for connection in ExternalChannelConnection.objects.filter(db_external_key__startswith="rss_"): # This will create a new RSS->channel connection
print "connecting RSS: %s" % connection # """
connect_to_rss(connection) # if not type(channel) == ChannelDB:
# new_channel = ChannelDB.objects.filter(db_key=channel)
# if not new_channel:
# logger.log_errmsg("Cannot attach RSS->Evennia: Evennia Channel '%s' not found." % channel)
# return False
# channel = new_channel[0]
# key = build_connection_key(channel, url)
# old_conns = ExternalChannelConnection.objects.filter(db_external_key=key)
# if old_conns:
# return False
# config = "%s|%i" % (url, interval)
# # There is no sendback from evennia to the rss, so we need not define
# # any sendback code.
# conn = ExternalChannelConnection(db_channel=channel,
# db_external_key=key,
# db_external_config=config)
# conn.save()
#
# connect_to_rss(conn)
# return True
#
#
#def delete_connection(channel, url):
# """
# Delete rss connection between channel and url
# """
# key = build_connection_key(channel, url)
# try:
# conn = ExternalChannelConnection.objects.get(db_external_key=key)
# except Exception:
# return False
# conn.delete()
# reader = RSS_READERS.get(key, None)
# if reader and reader.task:
# reader.task.stop()
# return True
#
#
#def connect_to_rss(connection):
# """
# Create the parser instance and connect to RSS feed and channel
# """
# global RSS_READERS
# key = utils.to_str(connection.external_key)
# url, interval = [utils.to_str(conf) for conf in connection.external_config.split('|')]
# # Create reader (this starts the running task and stores a reference in RSS_TASKS)
# RSSReader(key, url, int(interval))
#
#
#def connect_all():
# """
# Activate all rss feed parsers
# """
# if not RSS_ENABLED:
# return
# for connection in ExternalChannelConnection.objects.filter(db_external_key__startswith="rss_"):
# print "connecting RSS: %s" % connection
# connect_to_rss(connection)

View file

@ -423,32 +423,21 @@ if WEBSERVER_ENABLED:
print " webserver: %s" % serverport print " webserver: %s" % serverport
ENABLED = []
if IRC_ENABLED: if IRC_ENABLED:
# IRC channel connections # IRC channel connections
ENABLED.append('irc')
print ' irc enabled'
from src.comms import irc
irc.connect_all()
if IMC2_ENABLED: if IMC2_ENABLED:
# IMC2 channel connections # IMC2 channel connections
ENABLED.append('imc2')
print ' imc2 enabled'
from src.comms import imc2
imc2.connect_all()
if RSS_ENABLED: if RSS_ENABLED:
# RSS feed channel connections # RSS feed channel connections
ENABLED.append('rss')
print ' rss enabled' if ENABLED:
print " " + ", ".join(ENABLED) + " enabled."
from src.comms import rss
rss.connect_all()
for plugin_module in SERVER_SERVICES_PLUGIN_MODULES: for plugin_module in SERVER_SERVICES_PLUGIN_MODULES:
# external plugin protocols # external plugin protocols

View file

@ -236,14 +236,14 @@ class AttributeHandler(object):
def get(self, key=None, category=None, default=None, return_obj=False, def get(self, key=None, category=None, default=None, return_obj=False,
strattr=False, raise_exception=False, accessing_obj=None, strattr=False, raise_exception=False, accessing_obj=None,
default_access=True): default_access=True, not_found_none=False):
""" """
Returns the value of the given Attribute or list of Attributes. Returns the value of the given Attribute or list of Attributes.
strattr will cause the string-only value field instead of the normal strattr will cause the string-only value field instead of the normal
pickled field data. Use to get back values from Attributes added with pickled field data. Use to get back values from Attributes added with
the strattr keyword. the strattr keyword.
If return_obj=True, return the matching Attribute object If return_obj=True, return the matching Attribute object
instead. Returns None if no matches (or [ ] if key was a list instead. Returns default if no matches (or [ ] if key was a list
with no matches). If raise_exception=True, failure to find a with no matches). If raise_exception=True, failure to find a
match will raise AttributeError instead. match will raise AttributeError instead.
@ -278,6 +278,8 @@ class AttributeHandler(object):
ret = ret if return_obj else [attr.strvalue for attr in ret if attr] ret = ret if return_obj else [attr.strvalue for attr in ret if attr]
else: else:
ret = ret if return_obj else [attr.value for attr in ret if attr] ret = ret if return_obj else [attr.value for attr in ret if attr]
if not ret:
return ret if len(key) > 1 else default
return ret[0] if len(ret)==1 else ret return ret[0] if len(ret)==1 else ret
def add(self, key, value, category=None, lockstring="", def add(self, key, value, category=None, lockstring="",
@ -399,10 +401,10 @@ class NickHandler(AttributeHandler):
raw_string raw_string
obj_nicks, player_nicks = [], [] obj_nicks, player_nicks = [], []
for category in make_iter(categories): for category in make_iter(categories):
obj_nicks.extend(make_iter(self.get(category=category, return_obj=True))) obj_nicks.extend([n for n in make_iter(self.get(category=category, return_obj=True)) if n])
if include_player and self.obj.has_player: if include_player and self.obj.has_player:
for category in make_iter(categories): for category in make_iter(categories):
player_nicks.extend(make_iter(self.obj.player.nicks.get(category=category, return_obj=True))) player_nicks.extend([n for n in make_iter(self.obj.player.nicks.get(category=category, return_obj=True)) if n])
for nick in obj_nicks + player_nicks: for nick in obj_nicks + player_nicks:
# make a case-insensitive match here # make a case-insensitive match here
match = re.match(re.escape(nick.db_key), raw_string, re.IGNORECASE) match = re.match(re.escape(nick.db_key), raw_string, re.IGNORECASE)