Example #1
0
def handle_omdb(sock, cmd_esc, cmd, line_post_cmd, channel, is_pm):
    if (line_post_cmd != ''):
        title_words = line_post_cmd.rstrip(' ').split(' ')
        for i in range(0, len(title_words)):
            if (title_words[i][0] == title_words[i][0].lower()):
                title_words[i] = title_words[i][0].upper() + title_words[i][1:]
        url = 'http://www.omdbapi.com/?t=' + (
            '+'.join(title_words)) + '&y=&plot=short&r=json'
        try:
            response = http_cat.get_page(url)
        except:
            py3queueln(
                sock, 'PRIVMSG ' + channel +
                ' :Err: Could not retrieve data (weird characters in title?)',
                1)
            return

        response_type = response[0].split("\n")[0].rstrip("\r")
        if (response_type.find('200 OK') < 0):
            py3queueln(
                sock,
                'PRIVMSG ' + channel + ' :Err: \"' + response_type + '\"', 1)
        else:
            try:
                json_tree = json.loads(response[1])
            except ValueError:
                py3queueln(
                    sock, 'PRIVMSG ' + channel +
                    ' :Err: Could not parse json response from omdb', 1)
                return

            #movie information now that retrieval is done
            title = config.get_json_param(json_tree, 'Title')
            title = '' if title == None else title
            rating = config.get_json_param(json_tree, 'imdbRating')
            rating = '' if rating == None else rating
            year = config.get_json_param(json_tree, 'Year')
            year = '' if year == None else year
            #remove unicode to be IRC-friendly
            year = year.replace('–', '-')
            genre = config.get_json_param(json_tree, 'Genre')
            genre = '' if genre == None else genre
            plot = config.get_json_param(json_tree, 'Plot')
            plot = '' if plot == None else plot

            if ((title == '') and (rating == '') and (year == '')
                    and (genre == '') and (plot == '')):
                py3queueln(
                    sock, 'PRIVMSG ' + channel +
                    ' :Err: No information (movie might not be in omdb, or might not exist)',
                    1)
            else:
                py3queueln(
                    sock, 'PRIVMSG ' + channel + ' :' + title + ' / ' +
                    rating + ' / ' + year + ' / ' + genre + ' / ' + plot, 1)
    else:
        py3queueln(
            sock, 'PRIVMSG ' + channel +
            ' :Err: omdb requires a movie title as a parameter', 1)
Example #2
0
def handle_omdb(sock,cmd_esc,cmd,line_post_cmd,channel,is_pm):
	if(line_post_cmd!=''):
		title_words=line_post_cmd.rstrip(' ').split(' ')
		for i in range(0,len(title_words)):
			if(title_words[i][0]==title_words[i][0].lower()):
				title_words[i]=title_words[i][0].upper()+title_words[i][1:]
		url='http://www.omdbapi.com/?t='+('+'.join(title_words))+'&y=&plot=short&r=json'
		try:
			response=http_cat.get_page(url)
		except:
			py3queueln(sock,'PRIVMSG '+channel+' :Err: Could not retrieve data (weird characters in title?)',1)
			return
		
		response_type=response[0].split("\n")[0].rstrip("\r")
		if(response_type.find('200 OK')<0):
			py3queueln(sock,'PRIVMSG '+channel+' :Err: \"'+response_type+'\"',1)
		else:
			try:
				json_tree=json.loads(response[1])
			except ValueError:
				py3queueln(sock,'PRIVMSG '+channel+' :Err: Could not parse json response from omdb',1)
				return
			
			#movie information now that retrieval is done
			title=config.get_json_param(json_tree,'Title')
			title='' if title==None else title
			rating=config.get_json_param(json_tree,'imdbRating')
			rating='' if rating==None else rating
			year=config.get_json_param(json_tree,'Year')
			year='' if year==None else year
			#remove unicode to be IRC-friendly
			year=year.replace('–','-')
			genre=config.get_json_param(json_tree,'Genre')
			genre='' if genre==None else genre
			plot=config.get_json_param(json_tree,'Plot')
			plot='' if plot==None else plot
			
			if((title=='') and (rating=='') and (year=='') and (genre=='') and (plot=='')):
				py3queueln(sock,'PRIVMSG '+channel+' :Err: No information (movie might not be in omdb, or might not exist)',1)
			else:
				py3queueln(sock,'PRIVMSG '+channel+' :'+title+' / '+rating+' / '+year+' / '+genre+' / '+plot,1)
	else:
		py3queueln(sock,'PRIVMSG '+channel+' :Err: omdb requires a movie title as a parameter',1)
Example #3
0
def handle_bot_cmd(sock, cmd_esc, cmd, line_post_cmd, channel, nick, is_pm,
                   state_change, use_pg, db_login):
    global gen_cmd
    global unit_conv_list
    handled = False

    dbg_str = ''

    #check if this was a bot command
    if ((cmd == (cmd_esc + 'wut')) or (cmd == cmd_esc)):
        output = ''
        if (line_post_cmd != ''):
            output, dbg_str = markov.gen_from_str(state_change,
                                                  use_pg,
                                                  db_login,
                                                  irc_str_map(line_post_cmd),
                                                  random.randint(0, 1) + 1,
                                                  retries_left=3)
        if (output == ''):
            output, dbg_str = markov.generate(state_change,
                                              use_pg=use_pg,
                                              db_login=db_login,
                                              back_gen=False)

        #prevent generating commands directed towards other bots,
        #if configured to do that
        if (not gen_cmd):
            if (output.startswith('!')):
                output = '\\' + output

        py3queueln(sock, 'PRIVMSG ' + channel + ' :' + output, 1)
        dbg_str = '[dbg] generated from line \"' + line_post_cmd + '\"' + "\n" + dbg_str
        handled = True
    elif (cmd == (cmd_esc + 'help')):
        if (is_pm):
            py3queueln(
                sock,
                'PRIVMSG ' + channel + ' :This is a simple markov chain bot',
                3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'wut                       -> generate text based on markov chains',
                3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'help                      -> displays this command list', 3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'shup [min nice lvl]       -> clears low-priority messages from sending queue (authorized users can clear higher priority messages)',
                3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'part                      -> parts current channel (you can invite to me get back)',
                3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'calc <expression>         -> simple calculator; supports +,-,*,/,and ^; uses rpn internally',
                3)
            #			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'wiki <topic>              -> [EXPERIMENTAL] grabs first paragraph from wikipedia',3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'source                    -> links the github url for this bot\'s source code',
                3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'omdb <movie name>         -> grabs movie information from the open movie database',
                3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'splchk <word> [edit dist] -> checks given word against a dictionary and suggests fixes',
                3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'dieroll [sides]           -> generates random number in range [1,sides]',
                3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'time [utc offset tz]      -> tells current UTC time, or if a timezone is given, current time in that timezone',
                3)
            py3queueln(
                sock, 'PRIVMSG ' + channel + ' :' + cmd_esc +
                'timecalc <%R> <tz1> <tz2> -> tells what the given time (%R == hours:minutes on a 24-hour clock) at the first utc-offset timezone will be at the second utc-offset timezone',
                3)
            for conversion in unit_conv_list:
                help_str = 'PRIVMSG ' + channel + ' :' + cmd_esc + conversion.from_abbr + '->' + conversion.to_abbr + ' <value>'
                while (len(help_str) <
                       len('PRIVMSG ' + channel + ' :' + cmd_esc +
                           'XXXXXXXXXXXXXXXXXXXXXXXXXX')):
                    help_str += ' '
                help_str += '-> converts ' + conversion.dimension + ' from ' + conversion.from_disp + ' to ' + conversion.to_disp
                py3queueln(sock, help_str, 3)

        else:
            py3queueln(
                sock, 'PRIVMSG ' + channel +
                ' :This is a simple markov chain bot; use ' + cmd_esc +
                'wut or address me by name to generate text; PM !help for more detailed help',
                3)

        handled = True
    #clear (low-priority) messages from the output queue
    elif ((cmd == (cmd_esc + 'shup')) or (cmd == (cmd_esc + 'shoo'))):
        #the minimum nice value to clear messages from the output queue
        nice_lvl = 4
        try:
            nice_lvl = int(line_post_cmd.strip(' '))
        except ValueError:
            nice_lvl = 4

        #authorized users can suppress high-priority output
        if (nick in authed_users):
            nice_lvl = max(nice_lvl, 1)
        #unauthorized users can only suppress low-priority output
        else:
            nice_lvl = max(nice_lvl, 4)

        py3clearq(nice_lvl)
        py3queueln(
            sock, 'PRIVMSG ' + channel +
            ' :Info: outgoing message queue cleared of low-priority messages (nice_lvl='
            + str(nice_lvl) + ')', 1)
        handled = True
    elif (cmd == (cmd_esc + 'part')):
        if (not is_pm):
            py3queueln(
                sock, 'PART ' + channel +
                ' :Goodbye for now (you can invite me back any time)', 1)
        else:
            py3queueln(
                sock, 'PRIVMSG ' + channel +
                ' :part from where, asshole? this is a PM!', 1)
        handled = True
    #conversions are their own function now
    elif (handle_conversion(sock, cmd_esc, cmd, line_post_cmd, channel)):
        handled = True
    elif (cmd == (cmd_esc + 'calc')):
        try:
            err_msgs, result = rpn.rpn_eval(rpn.rpn_translate(line_post_cmd))
            if (len(result) == 1):
                py3queueln(sock, 'PRIVMSG ' + channel + ' :' + str(result[0]),
                           1)
            else:
                py3queueln(
                    sock, 'PRIVMSG ' + channel +
                    ' :Warn: An error occurred during evaluation; simplified RPN expression is '
                    + str(result), 1)
                for err_idx in range(0, len(err_msgs)):
                    py3queueln(
                        sock, 'PRIVMSG ' + channel + ' :Err #' + str(err_idx) +
                        ': ' + str(err_msgs[err_idx]), 3)
        #TODO: figure out why divide-by-0 is triggering a ValueError here, it should be handled elsewhere
        except ValueError:
            py3queueln(
                sock, 'PRIVMSG ' + channel +
                ' :Err: Could not parse expression (ValueError) (divide by zero?)',
                1)
        except IndexError:
            py3queueln(
                sock, 'PRIVMSG ' + channel +
                ' :Err: Could not parse expression (IndexError) (mismatched parens?)',
                1)
        except:
            py3queueln(
                sock, 'PRIVMSG ' + channel +
                ' :Err: Unhandled exception in rpn parsing; tell neutrak the command you used to get this and he\'ll look into it',
                1)
        handled = True
    elif (cmd == (cmd_esc + 'wiki')):
        #disabled because we have another bot to do this now
        return (True, dbg_str)

        #TODO: handle more specific errors; this is super nasty but should keep the bot from crashing
        try:
            wiki_title = line_post_cmd.replace(' ', '_')
            wiki_url = 'https://en.wikipedia.org/wiki/' + wiki_title
            response = http_cat.get_page(wiki_url)

            response_type = response[0].split("\n")[0].rstrip("\r")

            #if we get a 301 moved and the page requested was lower case then
            #before giving up try it as upper-case
            if ((response_type.find('301 Moved') >= 0)
                    and (line_post_cmd[0] == line_post_cmd[0].lower())):
                return handle_bot_cmd(sock, cmd_esc, cmd,
                                      (line_post_cmd[0].upper()) +
                                      (line_post_cmd[1:]), channel, nick,
                                      is_pm, state_change, use_pg, db_login)

            if (response_type.find('200 OK') < 0):
                py3queueln(
                    sock,
                    'PRIVMSG ' + channel + ' :Err: \"' + response_type + '\"',
                    1)
            else:
                wiki_text = response[1]
                if (wiki_text == ''):
                    py3queueln(
                        sock, 'PRIVMSG ' + channel +
                        ' :Err: wiki got null page text', 1)
                else:
                    #get the first paragraph and throw out nested html tags
                    wiki_text = http_cat.html_parse_first(
                        wiki_text, '<p>', '</p>')
                    max_p_len = 768
                    wiki_text = wiki_text[0:max_p_len]
                    line_len = 300
                    while (wiki_text != ''):
                        line_delimiter = '. '
                        prd_idx = wiki_text.find(line_delimiter)
                        if (prd_idx >= 0):
                            prd_idx += len(line_delimiter)
                            py3queueln(
                                sock, 'PRIVMSG ' + channel + ' :' +
                                wiki_text[0:prd_idx], 1)
                            wiki_text = wiki_text[prd_idx:]
                        else:
                            py3queueln(
                                sock, 'PRIVMSG ' + channel + ' :' +
                                wiki_text[0:line_len], 1)
                            wiki_text = wiki_text[line_len:]
                py3queueln(sock, 'PRIVMSG ' + channel + ' :' + wiki_url,
                           1)  #link the wiki page itself?
        except:
            py3queueln(
                sock,
                'PRIVMSG ' + channel + ' :Err: wiki failed to get page text',
                1)
        handled = True
    elif (cmd == (cmd_esc + 'source')):
        py3queueln(
            sock,
            'PRIVMSG ' + channel + ' :bot source code: ' + SOURCE_CODE_URL, 1)
        handled = True
    elif ((cmd == (cmd_esc + 'omdb')) or (cmd == (cmd_esc + 'imdb'))):
        handle_omdb(sock, cmd_esc, cmd, line_post_cmd, channel, is_pm)
        handled = True
    elif ((cmd == (cmd_esc + 'splchk')) or (cmd == (cmd_esc + 'spellcheck'))
          or (cmd == (cmd_esc + 'sp')) or (cmd == (cmd_esc + 'spell'))):
        handle_spellcheck(sock, cmd_esc, cmd, line_post_cmd, channel, is_pm)
        handled = True
    elif (cmd == (cmd_esc + 'dieroll')):
        sides = 6
        if (line_post_cmd != ''):
            try:
                sides = int(line_post_cmd)
            except ValueError:
                py3queueln(
                    sock, 'PRIVMSG ' + channel +
                    ' :Warn: Invalid number of sides, assuming d-6', 1)
                sides = 6
        if (sides < 1):
            py3queueln(
                sock, 'PRIVMSG ' + channel +
                ' :Warn: Number of sides less than 1, setting number of sides 1 (this will return 1)',
                1)
            sides = 1

        value = random.randint(1, sides)
        py3queueln(
            sock, 'PRIVMSG ' + channel + ' :Rolled a ' + str(value) +
            ' with a d' + str(sides), 1)

        handled = True
    elif (cmd == (cmd_esc + 'time')):
        tz = 0
        if (line_post_cmd != ''):
            try:
                tz = float(line_post_cmd)
            except ValueError:
                py3queueln(
                    sock, 'PRIVMSG ' + channel + ' :Err: ' + line_post_cmd +
                    ' is not a valid UTC-offset timezone; will give UTC time instead...',
                    1)
        if (abs(tz) > 24):
            py3queueln(
                sock, 'PRIVMSG ' + channel +
                ' :Err: timezone offsets from utc cannot be outside the range [-24,24] because that makes no sense; giving UTC time...'
            )
            tz = 0
        current_time = time.asctime(time.gmtime(time.time() + (tz * 60 * 60)))
        py3queueln(
            sock, 'PRIVMSG ' + channel + ' :Current time is ' + current_time +
            ' (UTC ' + ('+' + str(tz) if tz >= 0 else str(tz)) + ')')
        handled = True
    elif (cmd == (cmd_esc + 'timecalc')):
        handle_timecalc(sock, cmd_esc, cmd, line_post_cmd, channel, is_pm)
        handled = True
    elif (cmd.startswith(cmd_esc)):
        try:
            #alternate conversion syntax
            #check if the "command" is a valid floating point number
            conv_arg = float(cmd[len(cmd_esc):])

            #the line after the "command" is the command checked against the conversion list
            #some arguments here are a little weird because they're being transposed
            found_conversion = False
            for conversion in unit_conv_list:
                #we found the requested conversion, so do the thing and output the result
                #note that "X to Y" gets translated here as "X->Y"
                if (conversion.chk_cmd(
                        cmd_esc,
                        cmd_esc + line_post_cmd.replace(' to ', '->'))):
                    conversion.output_conv(sock, channel, conv_arg)
                    found_conversion = True

            #this was a valid number, but something went wrong during conversion
            if (not found_conversion):
                py3queueln(
                    sock, 'PRIVMSG ' + channel +
                    ' :Err: Conversion not found ' + line_post_cmd, 1)

            #in any case if we got a number don't handle this line any more
            handled = True
        #the "command" wasn't a valid floating point number,
        #so output an error for PM, or just do nothing in a channel
        except ValueError:
            if (is_pm):
                py3queueln(
                    sock,
                    'PRIVMSG ' + channel + ' :Warn: Invalid command: \"' +
                    cmd + '\"; see ' + cmd_esc + 'help for help', 1)

        #this prevents the bot from learning from unrecognized ! commands
        #(which are usually meant for another bot)


#		handled=True
#this was added at the request of NuclearWaffle, in an attempt, and I'm quoting here
#to "f**k with Proview"
#	elif((len(cmd)>1) and odd_quest(cmd)):
#		output,dbg_str=markov.generate(state_change,use_pg=use_pg,db_login=db_login,back_gen=False)
#
#		#prevent generating commands directed towards other bots,
#		#if configured to do that
#		if(not gen_cmd):
#			if(output.startswith('!')):
#				output='\\'+output
#
#		py3queueln(sock,'PRIVMSG '+channel+' :'+output,1)
#		handled=True

    return (handled, dbg_str)
Example #4
0
def handle_bot_cmd(sock,cmd_esc,cmd,line_post_cmd,channel,nick,is_pm,state_change,use_pg,db_login):
	global gen_cmd
	global unit_conv_list
	handled=False
	
	dbg_str=''
	
	#check if this was a bot command
	if((cmd==(cmd_esc+'wut')) or (cmd==cmd_esc)):
		output=''
		if(line_post_cmd!=''):
			output,dbg_str=markov.gen_from_str(state_change,use_pg,db_login,irc_str_map(line_post_cmd),random.randint(0,1)+1,retries_left=3)
		if(output==''):
			output,dbg_str=markov.generate(state_change,use_pg=use_pg,db_login=db_login,back_gen=False)
		
		#prevent generating commands directed towards other bots,
		#if configured to do that
		if(not gen_cmd):
			if(output.startswith('!')):
				output='\\'+output
		
		py3queueln(sock,'PRIVMSG '+channel+' :'+output,1)
		dbg_str='[dbg] generated from line \"'+line_post_cmd+'\"'+"\n"+dbg_str
		handled=True
	elif(cmd==(cmd_esc+'help')):
		if(is_pm):
			py3queueln(sock,'PRIVMSG '+channel+' :This is a simple markov chain bot',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'wut                       -> generate text based on markov chains',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'help                      -> displays this command list',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'shup [min nice lvl]       -> clears low-priority messages from sending queue (authorized users can clear higher priority messages)',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'part                      -> parts current channel (you can invite to me get back)',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'calc <expression>         -> simple calculator; supports +,-,*,/,and ^; uses rpn internally',3)
#			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'wiki <topic>              -> [EXPERIMENTAL] grabs first paragraph from wikipedia',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'source                    -> links the github url for this bot\'s source code',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'omdb <movie name>         -> grabs movie information from the open movie database',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'splchk <word> [edit dist] -> checks given word against a dictionary and suggests fixes',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'dieroll [sides]           -> generates random number in range [1,sides]',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'time [utc offset tz]      -> tells current UTC time, or if a timezone is given, current time in that timezone',3)
			py3queueln(sock,'PRIVMSG '+channel+' :'+cmd_esc+'timecalc <%R> <tz1> <tz2> -> tells what the given time (%R == hours:minutes on a 24-hour clock) at the first utc-offset timezone will be at the second utc-offset timezone',3)
			for conversion in unit_conv_list:
				help_str='PRIVMSG '+channel+' :'+cmd_esc+conversion.from_abbr+'->'+conversion.to_abbr+' <value>'
				while(len(help_str)<len('PRIVMSG '+channel+' :'+cmd_esc+'XXXXXXXXXXXXXXXXXXXXXXXXXX')):
					help_str+=' '
				help_str+='-> converts '+conversion.dimension+' from '+conversion.from_disp+' to '+conversion.to_disp
				py3queueln(sock,help_str,3)

		else:
			py3queueln(sock,'PRIVMSG '+channel+' :This is a simple markov chain bot; use '+cmd_esc+'wut or address me by name to generate text; PM !help for more detailed help',3)
			
		handled=True
	#clear (low-priority) messages from the output queue
	elif((cmd==(cmd_esc+'shup')) or (cmd==(cmd_esc+'shoo'))):
		#the minimum nice value to clear messages from the output queue
		nice_lvl=4
		try:
			nice_lvl=int(line_post_cmd.strip(' '))
		except ValueError:
			nice_lvl=4
		
		#authorized users can suppress high-priority output
		if(nick in authed_users):
			nice_lvl=max(nice_lvl,1)
		#unauthorized users can only suppress low-priority output
		else:
			nice_lvl=max(nice_lvl,4)
		
		py3clearq(nice_lvl)
		py3queueln(sock,'PRIVMSG '+channel+' :Info: outgoing message queue cleared of low-priority messages (nice_lvl='+str(nice_lvl)+')',1)
		handled=True
	elif(cmd==(cmd_esc+'part')):
		if(not is_pm):
			py3queueln(sock,'PART '+channel+' :Goodbye for now (you can invite me back any time)',1)
		else:
			py3queueln(sock,'PRIVMSG '+channel+' :part from where, asshole? this is a PM!',1)
		handled=True
	#conversions are their own function now
	elif(handle_conversion(sock,cmd_esc,cmd,line_post_cmd,channel)):
		handled=True
	elif(cmd==(cmd_esc+'calc')):
		try:
			err_msgs,result=rpn.rpn_eval(rpn.rpn_translate(line_post_cmd))
			if(len(result)==1):
				py3queueln(sock,'PRIVMSG '+channel+' :'+str(result[0]),1)
			else:
				py3queueln(sock,'PRIVMSG '+channel+' :Warn: An error occurred during evaluation; simplified RPN expression is '+str(result),1)
				for err_idx in range(0,len(err_msgs)):
					py3queueln(sock,'PRIVMSG '+channel+' :Err #'+str(err_idx)+': '+str(err_msgs[err_idx]),3)
		#TODO: figure out why divide-by-0 is triggering a ValueError here, it should be handled elsewhere
		except ValueError:
			py3queueln(sock,'PRIVMSG '+channel+' :Err: Could not parse expression (ValueError) (divide by zero?)',1)
		except IndexError:
			py3queueln(sock,'PRIVMSG '+channel+' :Err: Could not parse expression (IndexError) (mismatched parens?)',1)
		except:
			py3queueln(sock,'PRIVMSG '+channel+' :Err: Unhandled exception in rpn parsing; tell neutrak the command you used to get this and he\'ll look into it',1)
		handled=True
	elif(cmd==(cmd_esc+'wiki')):
		#disabled because we have another bot to do this now
		return (True,dbg_str)
		
		#TODO: handle more specific errors; this is super nasty but should keep the bot from crashing
		try:
			wiki_title=line_post_cmd.replace(' ','_')
			wiki_url='https://en.wikipedia.org/wiki/'+wiki_title
			response=http_cat.get_page(wiki_url)
			
			response_type=response[0].split("\n")[0].rstrip("\r")
			
			#if we get a 301 moved and the page requested was lower case then
			#before giving up try it as upper-case
			if((response_type.find('301 Moved')>=0) and (line_post_cmd[0]==line_post_cmd[0].lower())):
				return handle_bot_cmd(sock,cmd_esc,
					cmd,
					(line_post_cmd[0].upper())+(line_post_cmd[1:]),
					channel,
					nick,is_pm,state_change,use_pg,db_login)
			
			if(response_type.find('200 OK')<0):
				py3queueln(sock,'PRIVMSG '+channel+' :Err: \"'+response_type+'\"',1)
			else:
				wiki_text=response[1]
				if(wiki_text==''):
					py3queueln(sock,'PRIVMSG '+channel+' :Err: wiki got null page text',1)
				else:
					#get the first paragraph and throw out nested html tags
					wiki_text=http_cat.html_parse_first(wiki_text,'<p>','</p>')
					max_p_len=768
					wiki_text=wiki_text[0:max_p_len]
					line_len=300
					while(wiki_text!=''):
						line_delimiter='. '
						prd_idx=wiki_text.find(line_delimiter)
						if(prd_idx>=0):
							prd_idx+=len(line_delimiter)
							py3queueln(sock,'PRIVMSG '+channel+' :'+wiki_text[0:prd_idx],1)
							wiki_text=wiki_text[prd_idx:]
						else:
							py3queueln(sock,'PRIVMSG '+channel+' :'+wiki_text[0:line_len],1)
							wiki_text=wiki_text[line_len:]
				py3queueln(sock,'PRIVMSG '+channel+' :'+wiki_url,1) #link the wiki page itself?
		except:
			py3queueln(sock,'PRIVMSG '+channel+' :Err: wiki failed to get page text',1)
		handled=True
	elif(cmd==(cmd_esc+'source')):
		py3queueln(sock,'PRIVMSG '+channel+' :bot source code: '+SOURCE_CODE_URL,1)
		handled=True
	elif((cmd==(cmd_esc+'omdb')) or (cmd==(cmd_esc+'imdb'))):
		handle_omdb(sock,cmd_esc,cmd,line_post_cmd,channel,is_pm)
		handled=True
	elif((cmd==(cmd_esc+'splchk')) or (cmd==(cmd_esc+'spellcheck')) or (cmd==(cmd_esc+'sp')) or (cmd==(cmd_esc+'spell'))):
		handle_spellcheck(sock,cmd_esc,cmd,line_post_cmd,channel,is_pm)
		handled=True
	elif(cmd==(cmd_esc+'dieroll')):
		sides=6
		if(line_post_cmd!=''):
			try:
				sides=int(line_post_cmd)
			except ValueError:
				py3queueln(sock,'PRIVMSG '+channel+' :Warn: Invalid number of sides, assuming d-6',1)
				sides=6
		if(sides<1):
			py3queueln(sock,'PRIVMSG '+channel+' :Warn: Number of sides less than 1, setting number of sides 1 (this will return 1)',1)
			sides=1
		
		value=random.randint(1,sides)
		py3queueln(sock,'PRIVMSG '+channel+' :Rolled a '+str(value)+' with a d'+str(sides),1)
		
		handled=True
	elif(cmd==(cmd_esc+'time')):
		tz=0
		if(line_post_cmd!=''):
			try:
				tz=float(line_post_cmd)
			except ValueError:
				py3queueln(sock,'PRIVMSG '+channel+' :Err: '+line_post_cmd+' is not a valid UTC-offset timezone; will give UTC time instead...',1)
		if(abs(tz)>24):
			py3queueln(sock,'PRIVMSG '+channel+' :Err: timezone offsets from utc cannot be outside the range [-24,24] because that makes no sense; giving UTC time...')
			tz=0
		current_time=time.asctime(time.gmtime(time.time()+(tz*60*60)))
		py3queueln(sock,'PRIVMSG '+channel+' :Current time is '+current_time+' (UTC '+('+'+str(tz) if tz>=0 else str(tz))+')')
		handled=True
	elif(cmd==(cmd_esc+'timecalc')):
		handle_timecalc(sock,cmd_esc,cmd,line_post_cmd,channel,is_pm)
		handled=True
	elif(cmd.startswith(cmd_esc)):
		try:
			#alternate conversion syntax
			#check if the "command" is a valid floating point number
			conv_arg=float(cmd[len(cmd_esc):])
			
			#the line after the "command" is the command checked against the conversion list
			#some arguments here are a little weird because they're being transposed
			found_conversion=False
			for conversion in unit_conv_list:
				#we found the requested conversion, so do the thing and output the result
				#note that "X to Y" gets translated here as "X->Y"
				if(conversion.chk_cmd(cmd_esc,cmd_esc+line_post_cmd.replace(' to ','->'))):
					conversion.output_conv(sock,channel,conv_arg)
					found_conversion=True
			
			#this was a valid number, but something went wrong during conversion
			if(not found_conversion):
				py3queueln(sock,'PRIVMSG '+channel+' :Err: Conversion not found '+line_post_cmd,1)
			
			#in any case if we got a number don't handle this line any more
			handled=True
		#the "command" wasn't a valid floating point number,
		#so output an error for PM, or just do nothing in a channel
		except ValueError:
			if(is_pm):
				py3queueln(sock,'PRIVMSG '+channel+' :Warn: Invalid command: \"'+cmd+'\"; see '+cmd_esc+'help for help',1)
		
		#this prevents the bot from learning from unrecognized ! commands
		#(which are usually meant for another bot)
#		handled=True
	#this was added at the request of NuclearWaffle, in an attempt, and I'm quoting here
	#to "f**k with Proview"
#	elif((len(cmd)>1) and odd_quest(cmd)):
#		output,dbg_str=markov.generate(state_change,use_pg=use_pg,db_login=db_login,back_gen=False)
#		
#		#prevent generating commands directed towards other bots,
#		#if configured to do that
#		if(not gen_cmd):
#			if(output.startswith('!')):
#				output='\\'+output
#		
#		py3queueln(sock,'PRIVMSG '+channel+' :'+output,1)
#		handled=True
	
	return (handled,dbg_str)