def ud(query, res): u = f'http://api.urbandictionary.com/v0/define?term={query}' r = requests.get(u, timeout=30) j = r.json()['list'][res] word = j['word'] definition = p_truncate(j['definition'], msg_len, 71, True) example = p_truncate(j['example'], msg_len, 15, True) author = j['author'] t_up = j['thumbs_up'] t_down = j['thumbs_down'] pl = j['permalink'].rsplit('/', 1)[0] return (word, definition, example, author, t_up, t_down, pl)
def mw_parse_section(url, section_list, page, sect, limit): ''' Uses the MediaWiki API:Parsing_wikitext#parse https://www.mediawiki.org/wiki/Special:MyLanguage/API:Parsing_wikitext#parse This function finds the position of the section ('sect') requested in 'section_list' and calls the MediaWiki API, which returns a JSON document containing the html of the requested section which is parsed by beautifulsoup4, limited to the specified amount of characters and returned. 'url' is the url of the MediaWiki website 'section_list' is the second item returned by mw_list_sections() 'page' should be the name of the MediaWiki article as returned by mw_opensearch() 'sect' is the section requested to be viewed 'limit' if True truncate the text ''' id_index = section_list[0].index(sect) u = (f'{url}/w/api.php' '?action=parse&format=json&prop=text' f'§ion={section_list[1][id_index]}&page={page}') r = requests.get(u, timeout=r_timeout) html = r.json()['parse']['text']['*'] soup = bs4.BeautifulSoup(html, bs4_parser) soup = text_cleanup(soup) text = soup.find('span', id=sect) text = text.find_next('p').text if limit: text = p_truncate(text, msg_len, 85, True) return text
def mw_parse_intro(url, page, limit): ''' Uses the MediaWiki API:Parsing_wikitext#parse https://www.mediawiki.org/wiki/Special:MyLanguage/API:Parsing_wikitext#parse This function calls the MediaWiki API, which returns a JSON document containing the html of the introduction section of an article, which is parsed by beautifulsoup4, limited to the specified amount of characters and returned. 'url' is the url of the MediaWiki website 'page' should be the name of the MediaWiki article as returned by mw_opensearch() 'limit' if True truncate the text ''' u = (f'{url}/w/api.php' f'?action=parse&format=json&prop=text§ion=0&page={page}') r = requests.get(u, timeout=r_timeout) html = r.json()['parse']['text']['*'] soup = bs4.BeautifulSoup(html, bs4_parser) soup = text_cleanup(soup) text = soup.find('p').text if text == 'Redirect to:': n_title = soup.find('a').text n_text = mw_parse_intro(url, n_title, limit) text = f'\x0302[Redirect to: {n_title}]\x0F {n_text}' if limit: text = p_truncate(text, msg_len, 85, True) return text
def main(i, irc): msgtarget = i.msg.get_msgtarget() nickname = i.msg.get_nickname() botcmd = i.msg.get_botcmd() prefix = i.msg.get_botcmd_prefix() args = i.msg.get_args() if not args: m = (f'Usage: {prefix}{botcmd} <Word> [-e <NUM>]') irc.out.notice(msgtarget, m) return argv = args.split() if '-e' in argv: idx = argv.index('-e') res = int(argv[idx + 1]) else: res = 1 q = search_query(argv) q_web = q.replace(" ", "_") url = f"https://en.wiktionary.org/wiki/{q_web}" result = wiktionary(url, res) result_length = len(result) if res not in range(1, result_length + 1): m = f'Wiktionary: No definition was found for "{q}" | {url}' irc.out.notice(msgtarget, m) return try: result = result[f"Etymology_{res}"] except KeyError: result = result["Etymology"] msg_len = (irc.msg_len - 9 - 8 - len(str(result_length)) - (len(result) * 5) - len(url)) p_tr_percent = 100 / len(result) txt = "" for part, cont in result.items(): rslt = f"{part}: {cont}" if nickname != msgtarget: rslt = p_truncate(rslt, msg_len, p_tr_percent, True) txt += f"{rslt} | " rpl = f"{q} | {txt}({result_length}) | {url}" irc.out.notice(msgtarget, rpl)
def main(i, irc): if not i.msg_nocmd: msg = (f'Usage: {i.cmd_prefix}{i.cmd} <Word> [-e <NUM>]') return irc.privmsg(i.channel, msg) args = i.msg_nocmd.split() if '-e' in args: idx = args.index('-e') res = int(args[idx + 1]) else: res = 1 q = query(args) q_web = q.replace(" ", "_") url = f"https://en.wiktionary.org/wiki/{q_web}" result = wiktionary(url, res) result_length = len(result) if res not in range(1, result_length + 1): msg = f'Wiktionary: No definition was found for "{q}" | {url}' return irc.privmsg(i.channel, msg) if res == 1: try: result = result["Etymology"] except KeyError: result = result["Etymology_1"] else: result = result[f"Etymology_{res}"] msg_len = (irc.var.msg_len - 9 - 8 - len(str(result_length)) - (len(result) * 5) - len(url)) p_tr_percent = 100 / len(result) txt = "" for part, cont in result.items(): rslt = f"{part}: {cont}" if not i.nickname == i.channel: rslt = p_truncate(rslt, msg_len, p_tr_percent, True) txt += f"{rslt} | " rpl = f"{q} | {txt}({result_length}) | {url}" irc.privmsg(i.channel, rpl)
def main(i, irc): sed_parse = re.compile('(?<!\\\\)/') sed_cmd = re.compile('^s/.*/.*') sed_out = '' if not sed_cmd.match(i.msg): write(i.varget, i.varset, i.channel, i.msg) return sed_args = sed_parse.split(i.msg) if len(sed_args) < 4: # check if the last / is missed etc. return msglist = read(i.varget, i.channel) # Extension to allow the user match previous messages. # It uses the special syntax: "s///-n" where n is the # number of matches to skip. # Sideffect: because it matches upto two decimals after -, # sed string positioning (or other commands # with decimals in them) should be issued # before the - command or two characters after # the - . # The following code is for parsing the command. It # edits the "goback" variable which will be used in the # loop below. # We use two decimals because the queue save upto 50 # messages. goback = False if '-' in sed_args[3]: s = sed_args[3] idx = s.index('-') if len(s[idx:]) > 2 and s[idx + 2].isdecimal(): goback = int(f'{s[idx + 1]}{s[idx + 2]}') sed_args[3] = f'{s[:idx]}{s[idx + 3:]}' elif len(s[idx:]) > 1 and s[idx + 1].isdecimal(): goback = int(s[idx + 1]) sed_args[3] = f'{s[:idx]}{s[idx + 2:]}' n = 1 while n <= 50: if 'i' in sed_args[3]: db_search = re.search(sed_args[1], msglist[-n], re.I) else: db_search = re.search(sed_args[1], msglist[-n]) if db_search: if goback: # Check if the goback command was issued. goback -= 1 n = n + 1 continue a = n break else: a = False n = n + 1 if a: if '\x01ACTION' in msglist[-a][:7]: msg_len = irc.var.msg_len - 9 - len(i.channel) - 10 - 2 sed_out = call_sed(msglist[-a][7:], sed_args) sed_out = sed_out.rstrip('\n').replace('\x01', "").replace('\ca', "") sed_out = p_truncate(sed_out, msg_len, 98, True) irc.privmsg(i.channel, f'\x01ACTION {sed_out}') else: msg_len = irc.var.msg_len - 9 - len(i.channel) - 2 sed_out = call_sed(msglist[-a], sed_args).strip() sed_out = sed_out.rstrip('\n').replace('\x01', "").replace('\ca', "") sed_out = p_truncate(sed_out, msg_len, 98, True) irc.privmsg(i.channel, sed_out) if sed_out: # We try to limit the string saved in the queue to avoid: # OSError: [Errno 7] Argument list too long: 'echo' # when calling 'echo' in @call_sed . # 512 chars are more than enough, since the bot will # never be able to send a message with that many. write(i.varget, i.varset, i.channel, sed_out)
def main(i, irc): nickname = i.msg.get_nickname() msgtarget = i.msg.get_msgtarget() text = i.msg.get_text() if not sed_cmd.match(text): write(i.varget, i.varset, msgtarget, text) return sed_out = "" sed_args = sed_parse.split(text) if len(sed_args) < 4: # check if the last / is missed etc. return msglist = read(i.varget, msgtarget) # Extension to allow the user match previous messages. # It uses the special syntax: "s///-n" where n is the # number of matches to skip. # Sideffect: because it matches upto two decimals after -, # sed string positioning (or other commands # with decimals in them) should be issued # before the - command or two characters after # the - . # The following code is for parsing the command. It # edits the "goback" variable which will be used in the # loop below. # We use two decimals because the queue save upto 50 # messages. goback = False if '-' in sed_args[3]: s = sed_args[3] idx = s.index('-') if len(s[idx:]) > 2 and s[idx + 2].isdecimal(): goback = int(f'{s[idx + 1]}{s[idx + 2]}') sed_args[3] = f'{s[:idx]}{s[idx + 3:]}' elif len(s[idx:]) > 1 and s[idx + 1].isdecimal(): goback = int(s[idx + 1]) sed_args[3] = f'{s[:idx]}{s[idx + 2:]}' n = 1 while n <= 50: flags = 0 if 'i' in sed_args[3]: flags |= re.I try: db_search = re.search(sed_args[1], msglist[-n], flags) except re.error as e: # Invalid pattern given irc.out.notice(nickname, f"sed: regexp error: {e}") return if db_search: if goback: # Check if the goback command was issued. goback -= 1 n = n + 1 continue a = n break else: a = False n = n + 1 if a: if "\x01ACTION " in msglist[-a][:8]: msg_len = irc.msg_len - 9 - len(msgtarget) - 10 - 2 sed_out = call_sed(msglist[-a][8:], sed_args).strip() sed_out = sed_out.rstrip('\n').replace('\x01', "") sed_out = p_truncate(sed_out, msg_len, 98, True) irc.out.privmsg(msgtarget, f"\x01ACTION {sed_out}\x01") else: msg_len = irc.msg_len - 9 - len(msgtarget) - 2 sed_out = call_sed(msglist[-a], sed_args).strip() sed_out = sed_out.rstrip('\n').replace('\x01', "") sed_out = p_truncate(sed_out, msg_len, 98, True) irc.out.privmsg(msgtarget, sed_out) if sed_out: # We try to limit the string saved in the queue to avoid: # OSError: [Errno 7] Argument list too long: 'echo' # when calling 'echo' in @call_sed . # 512 chars are more than enough, since the bot will # never be able to send a message with that many. write(i.varget, i.varset, msgtarget, sed_out)