###
# Copyright (c) 2003-2005, James Vega
# Copyright (c) 2011, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import os
import re
import time
import urllib
import fnmatch
import bs4 as BeautifulSoup
import supybot.conf as conf
import supybot.utils as utils
import supybot.world as world
from supybot.commands import *
import supybot.plugins as plugins
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks
from supybot.utils.iter import all
class Debian(callbacks.Plugin):
threaded = True
_debreflags = re.DOTALL | re.MULTILINE
_deblistreFileExact = re.compile(r'([^<]+)',
_debreflags)
def file(self, irc, msg, args, optlist, filename):
"""[--exact] \
[--mode {path,filename,exactfilename}] \
[--branch {oldstable,stable,testing,unstable,experimental}] \
[--arch ] \
[--section {main,contrib,non-free}]
Returns the package(s) containing the .
--mode defaults to path, and defines how to search.
--branch defaults to stable, and defines in what branch to search."""
url = 'http://packages.debian.org/search?searchon=contents' + \
'&keywords=%(keywords)s&mode=%(mode)s&suite=%(suite)s' + \
'&arch=%(arch)s'
def reg(name):
return self.registryValue('defaults.file.%s' % name, msg.args[0])
args = {'keywords': None,
'mode': reg('mode'),
'suite': reg('branch'),
'section': reg('section'),
'arch': reg('arch')}
exact = ('exact', True) in optlist
for (key, value) in optlist:
if key == 'branch':
args['suite'] = value
elif key == 'section':
args['section'] = value
elif key == 'arch':
args['arch'] = value
elif key == 'mode':
args['mode'] = value
responses = []
if '*' in filename:
irc.error('Wildcard characters can not be specified.', Raise=True)
args['keywords'] = utils.web.urlquote(filename, '')
url %= args
try:
html = utils.web.getUrl(url).decode()
except utils.web.Error as e:
irc.error(format('I couldn\'t reach the search page (%s).', e),
Raise=True)
if 'is down at the moment' in html:
irc.error('Packages.debian.org is down at the moment. '
'Please try again later.', Raise=True)
step = 0
pkgs = []
for line in html.split('\n'):
if '' in line:
step += 1
elif step == 1 or (step >= 1 and not exact):
pkgs.extend(self._deblistreFileExact.findall(line))
if pkgs == []:
irc.reply(format('No filename found for %s (%s)',
utils.web.urlunquote(filename), args['suite']))
else:
# Filter duplicated
pkgs = dict(map(lambda x:(x, None), pkgs)).keys()
irc.reply(format('%i matches found: %s (%s)',
len(pkgs), '; '.join(pkgs), args['suite']))
file = wrap(file, [getopts({'exact': '',
'branch': ('literal', ('oldstable',
'stable',
'testing',
'unstable',
'experimental')),
'mode': ('literal', ('path',
'exactfilename',
'filename')),
'section': ('literal', ('main',
'contrib',
'non-free')),
'arch': 'somethingWithoutSpaces'}),
'text'])
_debreflags = re.DOTALL | re.IGNORECASE
_deblistreVersion = re.compile(r'Package ([^<]+)
(.*?)', _debreflags)
def version(self, irc, msg, args, optlist, package):
"""[--exact] \
[--searchon {names,all,sourcenames}] \
[--branch {oldstable,stable,testing,unstable,experimental}] \
[--section {main,contrib,non-free}]
Returns the current version(s) of the Debian package .
--exact, if given, means you want only the , and not
package names containing this name.
--searchon defaults to names, and defines where to search.
--branch defaults to all, and defines in what branch to search.
--section defaults to all, and defines in what section to search."""
url = 'http://packages.debian.org/search?keywords=%(keywords)s' + \
'&searchon=%(searchon)s&suite=%(suite)s§ion=%(section)s'
def reg(name):
return self.registryValue('defaults.version.%s' % name, msg.args[0])
args = {'keywords': None,
'searchon': reg('searchon'),
'suite': reg('branch'),
'section': reg('section')}
for (key, value) in optlist:
if key == 'exact':
url += '&exact=1'
elif key == 'branch':
args['suite'] = value
elif key == 'section':
args['section'] = value
elif key == 'searchon':
args['searchon'] = value
responses = []
if '*' in package:
irc.error('Wildcard characters can not be specified.', Raise=True)
args['keywords'] = utils.web.urlquote(package)
url %= args
try:
html = utils.web.getUrl(url).decode()
except utils.web.Error as e:
irc.error(format('I couldn\'t reach the search page (%s).', e),
Raise=True)
if 'is down at the moment' in html:
irc.error('Packages.debian.org is down at the moment. '
'Please try again later.', Raise=True)
pkgs = self._deblistreVersion.findall(html)
if not pkgs:
irc.reply(format('No package found for %s (%s)',
utils.web.urlunquote(package), args['suite']))
else:
for pkg in pkgs:
pkgMatch = pkg[0]
soup = BeautifulSoup.BeautifulSoup(pkg[1])
liBranches = soup.find_all('li')
branches = []
versions = []
def branchVers(br):
vers = [b.next.string.strip() for b in br]
return [utils.str.rsplit(v, ':', 1)[0] for v in vers]
for li in liBranches:
branches.append(li.a.string)
versions.append(branchVers(li.find_all('br')))
if branches and versions:
for pairs in zip(branches, versions):
branch = pairs[0]
ver = ', '.join(pairs[1])
s = format('%s (%s)', pkgMatch,
': '.join([branch, ver]))
responses.append(s)
resp = format('%i matches found: %s',
len(responses), '; '.join(responses))
irc.reply(resp)
version = wrap(version, [getopts({'exact': '',
'searchon': ('literal', ('names',
'all',
'sourcenames')),
'branch': ('literal', ('oldstable',
'stable',
'testing',
'unstable',
'experimental')),
'arch': ('literal', ('main',
'contrib',
'non-free'))}),
'text'])
_incomingRe = re.compile(r'', re.I)
def incoming(self, irc, msg, args, optlist, globs):
"""[--{regexp,arch} ] [ ...]
Checks debian incoming for a matching package name. The arch
parameter defaults to i386; --regexp returns only those package names
that match a given regexp, and normal matches use standard *nix
globbing.
"""
predicates = []
archPredicate = lambda s: ('_i386.' in s)
for (option, arg) in optlist:
if option == 'regexp':
predicates.append(r.search)
elif option == 'arch':
arg = '_%s.' % arg
archPredicate = lambda s, arg=arg: (arg in s)
predicates.append(archPredicate)
for glob in globs:
glob = fnmatch.translate(glob)
predicates.append(re.compile(glob).search)
packages = []
try:
fd = utils.web.getUrlFd('http://incoming.debian.org/')
except utils.web.Error as e:
irc.error(str(e), Raise=True)
for line in fd:
m = self._incomingRe.search(line.decode())
if m:
name = m.group(1)
if all(None, map(lambda p: p(name), predicates)):
realname = utils.str.rsplit(name, '_', 1)[0]
packages.append(realname)
if len(packages) == 0:
irc.error('No packages matched that search.')
else:
irc.reply(format('%L', packages))
incoming = thread(wrap(incoming,
[getopts({'regexp': 'regexpMatcher',
'arch': 'something'}),
any('glob')]))
def bold(self, s):
if self.registryValue('bold', dynamic.channel):
return ircutils.bold(s)
return s
_update = re.compile(r' : ([^<]+)