From 7e8bf6ab171830124e84af4484c383bac47b9bc6 Mon Sep 17 00:00:00 2001 From: James Lu Date: Mon, 5 Sep 2016 20:17:44 -0700 Subject: [PATCH] PkgInfo: add 'filesearch' for searching contents in Debian/Ubuntu --- PkgInfo/plugin.py | 45 ++++++++++++++++++++++++++++++++++++++++++++- PkgInfo/test.py | 5 ++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/PkgInfo/plugin.py b/PkgInfo/plugin.py index 1d9ad26..7d78031 100644 --- a/PkgInfo/plugin.py +++ b/PkgInfo/plugin.py @@ -102,6 +102,7 @@ addrs = {'ubuntu': 'http://packages.ubuntu.com/', 'debian': 'https://packages.debian.org/', # This site is very, VERY slow, but it still works.. 'debian-archive': 'http://archive.debian.net/'} +_normalize = lambda text: utils.str.normalizeWhitespace(text).strip() def _getDistro(release): """ @@ -169,7 +170,7 @@ class PkgInfo(callbacks.Plugin): irc.reply(err) return - # If we're using the --depends option, handle that separately. + # If we're using the --depends option, handle that separately. if 'depends' in opts: items = soup.find('div', {'id': 'pdeps'}).find_all('dt') # Store results by type and name, but in an ordered fashion: show dependencies first, @@ -390,6 +391,48 @@ class PkgInfo(callbacks.Plugin): pkgsearch = wrap(pkgsearch, ['somethingWithoutSpaces', 'somethingWithoutSpaces']) + @wrap(['somethingWithoutSpaces', 'somethingWithoutSpaces']) + def filesearch(self, irc, msg, args, release, query): + """ + + Searches what package in Debian or Ubuntu has which file. is the + codename/release name (e.g. xenial or jessie).""" + release = release.lower() + distro = _getDistro(release) + + try: + url = '%ssearch?keywords=%s&searchon=contents&suite=%s' % (addrs[distro], quote(query), quote(release)) + except KeyError: + irc.error(unknowndist, Raise=True) + + try: + fd = utils.web.getUrl(url).decode("utf-8") + except utils.web.Error as e: + irc.error(str(e), Raise=True) + + soup = BeautifulSoup(fd) + + results = [] + # Get results from table entries, minus the first one which is used for headings. + contentdiv = soup.find('div', attrs={'id': "pcontentsres"}) + if contentdiv: + for tr in contentdiv.find_all("tr")[1:]: + tds = tr.find_all('td') + try: + filename, packages = map(_normalize, [tds[0].get_text(), tds[1].get_text()]) + except IndexError: + continue + results.append('%s: %s' % (ircutils.bold(filename), packages)) + + if results: + irc.reply('; '.join(results)) + else: + try: + e = _normalize(soup.find("div", class_="perror").get_text()) + except AttributeError: + e = "No results found." + irc.error(e) + @wrap(['somethingWithoutSpaces', 'somethingWithoutSpaces', getopts({'exact': ''})]) diff --git a/PkgInfo/test.py b/PkgInfo/test.py index 76a60c9..78172a9 100644 --- a/PkgInfo/test.py +++ b/PkgInfo/test.py @@ -1,5 +1,5 @@ ### -# Copyright (c) 2014-2015, James Lu +# Copyright (c) 2014-2016, James Lu # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -67,6 +67,9 @@ class PkgInfoTestCase(PluginTestCase): def testPkgsearch(self): self.assertRegexp('pkgsearch debian python', 'python') + def testFilesearch(self): + self.assertRegexp('filesearch sid supybot', 'limnoria') + def testFedora(self): self.assertRegexp('fedora 22 bash*', 'bash') # Not found queries that don't have any wildcards in them