PackageInfo: General overhaul.
* Add full support for Debian releases. * Unify and simplify piping and redirection. * Various general and minor improvements. * Switch architecture for infos to amd64. * Update default configuration. * Improve APT update scripts.
This commit is contained in:
parent
4956995f9a
commit
398247f0dd
|
@ -20,10 +20,10 @@ deb-src http://archive.ubuntu.com/ubuntu lucid main restricted universe multiver
|
||||||
|
|
||||||
supybot.plugins.PackageInfo.defaultRelease:
|
supybot.plugins.PackageInfo.defaultRelease:
|
||||||
Set this to the default release to use when none is specified. (Channel)
|
Set this to the default release to use when none is specified. (Channel)
|
||||||
Default: 'lucid'
|
Default: 'zesty'
|
||||||
|
|
||||||
Whenever you create a new .list file, it is important to run the update_apt
|
Whenever you create a new .list file, it is important to run the update_apt
|
||||||
and update_apt_file scripts that comes with this plugin. Before you run these,
|
and update_apt_file scripts that come with this plugin. Before you run these,
|
||||||
you have to edit them to point to your apt dir. It's also useful to run them
|
you have to edit them to point to your apt dir. It's also useful to run them
|
||||||
periodically from cron (say, once per week for update_apt and once per moth for
|
periodically from cron (say, once per week for update_apt and once per moth for
|
||||||
update_apt_file). You also need to reload the plugin to make it pick up the new
|
update_apt_file). You also need to reload the plugin to make it pick up the new
|
||||||
|
@ -39,11 +39,14 @@ Default: !
|
||||||
|
|
||||||
--Usage--
|
--Usage--
|
||||||
find <package/filename> [<release>]
|
find <package/filename> [<release>]
|
||||||
Search for <package> or, of that fails, find <filename>'s package(s).
|
Search for <package> or, if that fails, <filename> in packages,
|
||||||
Optionally in <release>
|
optionally in <release>
|
||||||
|
|
||||||
info <package> [<release>]
|
info <package> [<release>]
|
||||||
Lookup information for <package>, optionally in <release>
|
Look up information for <package>, optionally in <release>
|
||||||
|
|
||||||
if supybot.plugins.PackageInfo.enabled is True the bot will also reply to
|
depends <package> [<release>]
|
||||||
|
Look up dependencies for <package>, optionally in <release>
|
||||||
|
|
||||||
|
If supybot.plugins.PackageInfo.enabled is True the bot will also reply to
|
||||||
the commands if prefixed with supybot.plugins.PackageInfo.prefixchar.
|
the commands if prefixed with supybot.plugins.PackageInfo.prefixchar.
|
||||||
|
|
|
@ -22,7 +22,7 @@ import supybot
|
||||||
import supybot.world as world
|
import supybot.world as world
|
||||||
from imp import reload
|
from imp import reload
|
||||||
|
|
||||||
__version__ = "1.1.0"
|
__version__ = "1.2.0"
|
||||||
__author__ = supybot.Author("Krytarik Raido", "krytarik", "krytarik@tuxgarage.com")
|
__author__ = supybot.Author("Krytarik Raido", "krytarik", "krytarik@tuxgarage.com")
|
||||||
__contributors__ = {
|
__contributors__ = {
|
||||||
supybot.Author("Dennis Kaarsemaker", "Seveas", "dennis@kaarsemaker.net"): ['Original Concept'],
|
supybot.Author("Dennis Kaarsemaker", "Seveas", "dennis@kaarsemaker.net"): ['Original Concept'],
|
||||||
|
|
|
@ -18,15 +18,24 @@ import supybot.conf as conf
|
||||||
import supybot.registry as registry
|
import supybot.registry as registry
|
||||||
|
|
||||||
def configure(advanced):
|
def configure(advanced):
|
||||||
# This will be called by supybot to configure this module. advanced is
|
# This will be called by Supybot to configure this module. advanced is
|
||||||
# a bool that specifies whether the user identified himself as an advanced
|
# a bool that specifies whether the user identified himself as an advanced
|
||||||
# user or not. You should effect your configuration by manipulating the
|
# user or not. You should affect your configuration by manipulating the
|
||||||
# registry as appropriate.
|
# registry as appropriate.
|
||||||
def makeSource(release):
|
def makeSourceUbuntu(release):
|
||||||
return """deb http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
return """deb http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||||
deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||||
""" % (release, release)
|
""" % (release, release)
|
||||||
#"""
|
|
||||||
|
def makeSourceDebian(release):
|
||||||
|
return """deb http://deb.debian.org/debian/ %s main contrib non-free
|
||||||
|
deb-src deb http://deb.debian.org/debian/ %s main contrib non-free
|
||||||
|
""" % (release, release)
|
||||||
|
|
||||||
|
def makeSourceDebianSec(release):
|
||||||
|
return """deb http://security.debian.org/ %s/updates main contrib non-free
|
||||||
|
deb-src deb http://security.debian.org/ %s/updates main contrib non-free
|
||||||
|
""" % (release, release)
|
||||||
|
|
||||||
from supybot.questions import output, expect, something, yn
|
from supybot.questions import output, expect, something, yn
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -42,13 +51,13 @@ deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||||
enabled = yn("Enable this plugin in all channels?", default=True)
|
enabled = yn("Enable this plugin in all channels?", default=True)
|
||||||
|
|
||||||
if enabled and advanced:
|
if enabled and advanced:
|
||||||
prefixchar = something("Which prefix character should be bot respond to?", default=PackageInfo.prefixchar._default)
|
prefixchar = something("Which prefix character should the bot respond to?", default=PackageInfo.prefixchar._default)
|
||||||
defaultRelease = something("What should be the default distrobution when not specified?", default=PackageInfo.defaultRelease._default)
|
defaultRelease = something("What should be the default release when none is specified?", default=PackageInfo.defaultRelease._default)
|
||||||
aptdir = something("Which directory should be used for the apt cache when looking up packages?", default=PackageInfo.aptdir._default)
|
aptdir = something("Which directory should be used for the apt cache when looking up packages?", default=PackageInfo.aptdir._default)
|
||||||
|
|
||||||
# People tend to thing this should be /var/cache/apt
|
# People tend to think this should be /var/cache/apt
|
||||||
while aptdir.startswith('/var'): #NOTE: This is not a good hack. Maybe just blacklist /var/cache/apt (or use apt to report back the cache dir)
|
while aptdir.startswith('/var'): #NOTE: This is not a good hack. Maybe just blacklist /var/cache/apt (or use apt to report back the cache dir)
|
||||||
output("NO! Do not use your systems apt directory")
|
output("NO! Do not use your system's apt directory")
|
||||||
aptdir = something("Which directory should be used for the apt cache when looking up packages?", default=PackageInfo.aptdir._default)
|
aptdir = something("Which directory should be used for the apt cache when looking up packages?", default=PackageInfo.aptdir._default)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -62,7 +71,8 @@ deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||||
PackageInfo.prefixchar.setValue(prefixchar)
|
PackageInfo.prefixchar.setValue(prefixchar)
|
||||||
PackageInfo.defaultRelease.setValue(defaultRelease)
|
PackageInfo.defaultRelease.setValue(defaultRelease)
|
||||||
|
|
||||||
default_dists = set(['dapper', 'hardy', 'lucid', 'maveric', 'natty', 'oneiric'])
|
default_dists = set(['precise', 'trusty', 'xenial', 'yakkety', 'zesty', 'artful',
|
||||||
|
'oldstable', 'stable', 'unstable', 'testing', 'experimental'])
|
||||||
pluginDir = os.path.abspath(os.path.dirname(__file__))
|
pluginDir = os.path.abspath(os.path.dirname(__file__))
|
||||||
update_apt = os.path.join(pluginDir, 'update_apt')
|
update_apt = os.path.join(pluginDir, 'update_apt')
|
||||||
update_apt_file = os.path.join(pluginDir, 'update_apt_file')
|
update_apt_file = os.path.join(pluginDir, 'update_apt_file')
|
||||||
|
@ -72,7 +82,7 @@ deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||||
## Create the aptdir
|
## Create the aptdir
|
||||||
try:
|
try:
|
||||||
os.makedirs(aptdir)
|
os.makedirs(aptdir)
|
||||||
except OSError: # The error number would be OS dependant (17 on Linux 2.6, ?? on others). So just pass on this
|
except OSError: # The error number would be OS dependent (17 on Linux 2.6, ?? on others). So just pass on this
|
||||||
pass
|
pass
|
||||||
|
|
||||||
for release in default_dists:
|
for release in default_dists:
|
||||||
|
@ -80,19 +90,31 @@ deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||||
try:
|
try:
|
||||||
output("Creating %s" % filename)
|
output("Creating %s" % filename)
|
||||||
fd = open(filename, 'wb')
|
fd = open(filename, 'wb')
|
||||||
fd.write("# Apt sources list for Ubuntu %s\n" % release)
|
fd.write("# Apt sources list for %s\n" % release)
|
||||||
fd.write(makeSource(release))
|
if release in ('oldstable', 'stable', 'unstable', 'testing', 'experimental'):
|
||||||
fd.write(makeSource(release + '-security'))
|
fd.write(makeSourceDebian(release))
|
||||||
fd.write(makeSource(release + '-updates'))
|
if release in ('oldstable', 'stable', 'testing'):
|
||||||
|
fd.write(makeSourceDebian(release + '-updates'))
|
||||||
|
fd.write(makeSourceDebianSec(release))
|
||||||
|
else:
|
||||||
|
fd.write(makeSourceUbuntu(release))
|
||||||
|
fd.write(makeSourceUbuntu(release + '-updates'))
|
||||||
|
fd.write(makeSourceUbuntu(release + '-security'))
|
||||||
fd.close()
|
fd.close()
|
||||||
|
|
||||||
|
if release in ('unstable', 'experimental'):
|
||||||
|
continue
|
||||||
|
|
||||||
for sub in ('backports', 'proposed'):
|
for sub in ('backports', 'proposed'):
|
||||||
sub_release = "%s-%s" % (release, sub)
|
sub_release = "%s-%s" % (release, sub)
|
||||||
filename = os.path.join(aptdir, "%s.list" % sub_release)
|
filename = os.path.join(aptdir, "%s.list" % sub_release)
|
||||||
output("Creating %s" % filename)
|
output("Creating %s" % filename)
|
||||||
fd = open(filename, 'wb')
|
fd = open(filename, 'wb')
|
||||||
fd.write("# Apt sources list for Ubuntu %s\n" % release)
|
fd.write("# Apt sources list for %s\n" % sub_release)
|
||||||
fd.write(makeSource(sub_release))
|
if release in ('oldstable', 'stable', 'testing'):
|
||||||
|
fd.write(makeSourceDebian(sub_release.replace('proposed', 'proposed-updates')))
|
||||||
|
else:
|
||||||
|
fd.write(makeSourceUbuntu(sub_release))
|
||||||
fd.close()
|
fd.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
output("Error writing to %r: %r (%s)" % (filename, str(e), type(e)))
|
output("Error writing to %r: %r (%s)" % (filename, str(e), type(e)))
|
||||||
|
@ -116,7 +138,7 @@ conf.registerChannelValue(PackageInfo, 'enabled',
|
||||||
conf.registerChannelValue(PackageInfo, 'prefixchar',
|
conf.registerChannelValue(PackageInfo, 'prefixchar',
|
||||||
conf.ValidPrefixChars('!', "Character the bot will respond to"))
|
conf.ValidPrefixChars('!', "Character the bot will respond to"))
|
||||||
conf.registerChannelValue(PackageInfo, 'defaultRelease',
|
conf.registerChannelValue(PackageInfo, 'defaultRelease',
|
||||||
registry.String('natty', "Default release to use when none is specified"))
|
registry.String('zesty', "Default release to use when none is specified"))
|
||||||
conf.registerGlobalValue(PackageInfo, 'aptdir',
|
conf.registerGlobalValue(PackageInfo, 'aptdir',
|
||||||
conf.Directory(conf.supybot.directories.data.dirize('aptdir'), "Path to the apt directory", private=True))
|
conf.Directory(conf.supybot.directories.data.dirize('aptdir'), "Path to the apt directory", private=True))
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- Encoding: utf-8 -*-
|
# -*- Encoding: utf-8 -*-
|
||||||
###
|
###
|
||||||
# Copyright (c) 2006-2007 Dennis Kaarsemaker
|
# Copyright (c) 2006-2007 Dennis Kaarsemaker
|
||||||
|
@ -18,38 +17,39 @@
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning)
|
warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning)
|
||||||
import subprocess, os, apt
|
import subprocess, os, apt, re
|
||||||
import supybot.utils as utils
|
import supybot.utils as utils
|
||||||
from email.parser import FeedParser
|
from email.parser import FeedParser
|
||||||
|
|
||||||
def component(arg):
|
def component(arg):
|
||||||
if '/' in arg: return arg[:arg.find('/')]
|
if '/' in arg:
|
||||||
|
return arg[:arg.find('/')]
|
||||||
return 'main'
|
return 'main'
|
||||||
|
|
||||||
def description(pkg):
|
def description(pkg):
|
||||||
if not pkg:
|
|
||||||
return None
|
|
||||||
if 'Description-en' in pkg:
|
if 'Description-en' in pkg:
|
||||||
return pkg['Description-en'].split('\n')[0]
|
return pkg['Description-en'].split('\n')[0]
|
||||||
elif 'Description' in pkg:
|
elif 'Description' in pkg:
|
||||||
return pkg['Description'].split('\n')[0]
|
return pkg['Description'].split('\n')[0]
|
||||||
return None
|
return "Description not available"
|
||||||
|
|
||||||
def apt_cache(aptdir, distro, extra):
|
def apt_cache(aptdir, distro, cmd, pkg):
|
||||||
return subprocess.check_output(['apt-cache',
|
return subprocess.check_output(['apt-cache',
|
||||||
|
'-oAPT::Architecture=amd64',
|
||||||
|
'-oAPT::Architectures::=i386',
|
||||||
|
'-oAPT::Architectures::=amd64',
|
||||||
'-oDir::State::Lists=%s/%s' % (aptdir, distro),
|
'-oDir::State::Lists=%s/%s' % (aptdir, distro),
|
||||||
'-oDir::State::Status=%s/%s.status' % (aptdir, distro),
|
'-oDir::State::Status=%s/%s.status' % (aptdir, distro),
|
||||||
'-oDir::Etc::SourceList=%s/%s.list' % (aptdir, distro),
|
'-oDir::Etc::SourceList=%s/%s.list' % (aptdir, distro),
|
||||||
'-oDir::Etc::SourceParts=""',
|
'-oDir::Etc::SourceParts=""',
|
||||||
'-oDir::Cache=%s/cache' % aptdir,
|
'-oDir::Cache=%s/cache' % aptdir] +
|
||||||
'-oAPT::Architecture=i386'] +
|
cmd + [pkg.lower()]).decode('utf8')
|
||||||
extra).decode('utf8')
|
|
||||||
|
|
||||||
def apt_file(aptdir, distro, pkg):
|
def apt_file(aptdir, distro, pkg):
|
||||||
return subprocess.check_output(['apt-file',
|
return subprocess.check_output(['apt-file',
|
||||||
'-s', '%s/%s.list' % (aptdir, distro),
|
'-s', '%s/%s.list' % (aptdir, distro),
|
||||||
'-c', '%s/apt-file/%s' % (aptdir, distro),
|
'-c', '%s/apt-file/%s' % (aptdir, distro),
|
||||||
'-l', '-a', 'i386',
|
'-l', '-i', '-a', 'amd64',
|
||||||
'search', pkg]).decode('utf8')
|
'search', pkg]).decode('utf8')
|
||||||
|
|
||||||
class Apt:
|
class Apt:
|
||||||
|
@ -62,19 +62,22 @@ class Apt:
|
||||||
if self.aptdir:
|
if self.aptdir:
|
||||||
self.distros = sorted([x[:-5] for x in os.listdir(self.aptdir) if x.endswith('.list')])
|
self.distros = sorted([x[:-5] for x in os.listdir(self.aptdir) if x.endswith('.list')])
|
||||||
|
|
||||||
def find(self, pkg, chkdistro, filelookup=True):
|
def _parse(self, pkg):
|
||||||
_pkg = ''.join([x for x in pkg.strip().split(None,1)[0] if x.isalnum() or x in '.-_+/'])
|
parser = FeedParser()
|
||||||
distro = ''
|
parser.feed(pkg)
|
||||||
if len(pkg.strip().split()) > 1:
|
return parser.close()
|
||||||
distro = ''.join([x for x in pkg.strip().split(None,2)[1] if x.isalnum() or x in '.-_+'])
|
|
||||||
if not distro:
|
def find(self, pkg, distro, filelookup=True):
|
||||||
distro = chkdistro
|
|
||||||
if distro not in self.distros:
|
if distro not in self.distros:
|
||||||
return "%s is not a valid distribution: %s" % (distro, ", ".join(self.distros))
|
return "%r is not a valid release: %s" % (distro, ", ".join(self.distros))
|
||||||
pkg = _pkg
|
|
||||||
|
if distro.split('-')[0] in ('oldstable', 'stable', 'unstable', 'testing', 'experimental'):
|
||||||
|
pkgTracURL = "https://packages.debian.org"
|
||||||
|
else:
|
||||||
|
pkgTracURL = "https://packages.ubuntu.com"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = apt_cache(self.aptdir, distro, ['search', '-n', pkg])
|
data = apt_cache(self.aptdir, distro, ['search', '-n'], pkg)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
data = e.output
|
data = e.output
|
||||||
if not data:
|
if not data:
|
||||||
|
@ -85,111 +88,81 @@ class Apt:
|
||||||
data = e.output
|
data = e.output
|
||||||
if data:
|
if data:
|
||||||
if data[0] == 'sh:': # apt-file isn't installed
|
if data[0] == 'sh:': # apt-file isn't installed
|
||||||
self.log.error("PackageInfo/packages: apt-file is not installed")
|
self.log.error("PackageInfo/packages: apt-file is not installed")
|
||||||
return "Please use http://packages.ubuntu.com/ to search for files"
|
return "Please use %s/ to search for files" % pkgTracURL
|
||||||
if data[0] == 'E:': # No files in the cache dir
|
if data[0] == 'E:': # No files in the cache dir
|
||||||
self.log.error("PackageInfo/packages: Please run the 'update_apt_file' script")
|
self.log.error("PackageInfo/packages: Please run the 'update_apt_file' script")
|
||||||
return "Cache out of date, please contact the administrator"
|
return "Cache out of date, please contact the administrator"
|
||||||
if data[0] == "Use" and data[1] == "of":
|
if data[0] == "Use" and data[1] == "of":
|
||||||
url = "http://packages.ubuntu.com/search?searchon=contents&keywords=%s&mode=&suite=%s&arch=any" % (utils.web.urlquote(pkg), distro)
|
return "%s/search?searchon=contents&keywords=%s&mode=exactfilename&suite=%s&arch=any" % (pkgTracURL, utils.web.urlquote(pkg), distro)
|
||||||
return url
|
|
||||||
if len(data) > 10:
|
if len(data) > 10:
|
||||||
return "File %s found in %s (and %d others) http://packages.ubuntu.com/search?searchon=contents&keywords=%s&mode=&suite=%s&arch=any" % (pkg, ', '.join(data[:10]), len(data)-10, utils.web.urlquote(pkg), distro)
|
return "File %s found in %s and %d others <%s/search?searchon=contents&keywords=%s&mode=exactfilename&suite=%s&arch=any>" % (pkg, ', '.join(data[:10]), len(data)-10, pkgTracURL, utils.web.urlquote(pkg), distro)
|
||||||
return "File %s found in %s" % (pkg, ', '.join(data))
|
return "File %s found in %s" % (pkg, ', '.join(data))
|
||||||
return 'Package/file %s does not exist in %s' % (pkg, distro)
|
return 'Package/file %s does not exist in %s' % (pkg, distro)
|
||||||
return "No packages matching '%s' could be found" % pkg
|
return "No packages matching '%s' could be found" % pkg
|
||||||
pkgs = [x.split()[0] for x in data.split('\n') if x]
|
pkgs = [x.split()[0] for x in data.split('\n') if x]
|
||||||
if len(pkgs) > 10:
|
if len(pkgs) > 10:
|
||||||
return "Found: %s (and %d others) http://packages.ubuntu.com/search?keywords=%s&searchon=names&suite=%s§ion=all" % (', '.join(pkgs[:10]), len(pkgs)-10, utils.web.urlquote(pkg), distro)
|
return "Found: %s and %d others <%s/search?keywords=%s&searchon=names&suite=%s§ion=all>" % (', '.join(pkgs[:10]), len(pkgs)-10, pkgTracURL, utils.web.urlquote(pkg), distro)
|
||||||
else:
|
else:
|
||||||
return "Found: %s" % ', '.join(pkgs[:5])
|
return "Found: %s" % ', '.join(pkgs[:5])
|
||||||
|
|
||||||
def raw_info(self, pkg, chkdistro):
|
def raw_info(self, pkg, distro, archlookup=True):
|
||||||
if not pkg.strip():
|
|
||||||
return ''
|
|
||||||
_pkg = ''.join([x for x in pkg.strip().split(None,1)[0] if x.isalnum() or x in '.-_+'])
|
|
||||||
distro = chkdistro
|
|
||||||
if len(pkg.strip().split()) > 1:
|
|
||||||
distro = ''.join([x for x in pkg.strip().split(None,2)[1] if x.isalnum() or x in '-._+'])
|
|
||||||
if distro not in self.distros:
|
if distro not in self.distros:
|
||||||
return "%r is not a valid distribution: %s" % (distro, ", ".join(self.distros))
|
return "%r is not a valid release: %s" % (distro, ", ".join(self.distros))
|
||||||
|
|
||||||
pkg = _pkg
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = apt_cache(self.aptdir, distro, ['show', pkg])
|
data = apt_cache(self.aptdir, distro, ['show'], pkg)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
data = e.output
|
data = e.output
|
||||||
try:
|
|
||||||
data2 = apt_cache(self.aptdir, distro, ['showsrc', pkg])
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
data2 = e.output
|
|
||||||
if not data or 'E: No packages found' in data:
|
if not data or 'E: No packages found' in data:
|
||||||
return 'Package %s does not exist in %s' % (pkg, distro)
|
return 'Package %s does not exist in %s' % (pkg, distro)
|
||||||
|
|
||||||
maxp = {'Version': '0~'}
|
maxp = {'Version': '0~'}
|
||||||
packages = [x.strip() for x in data.split('\n\n')]
|
packages = list(map(self._parse, [x for x in data.split('\n\n') if x]))
|
||||||
for p in packages:
|
for p in packages:
|
||||||
if not p.strip():
|
|
||||||
continue
|
|
||||||
parser = FeedParser()
|
|
||||||
parser.feed(p)
|
|
||||||
p = parser.close()
|
|
||||||
if type(p) == type(""):
|
|
||||||
self.log.error("PackageInfo/packages: apt returned an error, do you have the deb-src URLs in %s.list?" % distro)
|
|
||||||
return "Package lookup faild"
|
|
||||||
if not p.get("Version", None):
|
|
||||||
continue
|
|
||||||
if apt.apt_pkg.version_compare(maxp['Version'], p['Version']) <= 0:
|
if apt.apt_pkg.version_compare(maxp['Version'], p['Version']) <= 0:
|
||||||
maxp = p
|
maxp = p
|
||||||
del parser
|
|
||||||
|
if not archlookup:
|
||||||
|
return maxp
|
||||||
|
|
||||||
|
try:
|
||||||
|
data2 = apt_cache(self.aptdir, distro, ['showsrc'], pkg)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
return maxp
|
||||||
|
|
||||||
maxp2 = {'Version': '0~'}
|
maxp2 = {'Version': '0~'}
|
||||||
packages2 = [x.strip() for x in data2.split('\n\n')]
|
packages2 = list(map(self._parse, [x for x in data2.split('\n\n') if x]))
|
||||||
for p in packages2:
|
for p in packages2:
|
||||||
if not p.strip():
|
|
||||||
continue
|
|
||||||
parser = FeedParser()
|
|
||||||
parser.feed(p)
|
|
||||||
p = parser.close()
|
|
||||||
if type(p) == type(""):
|
|
||||||
self.log.error("PackageInfo/packages: apt returned an error, do you have the deb-src URLs in %s.list?" % distro)
|
|
||||||
return "Package lookup faild"
|
|
||||||
if not p['Version']:
|
|
||||||
continue
|
|
||||||
if apt.apt_pkg.version_compare(maxp2['Version'], p['Version']) <= 0:
|
if apt.apt_pkg.version_compare(maxp2['Version'], p['Version']) <= 0:
|
||||||
maxp2 = p
|
maxp2 = p
|
||||||
del parser
|
|
||||||
archs = ''
|
|
||||||
if 'Architecture' in maxp2:
|
|
||||||
archs = [_.strip() for _ in maxp2['Architecture'].split() if _.strip()]
|
|
||||||
for arch in archs:
|
|
||||||
if arch not in ('any', 'all'):
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
archs = ''
|
|
||||||
break
|
|
||||||
|
|
||||||
if archs:
|
archs = re.match(r'.*^ %s \S+ \S+ \S+ arch=(?P<arch>\S+)$' % re.escape(pkg), maxp2['Package-List'],
|
||||||
archs = ' (Only available for %s)' % '; '.join(archs)
|
re.I | re.M | re.DOTALL)
|
||||||
|
if archs:
|
||||||
|
archs = archs.group('arch').split(',')
|
||||||
|
if not ('any' in archs or 'all' in archs):
|
||||||
|
maxp['Architectures'] = ', '.join(archs)
|
||||||
|
|
||||||
maxp["Distribution"] = distro
|
|
||||||
maxp["Architectures"] = archs
|
|
||||||
return maxp
|
return maxp
|
||||||
|
|
||||||
def info(self, pkg, chkdistro):
|
def info(self, pkg, distro):
|
||||||
maxp = self.raw_info(pkg, chkdistro)
|
maxp = self.raw_info(pkg, distro)
|
||||||
if isinstance(maxp, str):
|
if isinstance(maxp, str):
|
||||||
return maxp
|
return maxp
|
||||||
return("%s (source: %s): %s. In component %s, is %s. Version %s (%s), package size %s kB, installed size %s kB%s" %
|
return("%s (source: %s): %s. In component %s, is %s. Version %s (%s), package size %s kB, installed size %s kB%s" %
|
||||||
(maxp['Package'], maxp['Source'] or maxp['Package'], description(maxp), component(maxp['Section']),
|
(maxp['Package'], maxp.get('Source', None) or maxp['Package'], description(maxp), component(maxp['Section']),
|
||||||
maxp['Priority'], maxp['Version'], maxp["Distribution"], int(maxp['Size'])/1024, maxp['Installed-Size'], maxp["Architectures"]))
|
maxp['Priority'], maxp['Version'], distro, int(maxp['Size'])/1024, maxp['Installed-Size'],
|
||||||
|
". (Only available for %s)" % maxp['Architectures'] if maxp.get('Architectures', None) else ""))
|
||||||
|
|
||||||
def depends(self, pkg, chkdistro):
|
def depends(self, pkg, distro):
|
||||||
maxp = self.raw_info(pkg, chkdistro)
|
maxp = self.raw_info(pkg, distro, archlookup=False)
|
||||||
if isinstance(maxp, str):
|
if isinstance(maxp, str):
|
||||||
return maxp
|
return maxp
|
||||||
return("%s (version %s in %s) depends on: %s" %
|
return("%s (version: %s, %s): Depends on %s%s" %
|
||||||
(maxp['Package'], maxp["Version"], maxp["Distribution"], maxp["Depends"]))
|
(maxp['Package'], maxp['Version'], distro, maxp.get('Depends', None) or "nothing",
|
||||||
|
". Recommends %s" % maxp['Recommends'] if maxp.get('Recommends', None) else ""))
|
||||||
|
|
||||||
# Simple test
|
# Simple test
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
|
@ -210,21 +183,14 @@ if __name__ == "__main__":
|
||||||
def registryValue(self, *args, **kwargs):
|
def registryValue(self, *args, **kwargs):
|
||||||
return "/home/bot/aptdir"
|
return "/home/bot/aptdir"
|
||||||
|
|
||||||
command = argv[1].split(None, 1)[0]
|
|
||||||
try:
|
try:
|
||||||
lookup = argv[1].split(None, 1)[1]
|
(command, lookup) = argv[1].split(None, 1)
|
||||||
except:
|
except:
|
||||||
print("Need something to lookup")
|
print("Need something to look up")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
dists = "hardy"
|
dist = "zesty"
|
||||||
if argc == 3:
|
if argc == 3:
|
||||||
dists = argv[2]
|
dist = argv[2]
|
||||||
plugin = FakePlugin()
|
plugin = FakePlugin()
|
||||||
aptlookup = Apt(plugin)
|
aptlookup = Apt(plugin)
|
||||||
if command == "find":
|
print(getattr(aptlookup, command)(lookup, dist))
|
||||||
print(aptlookup.find(lookup, dists))
|
|
||||||
elif command == "depends":
|
|
||||||
print(aptlookup.depends(lookup, dists))
|
|
||||||
else:
|
|
||||||
print(aptlookup.info(lookup, dists))
|
|
||||||
|
|
||||||
|
|
|
@ -14,69 +14,79 @@
|
||||||
#
|
#
|
||||||
###
|
###
|
||||||
|
|
||||||
import supybot.utils as utils
|
|
||||||
from supybot.commands import *
|
from supybot.commands import *
|
||||||
import supybot.plugins as plugins
|
import supybot.utils as utils
|
||||||
import supybot.ircutils as ircutils
|
import supybot.ircutils as ircutils
|
||||||
import supybot.ircmsgs as ircmsgs
|
import supybot.ircmsgs as ircmsgs
|
||||||
import supybot.callbacks as callbacks
|
|
||||||
import supybot.ircutils as ircutils
|
|
||||||
import supybot.ircdb as ircdb
|
import supybot.ircdb as ircdb
|
||||||
|
import supybot.callbacks as callbacks
|
||||||
import supybot.conf as conf
|
import supybot.conf as conf
|
||||||
import os
|
import re, time
|
||||||
import re
|
|
||||||
import time
|
|
||||||
from . import packages
|
from . import packages
|
||||||
|
|
||||||
def get_user(msg):
|
|
||||||
try:
|
|
||||||
user = ircdb.users.getUser(msg.prefix)
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
return user
|
|
||||||
|
|
||||||
_stripNickChars = """!"#$%&'()*+,./:;<=>?@~"""
|
_stripNickChars = """!"#$%&'()*+,./:;<=>?@~"""
|
||||||
def stripNick(nick):
|
def stripNick(nick):
|
||||||
while nick and nick[-1] in _stripNickChars:
|
while nick and nick[-1] in _stripNickChars:
|
||||||
nick = nick[:-1]
|
nick = nick[:-1]
|
||||||
return nick
|
return nick
|
||||||
|
|
||||||
|
def defaultIgnored(hostmask, recipient):
|
||||||
|
if not conf.supybot.defaultIgnore():
|
||||||
|
return False
|
||||||
|
if conf.version <= '0.83.4.1' \
|
||||||
|
and ircutils.isChannel(recipient):
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
user = ircdb.users.getUser(hostmask)
|
||||||
|
except KeyError:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def checkIgnored(hostmask, recipient):
|
||||||
|
try:
|
||||||
|
user = ircdb.users.getUser(hostmask)
|
||||||
|
if user._checkCapability('owner'):
|
||||||
|
return False
|
||||||
|
elif user.ignore:
|
||||||
|
return True
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
if ircdb.ignores.checkIgnored(hostmask):
|
||||||
|
return True
|
||||||
|
if ircutils.isChannel(recipient):
|
||||||
|
c = ircdb.channels.getChannel(recipient)
|
||||||
|
if c.checkIgnored(hostmask):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
## Taken from Encyclopedia ##
|
## Taken from Encyclopedia ##
|
||||||
# Repeat filtering message queue
|
# Repeat filtering message queue
|
||||||
msgcache = {}
|
msgcache = {}
|
||||||
def queue(irc, to, msg):
|
def queue(irc, target, msg):
|
||||||
now = time.time()
|
now = time.time()
|
||||||
for m in list(msgcache.keys()):
|
for m in list(msgcache.keys()):
|
||||||
if msgcache[m] < now - 30:
|
if msgcache[m] < now - 30:
|
||||||
msgcache.pop(m)
|
msgcache.pop(m)
|
||||||
for m in msgcache:
|
for m in msgcache:
|
||||||
if m[0] == irc and m[1] == to:
|
if m[0] == irc and m[1] == target:
|
||||||
oldmsg = m[2]
|
oldmsg = m[2]
|
||||||
if msg == oldmsg or oldmsg.endswith(msg):
|
if oldmsg.endswith(msg):
|
||||||
break
|
break
|
||||||
if msg.endswith(oldmsg):
|
if msg.endswith(oldmsg) and msg[:-len(oldmsg)].endswith(': '):
|
||||||
msg = msg[:-len(oldmsg)] + 'please see above'
|
msg = msg[:-len(oldmsg)] + 'Please see above'
|
||||||
else:
|
else:
|
||||||
msgcache[(irc, to, msg)] = now
|
msgcache[(irc, target, msg)] = now
|
||||||
irc.queueMsg(ircmsgs.privmsg(to, msg))
|
irc.reply(msg, to=target)
|
||||||
|
|
||||||
class PackageInfo(callbacks.Plugin):
|
class PackageInfo(callbacks.Plugin):
|
||||||
"""Lookup package information via apt-cache/apt-file"""
|
"""Look up package information via apt-cache/apt-file"""
|
||||||
threaded = True
|
threaded = True
|
||||||
space_re = re.compile(r' *')
|
|
||||||
|
|
||||||
def __init__(self, irc):
|
def __init__(self, irc):
|
||||||
self.__parent = super(PackageInfo, self)
|
self.__parent = super(PackageInfo, self)
|
||||||
self.__parent.__init__(irc)
|
self.__parent.__init__(irc)
|
||||||
self.Apt = packages.Apt(self)
|
self.Apt = packages.Apt(self)
|
||||||
|
|
||||||
def callPrecedence(self, irc):
|
|
||||||
before = []
|
|
||||||
for cb in irc.callbacks:
|
|
||||||
if cb.name() == 'IRCLogin':
|
|
||||||
before.append(cb)
|
|
||||||
return (before, [])
|
|
||||||
|
|
||||||
def __getRelease(self, irc, release, channel, doError=True):
|
def __getRelease(self, irc, release, channel, doError=True):
|
||||||
if release:
|
if release:
|
||||||
release = release.strip()
|
release = release.strip()
|
||||||
|
@ -87,253 +97,124 @@ class PackageInfo(callbacks.Plugin):
|
||||||
return (None, None)
|
return (None, None)
|
||||||
if not release:
|
if not release:
|
||||||
return (defaultRelease, None)
|
return (defaultRelease, None)
|
||||||
(release, rest) = (release.split(' ', 1) + [None])[:2]
|
(release, rest) = (release.split(None, 1) + [None])[:2]
|
||||||
if release[0] in ('|', '>'):
|
if release[0] in '|>':
|
||||||
return (defaultRelease, "%s %s" % (release, rest))
|
return (defaultRelease, "%s %s" % (release, rest))
|
||||||
return (release, rest)
|
return (release, rest)
|
||||||
|
|
||||||
def __getChannel(self, channel):
|
def __handleRest(self, msg, target, reply, rest):
|
||||||
return ircutils.isChannel(channel) and channel or None
|
targeto = target
|
||||||
|
prefix = ''
|
||||||
|
if rest[0] == '|':
|
||||||
|
rest = rest.lstrip('|').strip()
|
||||||
|
if rest:
|
||||||
|
if rest.lower() == "me":
|
||||||
|
rest = msg.nick
|
||||||
|
prefix = "%s: " % rest
|
||||||
|
elif rest[0] == '>':
|
||||||
|
rest = rest.lstrip('>').strip()
|
||||||
|
if rest:
|
||||||
|
# Take the first "nick" and strip off bad chars
|
||||||
|
target = stripNick(rest.split()[0])
|
||||||
|
if target.lower() == "me":
|
||||||
|
target = msg.nick
|
||||||
|
prefix = "<%s> wants you to know: " % msg.nick
|
||||||
|
|
||||||
def __getReplyChars(self, channel):
|
if target.lower() != targeto.lower() and ircutils.isChannel(target):
|
||||||
prefix_chars = list(self.registryValue("prefixchar", channel))
|
target = targeto
|
||||||
address_chars = list(str( conf.supybot.reply.whenAddressedBy.chars() ))
|
prefix = "(Forwarding to channels is not permitted) "
|
||||||
if channel:
|
elif msg.nick.lower() in (target.lower(), prefix[:-2].lower()) \
|
||||||
address_chars = list(str( conf.supybot.reply.whenAddressedBy.chars.get(channel) ))
|
and msg.nick.lower() != targeto.lower():
|
||||||
return tuple(set(prefix_chars + address_chars))
|
target = msg.nick
|
||||||
|
prefix = "(In the future, please use a private message to investigate) "
|
||||||
|
|
||||||
def __getCommand(self, text, channel):
|
return (target, prefix + reply)
|
||||||
reply_chars = self.__getReplyChars(channel)
|
|
||||||
my_commands = self.listCommands()
|
|
||||||
if text[0] in reply_chars:
|
|
||||||
text = text[1:]
|
|
||||||
return text.strip().lower().split(' ', 1)[0]
|
|
||||||
|
|
||||||
def real_info(self, irc, msg, args, package, release):
|
def real_info(self, irc, msg, args, package, release=None):
|
||||||
"""<package> [<release>]
|
"""<package> [<release>]
|
||||||
|
|
||||||
Lookup information for <package>, optionally in <release>
|
Look up information for <package>, optionally in <release>
|
||||||
"""
|
"""
|
||||||
channel = self.__getChannel(msg.args[0])
|
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||||
reply_target = ircutils.replyTo(msg)
|
if not self.registryValue("enabled", channel):
|
||||||
|
return
|
||||||
(release, rest) = self.__getRelease(irc, release, channel)
|
(release, rest) = self.__getRelease(irc, release, channel)
|
||||||
if not release:
|
if not release:
|
||||||
return
|
return
|
||||||
|
target = ircutils.replyTo(msg)
|
||||||
reply = self.Apt.info(package, release)
|
reply = self.Apt.info(package, release)
|
||||||
if rest:
|
if rest:
|
||||||
if rest[0] == '|':
|
(target, reply) = self.__handleRest(msg, target, reply, rest)
|
||||||
try:
|
queue(irc, target, reply)
|
||||||
target = rest
|
|
||||||
while target[0] == '|':
|
|
||||||
target = target[1:].strip()
|
|
||||||
if target.lower() == "me":
|
|
||||||
target = msg.nick
|
|
||||||
queue(irc, reply_target, "%s: %s" % (target, reply))
|
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
self.log.info("PackageInfo: (info) Exception in pipe: %r" % e)
|
|
||||||
pass
|
|
||||||
elif rest[0] == '>':
|
|
||||||
try:
|
|
||||||
while rest[0] == '>':
|
|
||||||
rest = rest[1:].strip()
|
|
||||||
targets = [_ for _ in rest.split() if _] # Split and discard empty parts
|
|
||||||
target = stripNick(targets[0]) # Take the first "nick" and strip off bad chars
|
|
||||||
if target.lower() == "me":
|
|
||||||
target = msg.nick # redirect
|
|
||||||
if not target: # Throw error
|
|
||||||
raise Exception('No target')
|
|
||||||
queue(irc, target, "<%s> wants you to know: %s" % (msg.nick, reply))
|
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
self.log.info("PackageInfo: (info) Exception in redirect: %r" % e)
|
|
||||||
pass
|
|
||||||
|
|
||||||
queue(irc, reply_target, reply)
|
|
||||||
|
|
||||||
info = wrap(real_info, ['anything', optional('text')])
|
info = wrap(real_info, ['anything', optional('text')])
|
||||||
|
|
||||||
def real_depends(self, irc, msg, args, package, release):
|
def real_depends(self, irc, msg, args, package, release=None):
|
||||||
"""<package> [<release>]
|
"""<package> [<release>]
|
||||||
|
|
||||||
Lookup dependencies for <package>, optionally in <release>
|
Look up dependencies for <package>, optionally in <release>
|
||||||
"""
|
"""
|
||||||
channel = self.__getChannel(msg.args[0])
|
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||||
reply_target = ircutils.replyTo(msg)
|
if not self.registryValue("enabled", channel):
|
||||||
|
return
|
||||||
(release, rest) = self.__getRelease(irc, release, channel)
|
(release, rest) = self.__getRelease(irc, release, channel)
|
||||||
if not release:
|
if not release:
|
||||||
return
|
return
|
||||||
|
target = ircutils.replyTo(msg)
|
||||||
reply = self.Apt.depends(package, release)
|
reply = self.Apt.depends(package, release)
|
||||||
if rest:
|
if rest:
|
||||||
if rest[0] == '|':
|
(target, reply) = self.__handleRest(msg, target, reply, rest)
|
||||||
try:
|
queue(irc, target, reply)
|
||||||
target = rest
|
|
||||||
while target[0] == '|':
|
|
||||||
target = target[1:].strip()
|
|
||||||
if target.lower() == "me":
|
|
||||||
target = msg.nick
|
|
||||||
queue(irc, reply_target, "%s: %s" % (target, reply))
|
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
self.log.info("PackageInfo: (depends) Exception in pipe: %r" % e)
|
|
||||||
pass
|
|
||||||
elif rest[0] == '>':
|
|
||||||
try:
|
|
||||||
while rest[0] == '>':
|
|
||||||
rest = rest[1:].strip()
|
|
||||||
targets = [_ for _ in rest.split() if _] # Split and discard empty parts
|
|
||||||
target = stripNick(targets[0]) # Take the first "nick" and strip off bad chars
|
|
||||||
if target.lower() == "me":
|
|
||||||
target = msg.nick # redirect
|
|
||||||
if not target: # Throw error
|
|
||||||
raise Exception('No target')
|
|
||||||
queue(irc, target, "<%s> wants you to know: %s" % (msg.nick, reply))
|
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
self.log.info("PackageInfo: (depends) Exception in redirect: %r" % e)
|
|
||||||
pass
|
|
||||||
|
|
||||||
queue(irc, reply_target, reply)
|
|
||||||
|
|
||||||
depends = wrap(real_depends, ['anything', optional('text')])
|
depends = wrap(real_depends, ['anything', optional('text')])
|
||||||
|
|
||||||
def real_find(self, irc, msg, args, package, release):
|
def real_find(self, irc, msg, args, package, release=None):
|
||||||
"""<package/filename> [<release>]
|
"""<package/filename> [<release>]
|
||||||
|
|
||||||
Search for <package> or, of that fails, find <filename>'s package(s).
|
Search for <package> or, if that fails, <filename> in packages,
|
||||||
Optionally in <release>
|
optionally in <release>
|
||||||
"""
|
"""
|
||||||
channel = self.__getChannel(msg.args[0])
|
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||||
reply_target = ircutils.replyTo(msg)
|
if not self.registryValue("enabled", channel):
|
||||||
|
return
|
||||||
(release, rest) = self.__getRelease(irc, release, channel)
|
(release, rest) = self.__getRelease(irc, release, channel)
|
||||||
if not release:
|
if not release:
|
||||||
return
|
return
|
||||||
|
target = ircutils.replyTo(msg)
|
||||||
reply = self.Apt.find(package, release)
|
reply = self.Apt.find(package, release)
|
||||||
if rest:
|
if rest:
|
||||||
if rest[0] == '|':
|
(target, reply) = self.__handleRest(msg, target, reply, rest)
|
||||||
try:
|
queue(irc, target, reply)
|
||||||
target = rest
|
|
||||||
while target[0] == '|':
|
|
||||||
target = target[1:].strip()
|
|
||||||
if target.lower() == "me":
|
|
||||||
target = msg.nick
|
|
||||||
queue(irc, reply_target, "%s: %s" % (target, reply))
|
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
self.log.info("PackageInfo: (find) Exception in pipe: %r" % e)
|
|
||||||
pass
|
|
||||||
elif rest[0] == '>':
|
|
||||||
try:
|
|
||||||
while rest[0] == '>':
|
|
||||||
rest = rest[1:].strip()
|
|
||||||
targets = [_ for _ in rest.split() if _] # Split and discard empty parts
|
|
||||||
target = stripNick(targets[0]) # Take the first "nick" and strip off bad chars
|
|
||||||
if target.lower() == "me":
|
|
||||||
target = msg.nick # redirect
|
|
||||||
if not target: # Throw error
|
|
||||||
raise Exception('No target')
|
|
||||||
queue(irc, target, "<%s> wants you to know: %s" % (msg.nick, reply))
|
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
self.log.info("PackageInfo: (find) Exception in redirect: %r" % e)
|
|
||||||
pass
|
|
||||||
|
|
||||||
queue(irc, reply_target, reply)
|
|
||||||
|
|
||||||
find = wrap(real_find, ['anything', optional('text')])
|
find = wrap(real_find, ['anything', optional('text')])
|
||||||
|
|
||||||
def privmsg(self, irc, msg, user):
|
|
||||||
channel = self.__getChannel(msg.args[0])
|
|
||||||
text = self.space_re.subn(' ', msg.args[1].strip())[0]
|
|
||||||
my_commands = self.listCommands()
|
|
||||||
if text[0] == self.registryValue("prefixchar"):
|
|
||||||
text = text[1:].strip()
|
|
||||||
if user and text[0] in list(conf.supybot.reply.whenAddressedBy.chars()):
|
|
||||||
return
|
|
||||||
(cmd, rest) = (text.split(' ', 1) + [None])[:2]
|
|
||||||
if cmd not in my_commands:
|
|
||||||
return
|
|
||||||
if not rest:
|
|
||||||
return
|
|
||||||
(term, rest) = (rest.split(' ', 1) + [None])[:2]
|
|
||||||
if cmd == "find":
|
|
||||||
self.real_find(irc, msg, [], term, rest)
|
|
||||||
elif cmd == "depends":
|
|
||||||
self.real_depends(irc, msg, [], term, rest)
|
|
||||||
else:
|
|
||||||
self.real_info(irc, msg, [], term, rest)
|
|
||||||
|
|
||||||
def chanmsg(self, irc, msg, user):
|
|
||||||
channel = self.__getChannel(msg.args[0])
|
|
||||||
text = self.space_re.subn(' ', msg.args[1].strip())[0]
|
|
||||||
my_commands = self.listCommands()
|
|
||||||
if text[0] != self.registryValue("prefixchar", channel):
|
|
||||||
return
|
|
||||||
text = text[1:]
|
|
||||||
(cmd, rest) = (text.split(' ', 1) + [None])[:2]
|
|
||||||
if cmd not in my_commands:
|
|
||||||
return
|
|
||||||
if not rest:
|
|
||||||
return
|
|
||||||
(term, rest) = (rest.split(' ', 1) + [None])[:2]
|
|
||||||
if cmd == "find":
|
|
||||||
self.real_find(irc, msg, [], term, rest)
|
|
||||||
elif cmd == "depends":
|
|
||||||
self.real_depends(irc, msg, [], term, rest)
|
|
||||||
else:
|
|
||||||
self.real_info(irc, msg, [], term, rest)
|
|
||||||
|
|
||||||
def doPrivmsg(self, irc, msg):
|
def doPrivmsg(self, irc, msg):
|
||||||
if chr(1) in msg.args[1]: # CTCP
|
if chr(1) in msg.args[1]: # CTCP
|
||||||
return
|
return
|
||||||
if not msg.args[1]:
|
text = msg.args[1].strip()
|
||||||
|
if not text:
|
||||||
return
|
return
|
||||||
channel = self.__getChannel(msg.args[0])
|
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||||
if not self.registryValue("enabled", channel):
|
if text[0] == self.registryValue("prefixchar", channel):
|
||||||
|
text = text[1:].strip()
|
||||||
|
elif channel or text[0] in conf.supybot.reply.whenAddressedBy.chars():
|
||||||
return
|
return
|
||||||
user = get_user(msg)
|
if not text:
|
||||||
if channel:
|
return
|
||||||
self.chanmsg(irc, msg, user)
|
(cmd, rest) = (text.split(None, 1) + [None])[:2]
|
||||||
else:
|
if not cmd:
|
||||||
if user:
|
return
|
||||||
return
|
cmd = cmd.lower()
|
||||||
self.privmsg(irc, msg, user)
|
if not (cmd in ("info", "depends", "find") and rest):
|
||||||
|
return
|
||||||
|
(package, release) = (rest.split(None, 1) + [None])[:2]
|
||||||
|
irc = callbacks.NestedCommandsIrcProxy(irc, msg, [])
|
||||||
|
getattr(self, "real_%s" % cmd)(irc, msg, [], package, release)
|
||||||
|
|
||||||
def inFilter(self, irc, msg):
|
def inFilter(self, irc, msg):
|
||||||
if msg.command != "PRIVMSG":
|
if not defaultIgnored(msg.prefix, msg.args[0]):
|
||||||
return msg
|
return msg
|
||||||
if not conf.supybot.defaultIgnore():
|
if checkIgnored(msg.prefix, msg.args[0]):
|
||||||
return msg
|
return msg
|
||||||
text = msg.args[1].strip()
|
if msg.command == "PRIVMSG":
|
||||||
if len(text) < 6:
|
|
||||||
return msg
|
|
||||||
user = get_user(msg)
|
|
||||||
channel = self.__getChannel(msg.args[0])
|
|
||||||
reply_chars = self.__getReplyChars(channel)
|
|
||||||
my_commands = self.listCommands()
|
|
||||||
cmd = self.__getCommand(text, channel)
|
|
||||||
|
|
||||||
if cmd not in my_commands:
|
|
||||||
return msg
|
|
||||||
|
|
||||||
if user:
|
|
||||||
if not channel and text[0] == self.registryValue("prefixchar"):
|
|
||||||
msg.args = (msg.args[0], text[1:])
|
|
||||||
return msg
|
|
||||||
|
|
||||||
if channel:
|
|
||||||
if text[0] not in reply_chars:
|
|
||||||
return msg
|
|
||||||
|
|
||||||
# if not hasattr(irc, 'reply'):
|
|
||||||
# irc = callbacks.ReplyIrcProxy(irc, msg)
|
|
||||||
# self.doPrivmsg(irc, msg)
|
|
||||||
else:
|
|
||||||
if text[1] in reply_chars:
|
|
||||||
msg.args = (msg.args[0], text[1:])
|
|
||||||
irc = callbacks.ReplyIrcProxy(irc, msg)
|
|
||||||
self.doPrivmsg(irc, msg)
|
self.doPrivmsg(irc, msg)
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
Class = PackageInfo
|
Class = PackageInfo
|
||||||
|
|
|
@ -7,76 +7,65 @@ DIR=""
|
||||||
# Be quiet by default.
|
# Be quiet by default.
|
||||||
VERBOSE=0
|
VERBOSE=0
|
||||||
|
|
||||||
|
|
||||||
## Please don't change anything below this line, unless you really know what
|
## Please don't change anything below this line, unless you really know what
|
||||||
## you are doing and don't bother me with whatever errors it produces :)
|
## you are doing and don't bother me with whatever errors it produces :)
|
||||||
|
|
||||||
# Print usage information.
|
# Print usage information.
|
||||||
usage() {
|
usage() {
|
||||||
echo "Usage $0 [OPTION]..."
|
cat <<EOF
|
||||||
echo "Updates the APT package cache for PackageInfo"
|
Usage: $0 [OPTION]...
|
||||||
echo ""
|
|
||||||
echo "-h, --help Display this message and exit."
|
Updates the APT package cache for PackageInfo.
|
||||||
echo "-v, --verbose Be more verbose than normal."
|
|
||||||
echo "-V, --very-verbose Be even more verbose than normal."
|
-d, --dir <DIR> Specify directory for APT package cache.
|
||||||
echo "-d, --dir[=DIR] Sets the directory to use when updating the APT package cache."
|
-v, --verbose Be more verbose than normal.
|
||||||
echo ""
|
-V, --very-verbose Be even more verbose than normal.
|
||||||
echo "Note:"
|
-h, --help Display this message and exit.
|
||||||
echo " Please separate each option with a space, eg:"
|
|
||||||
echo " $0 -v -d /home/bot/aptdir"
|
Note:
|
||||||
echo " Rather than:"
|
Please separate each option with a space, eg:
|
||||||
echo " $0 -vd /home/bot/aptdir"
|
$0 -v -d /home/bot/aptdir
|
||||||
echo ""
|
Rather than:
|
||||||
echo "This script is intended to be ran automatically (eg: cron), so it shows no output by default."
|
$0 -vd /home/bot/aptdir
|
||||||
echo "You can make the script more verbose with either the -v/--verbose or -V/--very-verbose options."
|
|
||||||
echo "The -d/--dir option sets the directory where this script looks for *.list files for apt-get."
|
This script is intended to be run automatically (eg: cron), so it shows no output by default.
|
||||||
|
You can make the script more verbose with the -v/--verbose or -V/--very-verbose options.
|
||||||
|
The -d/--dir option sets the directory where this script looks for *.list files for apt-get.
|
||||||
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
# Prints an error message, usage (above), then exit with the specified exit value.
|
# Prints an error message, usage (above), then exits with the specified exit value.
|
||||||
error() {
|
error() {
|
||||||
local exit_val=$1
|
local exit_val=$1
|
||||||
shift
|
shift
|
||||||
echo $@ >&2
|
echo "$@" >&2
|
||||||
usage >&2
|
usage >&2
|
||||||
exit $exit_val
|
exit $exit_val
|
||||||
}
|
}
|
||||||
|
|
||||||
# Runs apt-get update in the specified directory for the specified distribution.
|
# Runs apt-get update in the specified directory for the specified distribution.
|
||||||
update_apt() {
|
update_apt() {
|
||||||
local apt_dir="$1"
|
|
||||||
local dist="$2"
|
|
||||||
local apt_args=""
|
|
||||||
|
|
||||||
if [ $VERBOSE -eq 0 ]; then
|
if [ $VERBOSE -eq 0 ]; then
|
||||||
apt_args="-qq"
|
apt_args="-qq"
|
||||||
elif [ $VERBOSE -eq 1 ]; then
|
elif [ $VERBOSE -eq 1 ]; then
|
||||||
apt_args="-q"
|
apt_args="-q"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
apt-get $apt_args -o="APT::Architecture=i386" \
|
apt-get $apt_args \
|
||||||
|
-o="APT::Architecture=amd64" \
|
||||||
-o="APT::Architectures::=i386" \
|
-o="APT::Architectures::=i386" \
|
||||||
-o "APT::Architectures::=amd64" \
|
-o="APT::Architectures::=amd64" \
|
||||||
-o="Dir::State::Lists=$apt_dir/$dist" \
|
-o="Dir::State::Lists=$DIR/$DIST" \
|
||||||
-o="Dir::State::Status=$apt_dir/$dist.status" \
|
-o="Dir::State::Status=$DIR/$DIST.status" \
|
||||||
-o="Dir::Cache=$apt_dir/cache" \
|
-o="Dir::Etc::SourceList=$DIR/$DIST.list" \
|
||||||
-o="Dir::Etc::SourceList=$apt_dir/$dist.list" \
|
-o="Dir::Etc::SourceParts=''" \
|
||||||
-o="Dir::Etc::SourceParts=\"\"" \
|
-o="Dir::Cache=$DIR/cache" \
|
||||||
update
|
update
|
||||||
|
|
||||||
return $?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# main()
|
|
||||||
|
|
||||||
# Acepted arguments are:
|
|
||||||
# -h,--help
|
|
||||||
# -v,--verbose
|
|
||||||
# -V,--very-verbose
|
|
||||||
# -d,--dir[=DIR]
|
|
||||||
|
|
||||||
# Check command-line arguments
|
# Check command-line arguments
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case "$1" in
|
case $1 in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
usage
|
usage
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -88,13 +77,13 @@ while [ $# -gt 0 ]; do
|
||||||
VERBOSE=2
|
VERBOSE=2
|
||||||
;;
|
;;
|
||||||
-d|--dir)
|
-d|--dir)
|
||||||
[ -z "$2" ] && error 1 "\"-d|--dir\" requires an argument."
|
[ -z "$2" ] && error 1 '"-d/--dir" requires an argument.'
|
||||||
shift
|
shift
|
||||||
DIR="$1"
|
DIR="$1"
|
||||||
;;
|
;;
|
||||||
--dir=*)
|
--dir=*)
|
||||||
DIR="${1:6}"
|
DIR="${1:6}"
|
||||||
[ -z "$DIR" ] && error 1 "\"--dir\" requires an argument."
|
[ -z "$DIR" ] && error 1 '"--dir" requires an argument.'
|
||||||
;;
|
;;
|
||||||
-*)
|
-*)
|
||||||
error 1 "Unknown option \"$1\"."
|
error 1 "Unknown option \"$1\"."
|
||||||
|
@ -106,38 +95,33 @@ while [ $# -gt 0 ]; do
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
apt_get=$(which apt-get 2>/dev/null)
|
# Check if apt-get is installed and bail if not.
|
||||||
|
if ! which apt-get >/dev/null 2>&1; then
|
||||||
# Check that apt-get exists and bail if it doesn't.
|
echo "ERROR: apt-get not found. Please install apt-get in your PATH." >&2
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "ERROR: apt-get not found. Please install apt-get in your \$PATH." >&2
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#TODO: Remove this section and error out if DIR is not set,
|
|
||||||
# This could hide errors where DIR/-d was not set, an error message.
|
|
||||||
if [ -z "$DIR" ]; then
|
if [ -z "$DIR" ]; then
|
||||||
DIR=/home/bot/aptdir
|
error 1 "ERROR: No DIR set in the script and no -d/--dir option given."
|
||||||
echo "WARNING: No DIR set and no -d/--dir option given, defaulting to \"$DIR\"" >&2
|
|
||||||
echo "WARNING: Please set DIR on line 5 of $(readlink -f $0) or use the -d/--dir option" >&2
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#[ -z "$DIR" ] && error 1 "ERROT: Please set DIR on line 5 of $(readlink -f $0) or use the -d/--dir option"
|
items=("$DIR"/*.list)
|
||||||
|
[ ! -e "${items[0]}" ] && error 1 "ERROR: Could not find any *.list files in \"$DIR\"."
|
||||||
|
|
||||||
DIR="$(echo $DIR | sed 's,/*$,,')" # Normalize $DIR
|
for DIST in "${items[@]}"; do
|
||||||
|
|
||||||
items=$(ls "${DIR}"/*.list 2>/dev/null)
|
|
||||||
[ $? -ne 0 ] && error 1 "Could not find \"*.list\" files in \"$DIR\"."
|
|
||||||
|
|
||||||
for DIST in $items; do
|
|
||||||
[ -h "$DIST" ] && continue # Ignore symbolic links
|
[ -h "$DIST" ] && continue # Ignore symbolic links
|
||||||
# Extract the distribution name from the .list file name.
|
# Extract the distribution name from the .list file name.
|
||||||
DIST="${DIST:${#DIR}}"
|
DIST=${DIST##*/}
|
||||||
DIST="${DIST/.list}"
|
DIST=${DIST%.list}
|
||||||
DIST="${DIST:1}"
|
|
||||||
|
|
||||||
touch "${DIR}/${DIST}.status" # Create APT status file
|
[ $VERBOSE -gt 0 ] && echo "INFO: Processing $DIST"
|
||||||
mkdir -p "${DIR}/${DIST}/partial" # APT needs this to exist
|
touch "$DIR/$DIST.status" # Create APT status file
|
||||||
update_apt "$DIR" "$DIST" # Update the package list with apt-get
|
mkdir -p "$DIR/$DIST/partial" # APT needs this to exist
|
||||||
|
update_apt # Update APT package cache
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
[ $VERBOSE -eq 0 ] && echo "Try passing -v or -V to get the error message." >&2
|
||||||
|
echo "ERROR: apt-get update failed for $DIST." >&2
|
||||||
|
exit_val=$?
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
exit $exit_val
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# or use the --dir command-line option.
|
# or use the --dir command-line option.
|
||||||
DIR=""
|
DIR=""
|
||||||
|
|
||||||
# Be quiet by default
|
# Be quiet by default.
|
||||||
VERBOSE=0
|
VERBOSE=0
|
||||||
|
|
||||||
## Please don't change anything below this line, unless you really know what
|
## Please don't change anything below this line, unless you really know what
|
||||||
|
@ -12,53 +12,48 @@ VERBOSE=0
|
||||||
|
|
||||||
# Print usage information.
|
# Print usage information.
|
||||||
usage() {
|
usage() {
|
||||||
echo "Usage $0 [OPTION]..."
|
cat <<EOF
|
||||||
echo "Updates the apt-file cache for PackageInfo"
|
Usage: $0 [OPTION]...
|
||||||
echo ""
|
|
||||||
echo "-h, --help Display this message and exit."
|
Updates the apt-file cache for PackageInfo.
|
||||||
echo "-v, --verbose Be more verbose than normal."
|
|
||||||
echo "-d, --dir[=DIR] Sets the directory to use when updating the apt-file cache."
|
-d, --dir <DIR> Specify directory for apt-file cache.
|
||||||
echo ""
|
-v, --verbose Be more verbose than normal.
|
||||||
echo "Note:"
|
-h, --help Display this message and exit.
|
||||||
echo " Please separate each option with a space, eg:"
|
|
||||||
echo " $0 -v -d /home/bot/aptdir"
|
Note:
|
||||||
echo " Rather than:"
|
Please separate each option with a space, eg:
|
||||||
echo " $0 -vd /home/bot/aptdir"
|
$0 -v -d /home/bot/aptdir
|
||||||
echo ""
|
Rather than:
|
||||||
echo "This script is intended to be ran automatically (eg: cron), so it shows no output by default."
|
$0 -vd /home/bot/aptdir
|
||||||
echo "You can make the script more verbose with the -v/--verbose option."
|
|
||||||
echo "The -d/--dir option sets the directory where this script looks for *.list files for apt-file."
|
This script is intended to be run automatically (eg: cron), so it shows no output by default.
|
||||||
|
You can make the script more verbose with the -v/--verbose option.
|
||||||
|
The -d/--dir option sets the directory where this script looks for *.list files for apt-file.
|
||||||
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
# Prints an error message, usage (above), then exit with the specified exit value.
|
# Prints an error message, usage (above), then exits with the specified exit value.
|
||||||
error() {
|
error() {
|
||||||
local exit_val=$1
|
local exit_val=$1
|
||||||
shift
|
shift
|
||||||
echo $@ >&2
|
echo "$@" >&2
|
||||||
usage >&2
|
usage >&2
|
||||||
exit $exit_val
|
exit $exit_val
|
||||||
}
|
}
|
||||||
|
|
||||||
# Runs apt-file in the specified directory against the specified distribution.
|
# Runs apt-file update in the specified directory for the specified distribution.
|
||||||
update_apt() {
|
update_apt_file() {
|
||||||
local DIST="$1"
|
|
||||||
if [ $VERBOSE -eq 0 ]; then
|
if [ $VERBOSE -eq 0 ]; then
|
||||||
apt-file -N -l -c "$DIR/apt-file/$DIST" -s "$DIR/$DIST.list" -a i386 update >/dev/null 2>&1
|
apt-file -N -l -c "$DIR/apt-file/$DIST" -s "$DIR/$DIST.list" -a amd64 update >/dev/null 2>&1
|
||||||
else
|
else
|
||||||
apt-file -N -l -c "$DIR/apt-file/$DIST" -s "$DIR/$DIST.list" -a i386 update
|
apt-file -N -l -c "$DIR/apt-file/$DIST" -s "$DIR/$DIST.list" -a amd64 update
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# main()
|
|
||||||
|
|
||||||
# Acepted arguments are:
|
|
||||||
# -h,--help
|
|
||||||
# -v,--verbose
|
|
||||||
# -d,--dir[=DIR]
|
|
||||||
|
|
||||||
# Check command-line arguments
|
# Check command-line arguments
|
||||||
while [ $# -ne 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case "$1" in
|
case $1 in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
usage
|
usage
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -67,61 +62,50 @@ while [ $# -ne 0 ]; do
|
||||||
VERBOSE=1
|
VERBOSE=1
|
||||||
;;
|
;;
|
||||||
-d|--dir)
|
-d|--dir)
|
||||||
[ -z "$2" ] && error 1 "\"-d|--dir\" requires an argument."
|
[ -z "$2" ] && error 1 '"-d/--dir" requires an argument.'
|
||||||
shift
|
shift
|
||||||
DIR="$1"
|
DIR="$1"
|
||||||
;;
|
;;
|
||||||
--dir=*)
|
--dir=*)
|
||||||
DIR="${1:6}"
|
DIR="${1:6}"
|
||||||
[ -z "$DIR" ] && error 1 "\"--dir\" requires an argument."
|
[ -z "$DIR" ] && error 1 '"--dir" requires an argument.'
|
||||||
;;
|
;;
|
||||||
-*)
|
-*)
|
||||||
error 1 "Unknown option \"$1\"."
|
error 1 "Unknown option \"$1\"."
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
error 1 "This script takes no non-argument parameterss."
|
error 1 "This script takes no non-argument parameters."
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
apt_file=$(which apt-file 2>/dev/null)
|
# Check if apt-file is installed and bail if not.
|
||||||
|
if ! which apt-file >/dev/null 2>&1; then
|
||||||
# Check if apt-file is installed and bail if it isn't.
|
echo "ERROR: apt-file not found. Please install apt-file in your PATH." >&2
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "ERROR: apt-file not found. Please install apt-file in your \$PATH." >&2
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#TODO: Remove this and error out if DIR is not set,
|
|
||||||
# This is legacy code and needs to disappear sometime.
|
|
||||||
if [ -z "$DIR" ]; then
|
if [ -z "$DIR" ]; then
|
||||||
DIR=/home/bot/aptdir
|
error 1 "ERROR: No DIR set in the script and no -d/--dir option given."
|
||||||
echo "WARNING: No DIR set and no -d/--dir option given, defaulting to \"$DIR\"" >&2
|
|
||||||
echo "WARNING: Please set DIR on line 5 of $(readlink -f $0) or use the -d/--dir option" >&2
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#[ -z "$DIR" ] && error 1 "Please set DIR on line 5 of $(readlink -f $0) or use the -d/--dir option"
|
items=("$DIR"/*.list)
|
||||||
|
[ ! -e "${items[0]}" ] && error 1 "ERROR: Could not find any *.list files in \"$DIR\"."
|
||||||
|
|
||||||
DIR="$(echo $DIR | sed 's,/*$,,')" # Normalize $DIR
|
for DIST in "${items[@]}"; do
|
||||||
|
[ -h "$DIST" ] && continue # Ignore symbolic links
|
||||||
|
# Extract the distribution name from the .list file name.
|
||||||
|
DIST=${DIST##*/}
|
||||||
|
DIST=${DIST%.list}
|
||||||
|
|
||||||
items=$(ls "${DIR}"/*.list 2>/dev/null)
|
[ $VERBOSE -gt 0 ] && echo "INFO: Processing $DIST"
|
||||||
[ $? -ne 0 ] && error 1 "ERROR: Could not find \"*.list\" files in \"$DIR\"."
|
mkdir -p "$DIR/apt-file/$DIST" # Create apt-file directory if it doesn't exist
|
||||||
|
update_apt_file # Update apt-file cache
|
||||||
for DIST in $items; do
|
|
||||||
[ -h $DIST ] && continue # Ignore symbolic links
|
|
||||||
# Extract the distribution from the .list file name
|
|
||||||
DIST="${DIST:${#DIR}}"
|
|
||||||
DIST="${DIST/.list}"
|
|
||||||
DIST="${DIST:1}"
|
|
||||||
|
|
||||||
mkdir -p "$DIR/apt-file/$DIST" # Create apt-file directory, if it doesn't exist
|
|
||||||
|
|
||||||
[ $VERBOSE -ne 0 ] && echo "INFO: Processing $DIST"
|
|
||||||
update_apt "$DIST" # Update apt-file database
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
[ $VERBOSE -eq 0 ] && echo "Try passing -v to get the error message." >&2
|
[ $VERBOSE -eq 0 ] && echo "Try passing -v to get the error message." >&2
|
||||||
error 1 "ERROR: apt-file failed for ${DIST}!."
|
echo "ERROR: apt-file update failed for $DIST." >&2
|
||||||
|
exit_val=$?
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
exit $exit_val
|
||||||
|
|
Loading…
Reference in New Issue