2015-09-02 23:26:13 +00:00
# Nemubot is a smart and modulable IM bot.
# Copyright (C) 2012-2015 Mercier Pierre-Olivier
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# 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/>.
import logging
logger = logging . getLogger ( " nemubot.treatment " )
class MessageTreater :
""" Treat a message """
2015-09-04 20:47:02 +00:00
def __init__ ( self ) :
from nemubot . hooks . manager import HooksManager
self . hm = HooksManager ( )
2015-09-02 23:26:13 +00:00
def treat_msg ( self , msg ) :
""" Treat a given message
Arguments :
msg - - the message to treat
"""
try :
2015-11-17 18:59:38 +00:00
handled = False
2015-09-02 23:26:13 +00:00
# Run pre-treatment: from Message to [ Message ]
msg_gen = self . _pre_treat ( msg )
m = next ( msg_gen , None )
# Run in-treatment: from Message to [ Response ]
while m is not None :
2015-11-17 18:59:38 +00:00
hook_gen = self . _in_hooks ( m )
hook = next ( hook_gen , None )
if hook is not None :
handled = True
for response in self . _in_treat ( m , hook , hook_gen ) :
# Run post-treatment: from Response to [ Response ]
yield from self . _post_treat ( response )
2015-09-02 23:26:13 +00:00
m = next ( msg_gen , None )
2015-11-17 18:59:38 +00:00
if not handled :
for m in self . _in_miss ( msg ) :
yield from self . _post_treat ( m )
2015-09-02 23:26:13 +00:00
except BaseException as e :
logger . exception ( " Error occurred during the processing of the %s : "
" %s " , type ( msg ) . __name__ , msg )
from nemubot . message import Text
yield from self . _post_treat ( Text ( " Sorry, an error occured ( %s ). Feel free to open a new issue at https://github.com/nemunaire/nemubot/issues/new " % type ( e ) . __name__ ,
to = msg . to_response ) )
def _pre_treat ( self , msg ) :
""" Modify input Messages
Arguments :
msg - - message to treat
"""
for h in self . hm . get_hooks ( " pre " , type ( msg ) . __name__ ) :
2015-11-02 18:12:46 +00:00
if h . can_read ( msg . to , msg . server ) and h . match ( msg ) :
2018-02-10 08:51:51 +00:00
for res in flatify ( h . run ( msg ) ) :
if res is not None and res != msg :
yield from self . _pre_treat ( res )
2015-09-02 23:26:13 +00:00
2018-02-10 08:51:51 +00:00
elif res is None or res is False :
break
2015-09-02 23:26:13 +00:00
else :
yield msg
2015-11-17 18:59:38 +00:00
def _in_hooks ( self , msg ) :
for h in self . hm . get_hooks ( " in " , type ( msg ) . __name__ ) :
if h . can_read ( msg . to , msg . server ) and h . match ( msg ) :
yield h
def _in_treat ( self , msg , hook , hook_gen ) :
2015-09-02 23:26:13 +00:00
""" Treats Messages and returns Responses
Arguments :
msg - - message to treat
"""
2016-11-10 17:36:10 +00:00
if hasattr ( msg , " frm_owner " ) :
msg . frm_owner = ( not hasattr ( msg . server , " owner " ) or msg . server . owner == msg . frm )
2015-11-17 18:59:38 +00:00
while hook is not None :
2018-02-10 08:51:51 +00:00
for res in flatify ( hook . run ( msg ) ) :
if not hasattr ( res , " server " ) or res . server is None :
res . server = msg . server
yield res
2015-09-02 23:26:13 +00:00
2015-11-17 18:59:38 +00:00
hook = next ( hook_gen , None )
2015-09-02 23:26:13 +00:00
2015-11-17 18:59:38 +00:00
def _in_miss ( self , msg ) :
2015-11-12 18:15:09 +00:00
from nemubot . message . command import Command as CommandMessage
2015-11-17 18:59:38 +00:00
from nemubot . message . directask import DirectAsk as DirectAskMessage
if isinstance ( msg , CommandMessage ) :
2015-11-12 18:15:09 +00:00
from nemubot . hooks import Command as CommandHook
from nemubot . tools . human import guess
2015-11-17 18:59:38 +00:00
hooks = self . hm . get_reverse_hooks ( " in " , type ( msg ) . __name__ )
2015-11-12 18:15:09 +00:00
suggest = [ s for s in guess ( msg . cmd , [ h . name for h in hooks if isinstance ( h , CommandHook ) and h . name is not None ] ) ]
if len ( suggest ) > = 1 :
2015-11-17 18:59:38 +00:00
yield DirectAskMessage ( msg . frm ,
" Unknown command %s . Would you mean: %s ? " % ( msg . cmd , " , " . join ( suggest ) ) ,
to = msg . to_response )
elif isinstance ( msg , DirectAskMessage ) :
yield DirectAskMessage ( msg . frm ,
" Sorry, I ' m just a bot and your sentence is too complex for me :( But feel free to teach me some tricks at https://github.com/nemunaire/nemubot/! " ,
to = msg . to_response )
2015-11-12 18:15:09 +00:00
2015-09-02 23:26:13 +00:00
def _post_treat ( self , msg ) :
""" Modify output Messages
Arguments :
msg - - response to treat
"""
2015-11-17 18:59:38 +00:00
for h in self . hm . get_hooks ( " post " , type ( msg ) . __name__ ) :
2015-11-02 18:12:46 +00:00
if h . can_write ( msg . to , msg . server ) and h . match ( msg ) :
2018-02-10 08:51:51 +00:00
for res in flatify ( h . run ( msg ) ) :
if res is not None and res != msg :
yield from self . _post_treat ( res )
2015-09-02 23:26:13 +00:00
2018-02-10 08:51:51 +00:00
elif res is None or res is False :
break
2015-09-02 23:26:13 +00:00
else :
yield msg
2018-02-10 08:51:51 +00:00
def flatify ( g ) :
if hasattr ( g , " __iter__ " ) :
for i in g :
yield from flatify ( i )
else :
yield g