Merge branch 'better-multilines' into 'master'
Better multilines by adding flood protection, consolidating privmsg/reply stuff Closes #21 and #23 See merge request !14
This commit is contained in:
commit
5d5b58daa5
@ -143,7 +143,8 @@ class Acro(Plugin):
|
|||||||
|
|
||||||
self.game.state = 1
|
self.game.state = 1
|
||||||
self.game.channel = channel
|
self.game.channel = channel
|
||||||
self.bot.privmsg(self.game.channel, "starting a new game of acro. it will run until you tell it to quit.")
|
self.bot.reply(None, "starting a new game of acro. it will run until you tell it to quit.",
|
||||||
|
explicit_target=self.game.channel)
|
||||||
|
|
||||||
self._start_new_round()
|
self._start_new_round()
|
||||||
|
|
||||||
@ -156,8 +157,9 @@ class Acro(Plugin):
|
|||||||
self.game.rounds[-1].acro = acro
|
self.game.rounds[-1].acro = acro
|
||||||
sleep_time = self.game.rounds[-1].seconds_to_submit + (self.game.rounds[-1].seconds_to_submit_step * (len(acro)-3))
|
sleep_time = self.game.rounds[-1].seconds_to_submit + (self.game.rounds[-1].seconds_to_submit_step * (len(acro)-3))
|
||||||
|
|
||||||
self.bot.privmsg(self.game.channel, "the round has started! your acronym is '{0:s}'. "
|
self.bot.reply(None, "the round has started! your acronym is '{0:s}'. "
|
||||||
"submit within {1:d} seconds via !acro submit [meaning]".format(acro, sleep_time))
|
"submit within {1:d} seconds via !acro submit [meaning]".format(acro, sleep_time),
|
||||||
|
explicit_target=self.game.channel)
|
||||||
|
|
||||||
t = threading.Thread(target=self.thread_do_process_submissions, args=(sleep_time,))
|
t = threading.Thread(target=self.thread_do_process_submissions, args=(sleep_time,))
|
||||||
t.daemon = True
|
t.daemon = True
|
||||||
@ -258,7 +260,7 @@ class Acro(Plugin):
|
|||||||
self.game.state = 3
|
self.game.state = 3
|
||||||
self.game.rounds[-1].sub_shuffle = list(self.game.rounds[-1].submissions.keys())
|
self.game.rounds[-1].sub_shuffle = list(self.game.rounds[-1].submissions.keys())
|
||||||
random.shuffle(self.game.rounds[-1].sub_shuffle)
|
random.shuffle(self.game.rounds[-1].sub_shuffle)
|
||||||
self.bot.privmsg(self.game.channel, "here are the results. vote with !acro vote [number]")
|
self.bot.reply(None, "here are the results. vote with !acro vote [number]", explicit_target=self.game.channel)
|
||||||
self._print_round_acros()
|
self._print_round_acros()
|
||||||
|
|
||||||
t = threading.Thread(target=self.thread_do_process_votes, args=())
|
t = threading.Thread(target=self.thread_do_process_votes, args=())
|
||||||
@ -271,7 +273,8 @@ class Acro(Plugin):
|
|||||||
i = 0
|
i = 0
|
||||||
for s in self.game.rounds[-1].sub_shuffle:
|
for s in self.game.rounds[-1].sub_shuffle:
|
||||||
log.debug("%s is %s", str(i), s)
|
log.debug("%s is %s", str(i), s)
|
||||||
self.bot.privmsg(self.game.channel, " {0:d}: {1:s}".format(i+1, self.game.rounds[-1].submissions[s]))
|
self.bot.reply(None, " {0:d}: {1:s}".format(i+1, self.game.rounds[-1].submissions[s]),
|
||||||
|
explicit_target=self.game.channel)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
def _take_acro_vote(self, nick, vote):
|
def _take_acro_vote(self, nick, vote):
|
||||||
@ -295,7 +298,7 @@ class Acro(Plugin):
|
|||||||
"""Clean up and output for ending the current round."""
|
"""Clean up and output for ending the current round."""
|
||||||
|
|
||||||
self.game.state = 4
|
self.game.state = 4
|
||||||
self.bot.privmsg(self.game.channel, "voting's over! here are the scores for the round:")
|
self.bot.reply(None, "voting's over! here are the scores for the round:", explicit_target=self.game.channel)
|
||||||
self._print_round_scores()
|
self._print_round_scores()
|
||||||
self._add_round_scores_to_game_scores()
|
self._add_round_scores_to_game_scores()
|
||||||
|
|
||||||
@ -309,7 +312,8 @@ class Acro(Plugin):
|
|||||||
i = 0
|
i = 0
|
||||||
for s in list(self.game.rounds[-1].submissions.keys()):
|
for s in list(self.game.rounds[-1].submissions.keys()):
|
||||||
votes = [x for x in list(self.game.rounds[-1].votes.values()) if x == s]
|
votes = [x for x in list(self.game.rounds[-1].votes.values()) if x == s]
|
||||||
self.bot.privmsg(self.game.channel, " {0:d} ({1:s}): {2:d}".format(i+1, s, len(votes)))
|
self.bot.reply(None, " {0:d} ({1:s}): {2:d}".format(i+1, s, len(votes)),
|
||||||
|
explicit_target=self.game.channel)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
def _add_round_scores_to_game_scores(self):
|
def _add_round_scores_to_game_scores(self):
|
||||||
@ -336,14 +340,14 @@ class Acro(Plugin):
|
|||||||
|
|
||||||
self.game.state = 0
|
self.game.state = 0
|
||||||
self.game.quit = False
|
self.game.quit = False
|
||||||
self.bot.privmsg(self.game.channel, "game's over! here are the final scores:")
|
self.bot.reply(None, "game's over! here are the final scores:", explicit_target=self.game.channel)
|
||||||
self._print_game_scores()
|
self._print_game_scores()
|
||||||
|
|
||||||
def _print_game_scores(self):
|
def _print_game_scores(self):
|
||||||
"""Print the final calculated scores."""
|
"""Print the final calculated scores."""
|
||||||
|
|
||||||
for s in list(self.game.scores.keys()):
|
for s in list(self.game.scores.keys()):
|
||||||
self.bot.privmsg(self.game.channel, " {0:s}: {1:d}".format(s, self.game.scores[s]))
|
self.bot.reply(None, " {0:s}: {1:d}".format(s, self.game.scores[s]), explicit_target=self.game.channel)
|
||||||
|
|
||||||
|
|
||||||
plugin = Acro
|
plugin = Acro
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
"""Dispatch is Django/ircbot glue code that allows REST clients to hit Django views and execute IRC bot stuff."""
|
@ -9,24 +9,23 @@ log = logging.getLogger('dispatch.models')
|
|||||||
|
|
||||||
|
|
||||||
class Dispatcher(models.Model):
|
class Dispatcher(models.Model):
|
||||||
|
|
||||||
"""Organize dispatchers by key."""
|
"""Organize dispatchers by key."""
|
||||||
|
|
||||||
key = models.CharField(max_length=16, unique=True)
|
key = models.CharField(max_length=16, unique=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
"""Meta options."""
|
||||||
|
|
||||||
permissions = (
|
permissions = (
|
||||||
('send_message', "Can send messages to dispatchers"),
|
('send_message', "Can send messages to dispatchers"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""String representation."""
|
"""String representation."""
|
||||||
|
|
||||||
return "{0:s}".format(self.key)
|
return "{0:s}".format(self.key)
|
||||||
|
|
||||||
|
|
||||||
class DispatcherAction(models.Model):
|
class DispatcherAction(models.Model):
|
||||||
|
|
||||||
"""Handle requests to dispatchers and do something with them."""
|
"""Handle requests to dispatchers and do something with them."""
|
||||||
|
|
||||||
PRIVMSG_TYPE = 'privmsg'
|
PRIVMSG_TYPE = 'privmsg'
|
||||||
@ -44,5 +43,4 @@ class DispatcherAction(models.Model):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""String representation."""
|
"""String representation."""
|
||||||
|
|
||||||
return "{0:s} -> {1:s} {2:s}".format(self.dispatcher.key, self.type, self.destination)
|
return "{0:s} -> {1:s} {2:s}".format(self.dispatcher.key, self.type, self.destination)
|
||||||
|
@ -6,22 +6,29 @@ from dispatch.models import Dispatcher, DispatcherAction
|
|||||||
|
|
||||||
|
|
||||||
class DispatcherActionSerializer(serializers.ModelSerializer):
|
class DispatcherActionSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serializer for the individual actions associated to a preconfigured dispatcher."""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
"""Meta options."""
|
||||||
|
|
||||||
model = DispatcherAction
|
model = DispatcherAction
|
||||||
fields = ('id', 'dispatcher', 'type', 'destination')
|
fields = ('id', 'dispatcher', 'type', 'destination')
|
||||||
|
|
||||||
|
|
||||||
class DispatcherSerializer(serializers.ModelSerializer):
|
class DispatcherSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serializer for a dispatcher, a set of actions for a key."""
|
||||||
|
|
||||||
actions = DispatcherActionSerializer(many=True, read_only=True)
|
actions = DispatcherActionSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
"""Meta options."""
|
||||||
|
|
||||||
model = Dispatcher
|
model = Dispatcher
|
||||||
fields = ('id', 'key', 'actions')
|
fields = ('id', 'key', 'actions')
|
||||||
|
|
||||||
|
|
||||||
class DispatchMessageSerializer(serializers.Serializer):
|
class DispatchMessageSerializer(serializers.Serializer):
|
||||||
|
"""Serializer for dispatch messaging."""
|
||||||
|
|
||||||
message = serializers.CharField()
|
message = serializers.CharField()
|
||||||
status = serializers.CharField(read_only=True)
|
status = serializers.CharField(read_only=True)
|
||||||
|
@ -18,8 +18,10 @@ log = logging.getLogger('dispatch.views')
|
|||||||
|
|
||||||
|
|
||||||
class HasSendMessagePermission(IsAuthenticated):
|
class HasSendMessagePermission(IsAuthenticated):
|
||||||
|
"""Class to check if the authenticated user can send messages via dispatch."""
|
||||||
|
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request, view):
|
||||||
|
"""Check user permission for dispatch.send_message."""
|
||||||
if request.user.has_perm('dispatch.send_message'):
|
if request.user.has_perm('dispatch.send_message'):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -27,7 +29,6 @@ class HasSendMessagePermission(IsAuthenticated):
|
|||||||
|
|
||||||
|
|
||||||
class DispatcherList(generics.ListAPIView):
|
class DispatcherList(generics.ListAPIView):
|
||||||
|
|
||||||
"""List all dispatchers."""
|
"""List all dispatchers."""
|
||||||
|
|
||||||
queryset = Dispatcher.objects.all()
|
queryset = Dispatcher.objects.all()
|
||||||
@ -35,7 +36,6 @@ class DispatcherList(generics.ListAPIView):
|
|||||||
|
|
||||||
|
|
||||||
class DispatcherDetail(generics.RetrieveAPIView):
|
class DispatcherDetail(generics.RetrieveAPIView):
|
||||||
|
|
||||||
"""Detail the given dispatcher."""
|
"""Detail the given dispatcher."""
|
||||||
|
|
||||||
queryset = Dispatcher.objects.all()
|
queryset = Dispatcher.objects.all()
|
||||||
@ -43,12 +43,12 @@ class DispatcherDetail(generics.RetrieveAPIView):
|
|||||||
|
|
||||||
|
|
||||||
class DispatcherDetailByKey(DispatcherDetail):
|
class DispatcherDetailByKey(DispatcherDetail):
|
||||||
|
"""Detail a specific dispatcher."""
|
||||||
|
|
||||||
lookup_field = 'key'
|
lookup_field = 'key'
|
||||||
|
|
||||||
|
|
||||||
class DispatchMessage(generics.GenericAPIView):
|
class DispatchMessage(generics.GenericAPIView):
|
||||||
|
|
||||||
"""Send a message to the given dispatcher."""
|
"""Send a message to the given dispatcher."""
|
||||||
|
|
||||||
permission_classes = (HasSendMessagePermission,)
|
permission_classes = (HasSendMessagePermission,)
|
||||||
@ -57,12 +57,13 @@ class DispatchMessage(generics.GenericAPIView):
|
|||||||
serializer_class = DispatchMessageSerializer
|
serializer_class = DispatchMessageSerializer
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
dispatcher = self.get_object()
|
"""Return a default message, since this needs POST."""
|
||||||
data = {'message': "", 'status': "READY"}
|
data = {'message': "", 'status': "READY"}
|
||||||
message = self.serializer_class(data=data)
|
message = self.serializer_class(data=data)
|
||||||
return Response(message.initial_data)
|
return Response(message.initial_data)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
|
"""Accept and dispatch a provided message."""
|
||||||
dispatcher = self.get_object()
|
dispatcher = self.get_object()
|
||||||
message = self.serializer_class(data=request.data)
|
message = self.serializer_class(data=request.data)
|
||||||
if message.is_valid():
|
if message.is_valid():
|
||||||
@ -77,9 +78,9 @@ class DispatchMessage(generics.GenericAPIView):
|
|||||||
# connect over XML-RPC and send
|
# connect over XML-RPC and send
|
||||||
try:
|
try:
|
||||||
bot_url = 'http://{0:s}:{1:d}/'.format(settings.IRCBOT_XMLRPC_HOST, settings.IRCBOT_XMLRPC_PORT)
|
bot_url = 'http://{0:s}:{1:d}/'.format(settings.IRCBOT_XMLRPC_HOST, settings.IRCBOT_XMLRPC_PORT)
|
||||||
bot = xmlrpc.client.ServerProxy(bot_url)
|
bot = xmlrpc.client.ServerProxy(bot_url, allow_none=True)
|
||||||
log.debug("sending '%s' to channel %s", text, action.destination)
|
log.debug("sending '%s' to channel %s", text, action.destination)
|
||||||
bot.privmsg(action.destination, text)
|
bot.reply(None, text, False, action.destination)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
new_data = copy.deepcopy(message.data)
|
new_data = copy.deepcopy(message.data)
|
||||||
new_data['status'] = "FAILED - {0:s}".format(str(e))
|
new_data['status'] = "FAILED - {0:s}".format(str(e))
|
||||||
@ -101,12 +102,12 @@ class DispatchMessage(generics.GenericAPIView):
|
|||||||
|
|
||||||
|
|
||||||
class DispatchMessageByKey(DispatchMessage):
|
class DispatchMessageByKey(DispatchMessage):
|
||||||
|
"""Dispatch a message for a specific key."""
|
||||||
|
|
||||||
lookup_field = 'key'
|
lookup_field = 'key'
|
||||||
|
|
||||||
|
|
||||||
class DispatcherActionList(generics.ListAPIView):
|
class DispatcherActionList(generics.ListAPIView):
|
||||||
|
|
||||||
"""List all dispatchers."""
|
"""List all dispatchers."""
|
||||||
|
|
||||||
queryset = DispatcherAction.objects.all()
|
queryset = DispatcherAction.objects.all()
|
||||||
@ -114,7 +115,6 @@ class DispatcherActionList(generics.ListAPIView):
|
|||||||
|
|
||||||
|
|
||||||
class DispatcherActionDetail(generics.RetrieveAPIView):
|
class DispatcherActionDetail(generics.RetrieveAPIView):
|
||||||
|
|
||||||
"""Detail the given dispatcher."""
|
"""Detail the given dispatcher."""
|
||||||
|
|
||||||
queryset = DispatcherAction.objects.all()
|
queryset = DispatcherAction.objects.all()
|
||||||
|
@ -30,8 +30,8 @@ def send_privmsg(request):
|
|||||||
message = form.cleaned_data['message']
|
message = form.cleaned_data['message']
|
||||||
|
|
||||||
bot_url = 'http://{0:s}:{1:d}/'.format(settings.IRCBOT_XMLRPC_HOST, settings.IRCBOT_XMLRPC_PORT)
|
bot_url = 'http://{0:s}:{1:d}/'.format(settings.IRCBOT_XMLRPC_HOST, settings.IRCBOT_XMLRPC_PORT)
|
||||||
bot = xmlrpc.client.ServerProxy(bot_url)
|
bot = xmlrpc.client.ServerProxy(bot_url, allow_none=True)
|
||||||
bot.privmsg(target, message)
|
bot.reply(None, message, False, target)
|
||||||
form = PrivmsgForm()
|
form = PrivmsgForm()
|
||||||
else:
|
else:
|
||||||
form = PrivmsgForm()
|
form = PrivmsgForm()
|
||||||
|
@ -53,6 +53,11 @@ class LenientServerConnection(irc.client.ServerConnection):
|
|||||||
|
|
||||||
buffer_class = irc.buffer.LenientDecodingLineBuffer
|
buffer_class = irc.buffer.LenientDecodingLineBuffer
|
||||||
|
|
||||||
|
def _prep_message(self, string):
|
||||||
|
"""Override SimpleIRCClient._prep_message to add some logging."""
|
||||||
|
log.debug("preparing message %s", string)
|
||||||
|
return super(LenientServerConnection, self)._prep_message(string)
|
||||||
|
|
||||||
|
|
||||||
class DrReactor(irc.client.Reactor):
|
class DrReactor(irc.client.Reactor):
|
||||||
"""Customize the basic IRC library's Reactor with more features."""
|
"""Customize the basic IRC library's Reactor with more features."""
|
||||||
@ -318,6 +323,7 @@ class IRCBot(irc.client.SimpleIRCClient):
|
|||||||
"""A single-server IRC bot class."""
|
"""A single-server IRC bot class."""
|
||||||
|
|
||||||
reactor_class = DrReactor
|
reactor_class = DrReactor
|
||||||
|
splitter = "..."
|
||||||
|
|
||||||
def __init__(self, reconnection_interval=60):
|
def __init__(self, reconnection_interval=60):
|
||||||
super(IRCBot, self).__init__()
|
super(IRCBot, self).__init__()
|
||||||
@ -371,7 +377,8 @@ class IRCBot(irc.client.SimpleIRCClient):
|
|||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
# register XML-RPC stuff
|
# register XML-RPC stuff
|
||||||
self.xmlrpc.register_function(self.privmsg, 'privmsg')
|
self.xmlrpc_register_function(self.privmsg, 'privmsg')
|
||||||
|
self.xmlrpc_register_function(self.reply, 'reply')
|
||||||
|
|
||||||
def _connected_checker(self):
|
def _connected_checker(self):
|
||||||
if not self.connection.is_connected():
|
if not self.connection.is_connected():
|
||||||
@ -832,35 +839,9 @@ class IRCBot(irc.client.SimpleIRCClient):
|
|||||||
return
|
return
|
||||||
|
|
||||||
log.debug("OUTGOING PRIVMSG: t[%s] m[%s]", target, text)
|
log.debug("OUTGOING PRIVMSG: t[%s] m[%s]", target, text)
|
||||||
|
|
||||||
splitter = "..."
|
|
||||||
|
|
||||||
# split messages that are too long. Max length is 512.
|
|
||||||
# TODO: this does not properly handle when the nickmask has been masked by the ircd
|
|
||||||
# is the above still the case?
|
|
||||||
space = 512 - len('\r\n') - len(' PRIVMSG ') - len(target) - len(' :') - len(self.nickmask) - len(' :')
|
|
||||||
splitspace = space - (len(splitter) + 1)
|
|
||||||
|
|
||||||
if len(text) > space:
|
|
||||||
times = 1
|
|
||||||
|
|
||||||
while len(text) > splitspace:
|
|
||||||
splitpos = text.rfind(' ', 0, splitspace)
|
|
||||||
splittext = text[0:splitpos] + ' ' + splitter
|
|
||||||
text = splitter + ' ' + text[splitpos+1:]
|
|
||||||
self.connection.send_raw("PRIVMSG {0:s} :{1:s}".format(target, splittext))
|
|
||||||
|
|
||||||
times = times + 1
|
|
||||||
if times >= 4:
|
|
||||||
# this is stupidly long, abort
|
|
||||||
return
|
|
||||||
|
|
||||||
# done splitting
|
|
||||||
self.connection.send_raw("PRIVMSG {0:s} :{1:s}".format(target, text))
|
|
||||||
else:
|
|
||||||
self.connection.send_raw("PRIVMSG {0:s} :{1:s}".format(target, text))
|
self.connection.send_raw("PRIVMSG {0:s} :{1:s}".format(target, text))
|
||||||
|
|
||||||
def reply(self, event, replystr, stop=False):
|
def reply(self, event, replystr, stop=False, explicit_target=None):
|
||||||
"""Reply over IRC to replypath or return a string with the reply.
|
"""Reply over IRC to replypath or return a string with the reply.
|
||||||
|
|
||||||
The primary utility for this is to properly handle recursion. The
|
The primary utility for this is to properly handle recursion. The
|
||||||
@ -876,24 +857,52 @@ class IRCBot(irc.client.SimpleIRCClient):
|
|||||||
event incoming event
|
event incoming event
|
||||||
replystr the message to reply with
|
replystr the message to reply with
|
||||||
stop whether or not to let other handlers see this
|
stop whether or not to let other handlers see this
|
||||||
|
explicit_target if event is none, use this for the destination
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The replystr if the event is inside recursion, or, potentially,
|
The replystr if the event is inside recursion, or, potentially,
|
||||||
"NO MORE" to stop other event handlers from acting.
|
"NO MORE" to stop other event handlers from acting.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if event:
|
||||||
log.debug("in reply for e[%s] r[%s]", event, replystr)
|
log.debug("in reply for e[%s] r[%s]", event, replystr)
|
||||||
replypath = ircbotlib.reply_destination_for_event(event)
|
replypath = ircbotlib.reply_destination_for_event(event)
|
||||||
|
recursing = getattr(event, '_recursing', False)
|
||||||
|
log.debug("determined recursing to be %s", recursing)
|
||||||
|
elif explicit_target:
|
||||||
|
log.debug("in reply for e[NO EVENT] r[%s]", replystr)
|
||||||
|
replypath = explicit_target
|
||||||
|
recursing = False
|
||||||
|
else:
|
||||||
|
log.warning("reply() called with no event and no explicit target, aborting")
|
||||||
|
return
|
||||||
|
|
||||||
log.debug("replypath: %s", replypath)
|
log.debug("replypath: %s", replypath)
|
||||||
|
|
||||||
if replystr is not None:
|
if replystr is not None:
|
||||||
recursing = getattr(event, '_recursing', False)
|
|
||||||
log.debug("determined recursing to be %s", recursing)
|
|
||||||
if recursing:
|
if recursing:
|
||||||
return replystr
|
return replystr
|
||||||
else:
|
else:
|
||||||
|
lines = 0
|
||||||
replies = replystr.split('\n')
|
replies = replystr.split('\n')
|
||||||
for reply in replies:
|
for reply in replies:
|
||||||
|
# split messages that are too long. max length is 512, but we also need to
|
||||||
|
# account for display and that'll show our hostname
|
||||||
|
space = 512 - len(':{0:s} PRIVMSG {1:s} :\r\n'.format(self.nickmask, replypath))
|
||||||
|
splitspace = space - (len(self.splitter) + 1)
|
||||||
|
|
||||||
|
while len(reply) > space:
|
||||||
|
# do splitting
|
||||||
|
splitpos = reply.rfind(' ', 0, splitspace)
|
||||||
|
splittext = reply[0:splitpos] + ' ' + self.splitter
|
||||||
|
reply = self.splitter + ' ' + reply[splitpos + 1:]
|
||||||
|
self.privmsg(replypath, splittext)
|
||||||
|
|
||||||
|
# antiflood
|
||||||
|
lines += 1
|
||||||
|
time.sleep(int(0.5 * lines))
|
||||||
|
|
||||||
|
# done splitting, or it was never necessary
|
||||||
self.privmsg(replypath, reply)
|
self.privmsg(replypath, reply)
|
||||||
if stop:
|
if stop:
|
||||||
return "NO MORE"
|
return "NO MORE"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.forms import Form, CharField
|
from django.forms import Form, CharField, Textarea
|
||||||
|
|
||||||
log = logging.getLogger('markov.forms')
|
log = logging.getLogger('markov.forms')
|
||||||
|
|
||||||
@ -12,4 +12,4 @@ class PrivmsgForm(Form):
|
|||||||
"""Accept a privmsg to send to the ircbot."""
|
"""Accept a privmsg to send to the ircbot."""
|
||||||
|
|
||||||
target = CharField()
|
target = CharField()
|
||||||
message = CharField()
|
message = CharField(widget=Textarea)
|
||||||
|
@ -133,8 +133,9 @@ class Storycraft(Plugin):
|
|||||||
player = StorycraftPlayer.objects.create(nick=nick, nickmask=event.source, game=game)
|
player = StorycraftPlayer.objects.create(nick=nick, nickmask=event.source, game=game)
|
||||||
|
|
||||||
# tell the control channel
|
# tell the control channel
|
||||||
self.bot.privmsg(master_channel, "{0:s} created a game of storycraft - do '!storycraft game "
|
self.bot.reply(None, "{0:s} created a game of storycraft - do '!storycraft game "
|
||||||
"{1:d} join' to take part!".format(nick, game.pk))
|
"{1:d} join' to take part!".format(nick, game.pk),
|
||||||
|
explicit_target=master_channel)
|
||||||
|
|
||||||
log.debug("%s added a new game", nick)
|
log.debug("%s added a new game", nick)
|
||||||
return self.bot.reply(event, "Game #{0:d} has been created. When everyone has joined, do "
|
return self.bot.reply(event, "Game #{0:d} has been created. When everyone has joined, do "
|
||||||
@ -163,7 +164,8 @@ class Storycraft(Plugin):
|
|||||||
# output results
|
# output results
|
||||||
master_channel = settings.STORYCRAFT_MASTER_CHANNEL
|
master_channel = settings.STORYCRAFT_MASTER_CHANNEL
|
||||||
|
|
||||||
self.bot.privmsg(master_channel, "{0:s} joined storycraft #{1:d}!".format(nick, game_id))
|
self.bot.reply(None, "{0:s} joined storycraft #{1:d}!".format(nick, game_id),
|
||||||
|
explicit_target=master_channel)
|
||||||
log.debug("%s joined game #%d", nick, game_id)
|
log.debug("%s joined game #%d", nick, game_id)
|
||||||
return self.bot.reply(event, "{0:s}, welcome to the game.".format(nick))
|
return self.bot.reply(event, "{0:s}, welcome to the game.".format(nick))
|
||||||
else:
|
else:
|
||||||
@ -235,9 +237,10 @@ class Storycraft(Plugin):
|
|||||||
master_channel = settings.STORYCRAFT_MASTER_CHANNEL
|
master_channel = settings.STORYCRAFT_MASTER_CHANNEL
|
||||||
|
|
||||||
# tell the control channel
|
# tell the control channel
|
||||||
self.bot.privmsg(master_channel, "{0:s} started storycraft #{1:d}! - first player "
|
self.bot.reply(None, "{0:s} started storycraft #{1:d}! - first player "
|
||||||
"is {2:s}, do '!storycraft game {1:d} show line' when the game is "
|
"is {2:s}, do '!storycraft game {1:d} show line' when the game is "
|
||||||
"assigned to you.".format(nick, game_id, player.nick))
|
"assigned to you.".format(nick, game_id, player.nick),
|
||||||
|
explicit_target=master_channel)
|
||||||
log.debug("%s started game #%d", nick, game_id)
|
log.debug("%s started game #%d", nick, game_id)
|
||||||
|
|
||||||
return self.bot.reply(event, "Game #{0:d} started.".format(game_id))
|
return self.bot.reply(event, "Game #{0:d} started.".format(game_id))
|
||||||
@ -343,22 +346,25 @@ class Storycraft(Plugin):
|
|||||||
return_msg = 'Line logged. Please add another. ' + progress_str
|
return_msg = 'Line logged. Please add another. ' + progress_str
|
||||||
else:
|
else:
|
||||||
# notify the new owner, too
|
# notify the new owner, too
|
||||||
self.bot.privmsg(player.nick, "You have a new line in storycraft "
|
self.bot.reply(None, "You have a new line in storycraft "
|
||||||
"#{0:d}: '{1:s}' {2:s}"
|
"#{0:d}: '{1:s}' {2:s}"
|
||||||
"".format(game_id, last_line.line, progress_str))
|
"".format(game_id, last_line.line, progress_str),
|
||||||
|
explicit_target=player.nick)
|
||||||
|
|
||||||
master_channel = settings.STORYCRAFT_MASTER_CHANNEL
|
master_channel = settings.STORYCRAFT_MASTER_CHANNEL
|
||||||
|
|
||||||
log.debug("%s added a line to #%d", nick, game_id)
|
log.debug("%s added a line to #%d", nick, game_id)
|
||||||
# log output
|
# log output
|
||||||
if game.status == StorycraftGame.STATUS_IN_PROGRESS:
|
if game.status == StorycraftGame.STATUS_IN_PROGRESS:
|
||||||
self.bot.privmsg(master_channel, "{0:s} added a line to storycraft "
|
self.bot.reply(None, "{0:s} added a line to storycraft "
|
||||||
"#{1:d}! - next player is {2:s}"
|
"#{1:d}! - next player is {2:s}"
|
||||||
"".format(nick, game_id, player.nick))
|
"".format(nick, game_id, player.nick),
|
||||||
|
explicit_target=master_channel)
|
||||||
return self.bot.reply(event, return_msg)
|
return self.bot.reply(event, return_msg)
|
||||||
else:
|
else:
|
||||||
self.bot.privmsg(master_channel, "{0:s} finished storycraft #{1:d}!"
|
self.bot.reply(None, "{0:s} finished storycraft #{1:d}!"
|
||||||
"".format(nick, game_id))
|
"".format(nick, game_id),
|
||||||
|
explicit_target=master_channel)
|
||||||
return self.bot.reply(event, "Line logged (and game completed).")
|
return self.bot.reply(event, "Line logged (and game completed).")
|
||||||
else:
|
else:
|
||||||
return self.bot.reply(event, "Failed to assign game to next player.")
|
return self.bot.reply(event, "Failed to assign game to next player.")
|
||||||
|
@ -276,7 +276,7 @@ class Twitter(Plugin):
|
|||||||
mentions.reverse()
|
mentions.reverse()
|
||||||
for mention in mentions:
|
for mention in mentions:
|
||||||
reply = self._return_tweet_or_retweet_text(tweet=mention, print_source=True)
|
reply = self._return_tweet_or_retweet_text(tweet=mention, print_source=True)
|
||||||
self.bot.privmsg(out_chan, reply)
|
self.bot.reply(None, reply, explicit_target=out_chan)
|
||||||
since_id = mention['id'] if mention['id'] > since_id else since_id
|
since_id = mention['id'] if mention['id'] > since_id else since_id
|
||||||
|
|
||||||
twittersettings.mentions_since_id = since_id
|
twittersettings.mentions_since_id = since_id
|
||||||
|
Loading…
Reference in New Issue
Block a user