2006-09-16 20:48:42 +00:00

448 lines
16 KiB
Python

#
# UrlGrab, version 1.0, for weechat version 0.1.6
#
# Listens to all channels for URLs, collects them in a list, and launches
# them in your favourite web server on the local host or a remote server.
#
# Usage:
#
# The /url command provides access to all UrlGrab functions. Run
# '/url help' for complete command usage.
#
# In general, use '/url list' to list the entire url list for the current
# channel, and '/url <n>' to launch the nth url in the list. For
# example, to launch the first (and most-recently added) url in the list,
# you would run '/url 1'
#
# From the server window, you must specify a specific channel for the
# list and launch commands, for example:
# /url list #weechat
# /url 3 #weechat
#
# Configuration:
#
# The '/url set' command lets you get and set the following options:
#
# historysize
# The maximum number of URLs saved per channel. Default is 10
#
# method
# Must be one of 'local' or 'remote' - Defines how URLs are launched by
# the script. If 'local', the script will run 'localcmd' on the host.
# If 'remote', the script will run 'remotessh remotehost remotecmd' on
# the local host which should normally use ssh to connect to another
# host and run the browser command there.
#
# localcmd
# The command to run on the local host to launch URLs in 'local' mode.
# The string '%s' will be replaced with the URL. The default is
# 'firefox %s'.
#
# remotessh
# The command (and arguments) used to connect to the remote host for
# 'remote' mode. The default is 'ssh -x' which will connect as the
# current username via ssh and disable X11 forwarding.
#
# remotehost
# The remote host to which we will connect in 'remote' mode. For ssh,
# this can just be a hostname or 'user@host' to specify a username
# other than your current login name. The default is 'localhost'.
#
# remotecmd
# The command to execute on the remote host for 'remote' mode. The
# default is 'bash -c "DISPLAY=:0.0 firefox %s"' Which runs bash, sets
# up the environment to display on the remote host's main X display,
# and runs firefox. As with 'localcmd', the string '%s' will be
# replaced with the URL.
#
# cmdoutput
# The file where the command output (if any) is saved. Overwritten
# each time you launch a new URL. Default is ~/.weechat/urllaunch.log
#
# Requirements:
#
# - Designed to run with weechat version 1.0.6 or better.
# http://weechat.flashtux.org/
#
# Acknowlegements:
#
# - Based on an earlier version called 'urlcollector.py' by 'kolter' of
# irc.freenode.net/#weechat Honestly, I just cleaned up the code a bit and
# made the settings a little more useful (to me).
#
# Copyright (C) 2005 Jim Ramsay <i.am@jimramsay.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
#
import os
import weechat
UC_NAME="UrlGrab"
UC_VERSION="1.0"
weechat.register (UC_NAME, UC_VERSION, "", "Url collector/launcher for weechat")
weechat.add_message_handler("privmsg", "urlGrabCheck")
weechat.add_command_handler("url", "urlGrabMain",
"Controls UrlGrab -> '/url help' for usage")
def urlGrabPrint(message):
weechat.prnt("-[%s]- %s" % ( UC_NAME, message ) )
class WeechatSetting:
def __init__(self, name, default, description = "" ):
self.name = name
self.default = default
self.description = description
test = weechat.get_plugin_config( name )
if test is None or test == "":
weechat.set_plugin_config( name, default )
class UrlGrabSettings:
def __init__(self):
self.settings = {
'historysize':WeechatSetting('historysize', '10',
"Number of URLs to keep per channel" ),
'method':WeechatSetting('method', 'local',
"""Where to launch URLs
If 'local', runs %localcmd%.
If 'remote' runs the following command:
`%remotessh% %remotehost% %remotecmd`"""),
'localcmd':WeechatSetting('localcmd', 'firefox %s',
"""Command to launch local URLs. '%s' becomes the URL.
Default 'firefox %s'"""),
'remotessh':WeechatSetting('remotessh', 'ssh -x',
"""Command (and arguments) to connect to a remote machine.
Default 'ssh -x'"""),
'remotehost':WeechatSetting('remotehost', 'localhost',
"""Hostname for remote launching
Default 'localhost'"""),
'remotecmd':WeechatSetting('remotecmd',
'bash -c \"DISPLAY=:0.0 firefox %s\"',
"""Command to launch remote URLs. '%s' becomes the URL.
Default 'bash -c \"DISPLAY=:0.0 firefox %s\"'"""),
'cmdlog':WeechatSetting('cmdlog',
'~/.weechat/urllaunch.log',
"""File where command output is saved. Overwritten each
time an URL is launched
Default '~/.weechat/urllaunch.log'""" )
}
def has(self, name):
return self.settings.has_key(name)
def names(self):
return self.settings.keys()
def description(self, name):
return self.settings[name].description
def set(self, name, value):
# Force string values only
if type(value) != type("a"):
value = str(value)
if name == "method":
if value.lower() == "remote":
weechat.set_plugin_config( 'method', "remote" )
elif value.lower() == "local":
weechat.set_plugin_config( 'method', "local" )
else:
raise ValueError( "\'%s\' is not \'local\' or \'remote\'" % value )
elif name == "localcmd":
if value.find( "%s" ) == -1:
weechat.set_plugin_config( 'localcmd', value + " %s" )
else:
weechat.set_plugin_config( 'localcmd', value )
elif name == "remotecmd":
if value.find( "%s" ) == -1:
weechat.set_plugin_config( 'remotecmd', value + " %s" )
else:
weechat.set_plugin_config( 'remotecmd', value )
elif self.has(name):
weechat.set_plugin_config( name, value )
if name == "historysize":
urlGrab.setHistorysize(int(value))
else:
raise KeyError( name )
def get(self, name):
if self.has(name):
return weechat.get_plugin_config(name)
else:
raise KeyError( name )
def prnt(self, name, verbose = True):
weechat.prnt( " %s = %s" % (name.ljust(11), self.get(name)) )
if verbose:
weechat.prnt( " -> %s" % (self.settings[name].description) )
def prntall(self):
for key in self.names():
self.prnt(key, verbose = False)
def createCmdList(self, url):
if weechat.get_plugin_config( 'method' ) == 'remote':
tmplist = weechat.get_plugin_config( 'remotessh' ).split(" ")
tmplist.append(weechat.get_plugin_config( 'remotehost' ))
tmplist.append(weechat.get_plugin_config( 'remotecmd' ) % (url))
else:
tmplist = (weechat.get_plugin_config( 'localcmd' ) % (url) ).split(" ")
return tmplist
class UrlGrabber:
def __init__(self, historysize):
# init
self.urls = {}
self.historysize = 5
# control
self.setHistorysize(historysize)
def setHistorysize(self, count):
if count > 1:
self.historysize = count
def getHistorysize(self):
return self.historysize
def addUrl(self, url, channel, server):
# check for server
if not self.urls.has_key(server):
self.urls[server] = {}
# check for chan
if not self.urls[server].has_key(channel):
self.urls[server][channel] = []
# add url
if url in self.urls[server][channel]:
self.urls[server][channel].remove(url)
self.urls[server][channel].insert(0, url)
# removing old urls
while len(self.urls[server][channel]) > self.historysize:
self.urls[server][channel].pop()
def hasIndex( self, index, channel, server ):
return self.urls.has_key(server) and \
self.urls[server].has_key(channel) and \
len(self.url[server][channel]) >= index
def hasChannel( self, channel, server ):
return self.urls.has_key(server) and \
self.urls[server].has_key(channel)
def hasServer( self, server ):
return self.urls.has_key(server)
def getUrl(self, index, channel, server):
url = ""
if self.urls.has_key(server):
if self.urls[server].has_key(channel):
if len(self.urls[server][channel]) >= index:
url = self.urls[server][channel][index-1]
return url
def prnt(self, channel, server):
found = True
if self.urls.has_key(server):
if self.urls[server].has_key(channel):
urlGrabPrint(channel + "@" + server)
if len(self.urls[server][channel]) > 0:
i = 1
for url in self.urls[server][channel]:
weechat.prnt(" --> " + str(i) + " : " + url)
i += 1
else:
found = False
elif channel == "*":
for channel in self.urls[server].keys():
self.prnt(channel, server)
else:
found = False
else:
found = False
if not found:
urlGrabPrint(channel + "@" + server + ": no entries")
def urlGrabParsemsg(command):
infos = command.split(" ")
chan = infos[2]
message = " ".join(infos[3:])[1:]
return (chan, message)
def urlGrabCheck(server, args):
global urlGrab
chan, message = urlGrabParsemsg(args)
# Ignore output from 'tinyurl.py'
if message.startswith( "[AKA] http://tinyurl.com" ):
return weechat.PLUGIN_RC_OK
# Check for URLs
for word in message.split(" "):
if word[0:7] == "http://" or \
word[0:8] == "https://" or \
word[0:6] == "ftp://":
urlGrab.addUrl(word, chan, server)
# check for any dead children and clean them up
while True:
try:
mypid, status = os.waitpid(0, os.WNOHANG)
except:
break
else:
if mypid <= 0:
break
return weechat.PLUGIN_RC_OK
def urlGrabOpen(index, channel = None):
global urlGrab, urlGrabSettings
server = weechat.get_info("server")
if channel is None or channel == "":
channel = weechat.get_info("channel")
if channel == "":
urlGrabPrint( "No current channel, you must specify one" )
elif not urlGrab.hasChannel( channel, server ):
urlGrabPrint("No URL found - Invalid channel")
else:
if index <= 0:
urlGrabPrint("No URL found - Invalid index")
return
url = urlGrab.getUrl(index, channel, server)
if url == "":
urlGrabPrint("No URL found - Invalid index")
else:
urlGrabPrint("loading %s %sly" % (url, urlGrabSettings.get("method")))
logfile = os.path.expanduser( urlGrabSettings.get( 'cmdlog' ) )
argl = urlGrabSettings.createCmdList( url )
dout = open(logfile, "w")
dout.write( "UrlGrab: Running '%s'\n" % (" ".join(argl)) )
dout.close()
try:
childpid = os.fork()
except:
urlGrabPrint("Fork failed!")
if childpid == 0:
# in the child- Detach from tty and Exec the command
logfile = os.path.expanduser( urlGrabSettings.get( 'cmdlog' ) )
din = open("/dev/null", "r")
dout = open(logfile, "a")
try:
# Redirect IO for the child
os.dup2(din.fileno(), 0)
os.dup2(dout.fileno(), 1)
os.dup2(dout.fileno(), 2)
except:
dout.write( "UrlGrab: IO Redirection failed\n" )
dout.close()
din.close()
sys.exit(1)
try:
# Actually run the command
os.execvp( argl[0], argl )
except:
dout.write( "UrlGrab: Exec failed" )
dout.close()
din.close()
sys.exit(1)
else:
# In the parent - Don't wait now, wait later.
return
def urlGrabList( args ):
global urlGrab
channel = ""
if len(args) == 0:
channel = weechat.get_info("channel")
else:
channel = args[0]
if channel == "" or channel == "all":
channel = "*"
urlGrab.prnt(channel, weechat.get_info("server"))
def urlGrabHelp():
weechat.prnt("")
urlGrabPrint("Help")
weechat.prnt(" Usage : ")
weechat.prnt(" /url help")
weechat.prnt(" -> display this help")
weechat.prnt(" /url list [channel]")
weechat.prnt(" -> display list of recorded urls in the specified channel")
weechat.prnt(" If no channel is given, lists the current channel")
weechat.prnt(" /url set [name [[=] value]]")
weechat.prnt(" -> set or get one of the parameters")
weechat.prnt(" /url n [channel]")
weechat.prnt(" -> launch the nth url in `/url list`")
weechat.prnt(" or the nth url in the specified channel")
weechat.prnt("")
def urlGrabMain(server, args):
largs = args.split(" ")
#strip spaces
while '' in largs:
largs.remove('')
while ' ' in largs:
largs.remove(' ')
if len(largs) == 0:
urlGrabHelp()
else:
if largs[0] == 'help':
urlGrabHelp()
elif largs[0] == 'list':
urlGrabList( largs[1:] )
elif largs[0] == 'set':
try:
if (len(largs) == 1):
urlGrabPrint( "Available settings:" )
urlGrabSettings.prntall()
elif (len(largs) == 2):
name = largs[1]
urlGrabPrint( "Get %s" % name )
urlGrabSettings.prnt( name )
elif (len(largs) > 2):
name = largs[1]
value = None
if( largs[2] != "="):
value = " ".join(largs[2:])
elif( largs > 3 and largs[2] == "=" ):
value = " ".join(largs[3:])
urlGrabPrint( "set %s = \'%s\'" % (name, value) )
if value is not None:
try:
urlGrabSettings.set( name, value )
urlGrabSettings.prnt( name, verbose=False )
except ValueError, msg:
weechat.prnt( " Failed: %s" % msg )
else:
weechat.prnt( " Failed: No value given" )
except KeyError:
weechat.prnt( " Failed: Unrecognized parameter '%s'" % name )
else:
try:
no = int(largs[0])
if len(largs) > 1:
urlGrabOpen(no, largs[1])
else:
urlGrabOpen(no)
except ValueError:
urlGrabPrint( "Unknown command '%s'. Try '/url help' for usage" % largs[0])
return weechat.PLUGIN_RC_OK
# Initialize global variables
urlGrabSettings = UrlGrabSettings()
urlGrab = UrlGrabber( urlGrabSettings.get('historysize') )