### # Copyright (c) 2021, B. Watson # All rights reserved. # # ### # TODO: add maintainer name/email to the DB. import os import glob 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('SBoTools') except ImportError: # Placeholder that allows to run the plugin on a bot # without the i18n module _ = lambda x: x class SBoTools(callbacks.Plugin): """Provides SlackBuilds.org build searches""" threaded = True db = None categories = None def getMaxResults(self, msg): maxresults = self.registryValue('maxresults') if msg.channel is None: # private message, increase limit maxresults *= 5 return maxresults 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 def getCategory(self, cat): if self.categories is None: self.categories = {} db = self.InitDB(); cursor = db.cursor() cursor.execute("select id, name from categories"); result = cursor.fetchall() for (id, name) in result: self.categories[name] = id if cat in self.categories: return self.categories[cat] else: return None def sbosearch(self, irc, msg, args, tflag, terms): """ [] | [-t] [ ...]> Search the SlackBuilds.org build database. Case-insensitive substring match. Without -t, does a search by name only. With -t, searches names, descriptions, and tags. With multiple search terms, results are ANDed together. """ category = None if(not tflag): if(len(terms) > 1): irc.error("only one search term allowed unless using -t flag", Raise=True) t = terms[0].split('/',1) if(len(t) != 1): category = self.getCategory(t[0]) if(category is None): irc.error("invalid category '" + t[0] + "'", Raise=True) terms[0] = t[1] db = self.InitDB(); cursor = db.cursor() tags = False; sql = "select distinct(b.id) from builds b, tags t " sql += "where b.id = t.build_id" if(category is not None): sql += " and b.category=" + str(category) + " " for (term) in terms: tlike = "'%" + term.replace("'", "''") + "%'" if(tflag): sql += " and (b.name like " + tlike + " or b.descrip like " + tlike + " or t.tag like " + tlike + ")" else: sql += " and b.name like " + tlike maxresults = self.getMaxResults(msg) sql += " limit " + str(maxresults + 1) cursor.execute(sql) result = cursor.fetchall() if(len(result) == 0): irc.reply("no results found") else: lines = [] for (i) in result: c2 = db.cursor() c2.execute("select b.name, c.name from builds b, categories c where b.category=c.id and b.id=?", (i[0],)) xres = c2.fetchall(); if(len(result) == 1): (name, cat) = xres[0] #irc.reply("would be showing !sboinfo " + cat + "/" + name); self.SBoInfo(irc, msg, cat + "/" + name) return; for (name, cat) in xres: lines.append(cat + "/" + name) if(len(result) > maxresults): lines.append("[too many results, only showing first " + str(maxresults) + "]") irc.replies(lines, joiner=' | ') sbosearch = thread(wrap(sbosearch, [optional(('literal', ['-t'])), many('somethingWithoutSpaces')])) def SBoInfo(self, irc, msg, catbuild): category = None build = None t = catbuild.split('/',1) if(len(t) == 1): build = catbuild else: category = self.getCategory(t[0]) if(category is None): irc.error("invalid category '" + t[0] + "'", Raise=True) build = t[1] db = self.InitDB(); cursor = db.cursor() if(category is None): cursor.execute("select b.id, b.name, c.name, b.descrip, b.version from builds b, categories c where b.category = c.id and b.name = ?", (build,)) else: cursor.execute("select b.id, b.name, c.name, b.descrip, b.version from builds b, categories c where c.id = ? and b.category = c.id and b.name = ?", (category, build,)) result = cursor.fetchall() if(len(result) == 0): irc.reply("no results found") else: lines = [] for (bid, bname, cname, bdescrip, bversion) in result: lines.append(cname + "/" + bname + " v" + bversion + ": " + bdescrip) cursor.execute("select b.name from builds b, deps d where d.build_id=? and b.id=d.depends_on", (bid,)) depres = cursor.fetchall() if(len(depres) != 0): deps = "" for (depname) in depres: deps += depname[0] + " " lines.append("deps: " + deps) irc.replies(lines, joiner=' | ') def sboinfo(self, irc, msg, args, catbuild): """ [] Show detailed information about a SBo build. The argument must be an exact match (this is not a search). """ self.SBoInfo(irc, msg, catbuild) sboinfo = thread(wrap(sboinfo, ['somethingWithoutSpaces'])) Class = SBoTools