aboutsummaryrefslogtreecommitdiff
path: root/Manpages
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2021-06-17 01:58:33 -0400
committerB. Watson <yalhcru@gmail.com>2021-06-17 01:58:33 -0400
commit15128b94b496324a1c0afd6cbdd7fffbdaa18ba7 (patch)
treea7901aab7124e41ca2a5466dd7547ee791061c7c /Manpages
downloadlimnoria.slackfacts.plugins-15128b94b496324a1c0afd6cbdd7fffbdaa18ba7.tar.gz
Initial commit.
Diffstat (limited to 'Manpages')
-rw-r--r--Manpages/README.md1
-rw-r--r--Manpages/__init__.py48
-rw-r--r--Manpages/config.py36
-rw-r--r--Manpages/local/__init__.py1
-rw-r--r--Manpages/plugin.py99
-rw-r--r--Manpages/plugin.py.old98
-rw-r--r--Manpages/test.py15
7 files changed, 298 insertions, 0 deletions
diff --git a/Manpages/README.md b/Manpages/README.md
new file mode 100644
index 0000000..b12ae49
--- /dev/null
+++ b/Manpages/README.md
@@ -0,0 +1 @@
+Provides Unix manpage lookups
diff --git a/Manpages/__init__.py b/Manpages/__init__.py
new file mode 100644
index 0000000..c726c08
--- /dev/null
+++ b/Manpages/__init__.py
@@ -0,0 +1,48 @@
+###
+# Copyright (c) 2021, B. Watson
+# All rights reserved.
+#
+#
+###
+
+"""
+Manpages: Provides Unix manpage lookups
+"""
+
+import sys
+import supybot
+from supybot import world
+
+# Use this for the version of this plugin.
+__version__ = "0.0.1"
+
+# XXX Replace this with an appropriate author or supybot.Author instance.
+__author__ = supybot.Author('B. Watson', 'Urchlay', 'yalhcru@gmail.com')
+
+# This is a dictionary mapping supybot.Author instances to lists of
+# contributions.
+__contributors__ = {}
+
+# This is a url where the most recent plugin package can be downloaded.
+__url__ = ''
+
+from . import config
+from . import plugin
+if sys.version_info >= (3, 4):
+ from importlib import reload
+else:
+ from imp import reload
+# In case we're being reloaded.
+reload(config)
+reload(plugin)
+# Add more reloads here if you add third-party modules and want them to be
+# reloaded when this plugin is reloaded. Don't forget to import them as well!
+
+if world.testing:
+ from . import test
+
+Class = plugin.Class
+configure = config.configure
+
+
+# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
diff --git a/Manpages/config.py b/Manpages/config.py
new file mode 100644
index 0000000..b0ab3ff
--- /dev/null
+++ b/Manpages/config.py
@@ -0,0 +1,36 @@
+###
+# Copyright (c) 2021, B. Watson
+# All rights reserved.
+#
+#
+###
+
+from supybot import conf, registry
+try:
+ from supybot.i18n import PluginInternationalization
+ _ = PluginInternationalization('Manpages')
+except:
+ # Placeholder that allows to run the plugin on a bot
+ # without the i18n module
+ _ = lambda x: x
+
+
+def configure(advanced):
+ # This will be called by supybot to configure this module. advanced is
+ # a bool that specifies whether the user identified themself as an advanced
+ # user or not. You should effect your configuration by manipulating the
+ # registry as appropriate.
+ from supybot.questions import expect, anything, something, yn
+ conf.registerPlugin('Manpages', True)
+
+
+Manpages = conf.registerPlugin('Manpages')
+# This is where your configuration variables (if any) should go. For example:
+# conf.registerGlobalValue(Manpages, 'someConfigVariableName',
+# registry.Boolean(False, _("""Help for someConfigVariableName.""")))
+
+conf.registerGlobalValue(Manpages, 'dbpath',
+ registry.String("/home/slackfacts/supybot/Manpages.sqlite3", _("""Path to sqite3 database.""")))
+
+conf.registerGlobalValue(Manpages, 'maxresults',
+ registry.Integer(5, _("""Maximum number of results to send to client.""")))
diff --git a/Manpages/local/__init__.py b/Manpages/local/__init__.py
new file mode 100644
index 0000000..e86e97b
--- /dev/null
+++ b/Manpages/local/__init__.py
@@ -0,0 +1 @@
+# Stub so local is a module, used for third-party modules
diff --git a/Manpages/plugin.py b/Manpages/plugin.py
new file mode 100644
index 0000000..e3913d1
--- /dev/null
+++ b/Manpages/plugin.py
@@ -0,0 +1,99 @@
+###
+# Copyright (c) 2021, B. Watson
+# All rights reserved.
+#
+#
+###
+
+import os
+import subprocess
+import sys
+import re
+import sqlite3
+
+from supybot import utils, plugins, ircutils, callbacks
+from supybot.commands import *
+import supybot.utils.minisix as minisix
+
+try:
+ from supybot.i18n import PluginInternationalization
+ _ = PluginInternationalization('Manpages')
+except ImportError:
+ # Placeholder that allows to run the plugin on a bot
+ # without the i18n module
+ _ = lambda x: x
+
+
+class Manpages(callbacks.Plugin):
+ """Provides Unix manpage lookups"""
+ threaded = True
+
+ db = None
+
+ def InitDB(self):
+ if self.db is None:
+ filename = self.registryValue('dbpath')
+ if(os.path.exists(filename)):
+ self.db = sqlite3.connect(filename)
+ return self.db
+
+ # man() is a *very* limited subset of what the real
+ # man command does. Should maybe be called whatis instead,
+ # use the Aka plugin to create an alias:
+ # load Aka
+ # aka add whatis man $*
+ def man(self, irc, msg, args, sect_or_page, page):
+ """ [<section>|-k] <page>
+
+ Look up man pages and show their summaries. Without -k, searches
+ man pages by name (same as the OS "whatis" or "man -f" commands).
+ With -k, also searches descriptions (same as OS "man -k" or "apropos").
+ With <section>, limits search to a single man section (otherwise all
+ sections are searched).
+ """
+
+ db = self.InitDB();
+ if db is None:
+ irc.error("manpage database doesn't exist", Raise=True)
+
+ maxresults = self.registryValue('maxresults')
+ if msg.channel is None:
+ # private message, increase limit
+ maxresults *= 5
+
+ cursor = db.cursor()
+
+ errmsg = "No manual entry for "
+
+ selectfrom = "select page, section, desc from whatis "
+ orderby = " order by section "
+ limit = " limit " + str(maxresults + 1) + " "
+
+ if page is None:
+ cursor.execute(selectfrom + "where page glob ?" + orderby + limit, (sect_or_page,))
+ errmsg = errmsg + sect_or_page
+ else:
+ if sect_or_page == "-k":
+ glob = "*" + page + "*"
+ cursor.execute(selectfrom + "where page glob ? or desc glob ? " + orderby + limit, (glob, glob))
+ errmsg = "No man pages matching " + page
+ else:
+ cursor.execute(selectfrom + "where section=? and page glob ? " + orderby + limit, (sect_or_page, page))
+ errmsg = errmsg + page + " in section " + sect_or_page
+
+ result = cursor.fetchall()
+
+ lines = []
+
+ if len(result) == 0:
+ irc.reply(errmsg)
+ else:
+ for (page, section, desc) in result:
+ lines.append(ircutils.bold(page + "(" + section + ")") + ": " + desc)
+ if(len(result) > maxresults):
+ lines.append("[too many results, only showing first " + str(maxresults) + "]")
+ irc.replies(lines, joiner=' | ')
+
+ man = thread(wrap(man, ['somethingWithoutSpaces', optional('somethingWithoutSpaces')]))
+
+Class = Manpages
diff --git a/Manpages/plugin.py.old b/Manpages/plugin.py.old
new file mode 100644
index 0000000..b60b4dd
--- /dev/null
+++ b/Manpages/plugin.py.old
@@ -0,0 +1,98 @@
+###
+# Copyright (c) 2021, B. Watson
+# All rights reserved.
+#
+#
+###
+
+import os
+import subprocess
+import sys
+import re
+
+from supybot import utils, plugins, ircutils, callbacks
+from supybot.commands import *
+import supybot.utils.minisix as minisix
+
+try:
+ from supybot.i18n import PluginInternationalization
+ _ = PluginInternationalization('Manpages')
+except ImportError:
+ # Placeholder that allows to run the plugin on a bot
+ # without the i18n module
+ _ = lambda x: x
+
+
+# The regex stuff is to turn this:
+# ls (1) - list directory contents
+# into this:
+# ls(1) - list directory contents
+
+class Manpages(callbacks.Plugin):
+ """Provides Unix manpage and whereis lookups"""
+ threaded = True
+
+ re_sub_spaces = re.compile(r"\s\s+")
+ re_sub_paren = re.compile(r"\s\(")
+
+ def Command(self, irc, msg, args):
+ try:
+ with open(os.devnull) as null:
+ child = subprocess.Popen(args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ stdin=null)
+ except OSError as e:
+ irc.error('Man page lookup failed.', Raise=True)
+ (out, err) = child.communicate()
+ child.wait()
+ out = out + err
+ if minisix.PY3:
+ lines = [i.decode('utf-8').rstrip() for i in out.splitlines()]
+ lines = list(map(str, lines))
+ else:
+ lines = out.splitlines()
+ lines = list(map(str.rstrip, lines))
+ lines = filter(None, lines)
+ return lines
+
+ # man() is a *very* limited subset of what the real
+ # man command does. Should maybe be called whatis instead,
+ # use the Aka plugin to create an alias:
+ # load Aka
+ # aka add whatis man $*
+ def man(self, irc, msg, args, sect_or_page, page):
+ """ Usage: man <section> <page>, or man <page> for all sections """
+
+ cmd = [ '/usr/bin/man', '-f' ]
+
+ try:
+ sect = int(sect_or_page)
+ if page is None:
+ irc.error("Missing <page>", Raise=True)
+ else:
+ cmd.append("-s")
+ cmd.append(sect_or_page)
+ cmd.append(page)
+ except ValueError:
+ if page is None:
+ cmd.append(sect_or_page)
+ else:
+ irc.error("Invalid <section>", Raise=True)
+
+ lines = self.Command(irc, msg, cmd)
+
+ lines = [self.re_sub_spaces.sub(' ', i) for i in lines]
+ lines = [self.re_sub_paren.sub('(', i) for i in lines]
+ irc.replies(lines, joiner=' | ')
+
+ man = thread(wrap(man, ['somethingWithoutSpaces', optional('somethingWithoutSpaces')]))
+
+ # whereis() is a limited subset of the real whereis.
+ def whereis(self, irc, msg, args, name):
+ """ <name> """
+ lines = self.Command(irc, msg, [ '/usr/bin/whereis', name ])
+ irc.replies(lines, joiner=' | ')
+ whereis = thread(wrap(whereis, ['somethingWithoutSpaces']))
+
+Class = Manpages
diff --git a/Manpages/test.py b/Manpages/test.py
new file mode 100644
index 0000000..53e803a
--- /dev/null
+++ b/Manpages/test.py
@@ -0,0 +1,15 @@
+###
+# Copyright (c) 2021, B. Watson
+# All rights reserved.
+#
+#
+###
+
+from supybot.test import *
+
+
+class ManpagesTestCase(PluginTestCase):
+ plugins = ('Manpages',)
+
+
+# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: