summaryrefslogtreecommitdiff
path: root/scripts/python
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/python')
-rw-r--r--scripts/python/auto_op.py80
-rw-r--r--scripts/python/autoauth.py245
-rw-r--r--scripts/python/autoaway.py153
-rw-r--r--scripts/python/catapult.py429
-rw-r--r--scripts/python/ctcp.py156
-rw-r--r--scripts/python/gimmicks.py99
-rw-r--r--scripts/python/mpdnp.py101
-rw-r--r--scripts/python/onattach.py445
-rw-r--r--scripts/python/shell.py136
-rw-r--r--scripts/python/theme.py197
-rw-r--r--scripts/python/tinyurl.py334
-rw-r--r--scripts/python/todo.py69
-rw-r--r--scripts/python/toggle.py131
-rw-r--r--scripts/python/uname.py18
-rw-r--r--scripts/python/urlgrab.py447
15 files changed, 3040 insertions, 0 deletions
diff --git a/scripts/python/auto_op.py b/scripts/python/auto_op.py
new file mode 100644
index 000000000..77da3a1ba
--- /dev/null
+++ b/scripts/python/auto_op.py
@@ -0,0 +1,80 @@
+# --------------------------------------------------------------------
+#
+# Copyright (c) 2006 by Jean-Marie Favreau <jm@jmtrivial.info>
+#
+# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# --------------------------------------------------------------------
+# This script automatically op and voice some nicks
+# --------------------------------------------------------------------
+
+
+import weechat
+import re
+
+
+# regexp list for /op
+U_OP = { "server": { "#chan" : [ "nick1@domain.com", "nick2.*@.*"] } }
+
+# chan list where all nicks are /voice
+C_VOICE = { "server": [ "#chan1", "#chan2" ] }
+
+
+def auto_op(server, args):
+ '''Handle connect'''
+ result = weechat.PLUGIN_RC_OK
+ # first, watch if need /op
+ if U_OP.has_key(server):
+ chans = U_OP[server]
+ try:
+ # find nick and channel
+ nothing, user, channel = args.split(":")
+ nick, next = user.split("!")
+ except ValueError:
+ result = weechat.PLUGIN_RC_KO
+ else:
+ if chans.has_key(channel):
+ users = chans[channel]
+ for userExpr in users:
+ if re.search("^n=" + userExpr, next):
+ weechat.command("/op "+nick, channel, server) # op nick
+ weechat.prnt("[op] "+nick+" on "+channel+"("+server+")") # print
+ return result # exit
+
+
+ # then watch if need /voice
+ if C_VOICE.has_key(server):
+ chans = C_VOICE[server]
+ try:
+ # find nick and channel
+ nothing, user, channel = args.split(":")
+ nick, next = user.split("!")
+ except ValueError:
+ result = weechat.PLUGIN_RC_KO
+ else:
+ if channel in chans:
+ weechat.command("/voice "+nick, channel, server) # voice nick
+ weechat.prnt("[voice] "+nick+" on "+channel+"("+server+")") # print info
+ return result # exit
+
+ # otherwise: nothing to do
+ return result
+
+
+# register and add function to weechat
+weechat.register("auto_op", "0.2", "", "auto op plug-in for weechat")
+weechat.add_message_handler ("join", "auto_op")
+
+
diff --git a/scripts/python/autoauth.py b/scripts/python/autoauth.py
new file mode 100644
index 000000000..6480cd73d
--- /dev/null
+++ b/scripts/python/autoauth.py
@@ -0,0 +1,245 @@
+# -*- coding: iso-8859-1 -*-
+
+# =============================================================================
+# autoauth.py (c) October 2005 by kolter <kolter+dev@openics.org>
+# Python script for WeeChat.
+#
+# Licence : GPL v2
+# Description : Permits to auto-authenticate when changing nick
+# Syntax : try /auth help to get help on this script
+#
+#
+# ### changelog ###
+#
+# * version 0.5
+# - fix bug when script script is run for first time
+# - rewrite half script to improve access to settings
+# - add a feature to permit to run command(s) when identified
+# - add completion for commands
+# * version 0.4
+# - use set_plugin_config and get_plugin_config to read ans save settings
+# - remove deprecated import
+# * version 0.3
+# - add return codes
+# * version 0.2
+# - correct weechatdir with weechat_dir while using weechat.get_info
+# * version 0.1 :
+# - first release
+#
+# =============================================================================
+
+
+VERSION="0.5"
+NAME="autoauth"
+
+import weechat
+
+weechat.register (NAME, VERSION, "", "Auto authentification while changing nick")
+weechat.add_message_handler("NOTICE", "auth_notice_check")
+weechat.add_command_handler(
+ "auth",
+ "auth_command",
+ "Auto authentification while changing nick",
+ "{ add $nick $pass [$server=current] | del $nick [$server=current] | list | cmd [$command [$server=current]] }",
+ " add : add authorization for $nick with password $pass for $server\n"
+ " del : del authorization for $nick for $server\n"
+ " list : list all authorization settings\n"
+ " cmd : command(s) (separated by '|') to run when identified for $server\n"
+ " %n will be replaced by current nick in each command",
+ "add|del|list|cmd %- %S %S"
+ )
+
+def auth_cmdlist():
+ cmd = ''
+ cmds = weechat.get_plugin_config("commands")
+ if cmds == '':
+ weechat.prnt("[%s] commands (empty)" % (NAME))
+ else:
+ weechat.prnt("[%s] commands (list)" % (NAME))
+ for c in cmds.split("####"):
+ weechat.prnt(" --> %s : '%s' " % (c.split(":::")[0], c.split(":::")[1]))
+
+def auth_cmdget(server):
+ cmd = ''
+ cmds = weechat.get_plugin_config("commands")
+ if cmds != '':
+ for c in cmds.split("####"):
+ if c.find(":::") != -1:
+ if c.split(":::")[0] == server:
+ cmd = ":::".join(c.split(":::")[1:])
+ break
+ return cmd
+
+def auth_cmdset(server, command):
+ cmds = weechat.get_plugin_config("commands")
+
+ found = False
+ conf = []
+ if cmds != '':
+ for c in cmds.split("####"):
+ if c.find(":::") != -1:
+ if c.split(":::")[0] == server:
+ found = True
+ conf.append("%s:::%s" % (server, command))
+ else:
+ conf.append(c)
+ if not found:
+ conf.append("%s:::%s" % (server, command))
+
+ weechat.set_plugin_config("commands", "####".join(conf))
+ weechat.prnt("[%s] command '%s' successfully added for server %s" % (NAME, command, server))
+
+def auth_cmdunset(server):
+ cmds = weechat.get_plugin_config("commands")
+
+ found = False
+ conf = []
+ if cmds != '':
+ for c in cmds.split("####"):
+ if c.find(":::") != -1:
+ if c.split(":::")[0] != server:
+ conf.append(c)
+ else:
+ found = True
+ if found:
+ weechat.prnt("[%s] command for server '%s' successfully removed" % (NAME, server))
+ weechat.set_plugin_config("commands", "####".join(conf))
+
+def auth_cmd(args, server):
+ if server == '':
+ if args == '':
+ auth_cmdlist()
+ else:
+ weechat.prnt("[%s] error while setting command, can't find a server" % (NAME))
+ else:
+ if args == '':
+ auth_cmdunset(server)
+ else:
+ auth_cmdset(server, args)
+
+def auth_list():
+ data = weechat.get_plugin_config("data")
+
+ if data == "":
+ weechat.prnt("[%s] accounts (empty)" % (NAME))
+ else:
+ weechat.prnt("[%s] accounts (list)" % (NAME))
+ for e in data.split(","):
+ if e.find("=") == -1:
+ continue
+ (serv_nick, passwd) = e.split("=")
+ (server, nick) = serv_nick.split(".")
+ weechat.prnt(" --> %s@%s " % (nick, server))
+
+def auth_notice_check(server, args):
+ if args.find("If this is your nickname, type /msg NickServ") != -1 or args.find("This nickname is registered and protected.") != -1 :
+ passwd = auth_get(weechat.get_info("nick"), server)
+ if passwd != None:
+ weechat.command("/quote nickserv identify %s" % (passwd), "", server)
+ commands = auth_cmdget(server)
+ if commands != '':
+ for c in commands.split("|"):
+ weechat.command(c.strip().replace("%n", weechat.get_info('nick')))
+
+ return weechat.PLUGIN_RC_OK
+
+def auth_del(the_nick, the_server):
+ data = weechat.get_plugin_config("data")
+
+ found = False
+ conf = []
+ for e in data.split(","):
+ if e.find("=") == -1:
+ continue
+ (serv_nick, passwd) = e.split("=")
+ (server, nick) = serv_nick.split(".")
+ if the_nick == nick and the_server == server:
+ found = True
+ else:
+ conf.append("%s.%s=%s" % (server, nick, passwd))
+
+ if found:
+ weechat.set_plugin_config("data", ",".join(conf))
+ weechat.prnt("[%s] nick '%s@%s' successfully remove" % (NAME, the_nick, the_server))
+ else:
+ weechat.prnt("[%s] an error occured while removing nick '%s@%s' (not found)" % (NAME, the_nick, the_server))
+
+def auth_add(the_nick, the_passwd, the_server):
+ data = weechat.get_plugin_config("data")
+
+ found = False
+ conf = []
+ for e in data.split(","):
+ if e.find("=") == -1:
+ continue
+ (serv_nick, passwd) = e.split("=")
+ (server, nick) = serv_nick.split(".")
+ if the_nick == nick and the_server == server:
+ passwd = the_passwd
+ found = True
+ conf.append("%s.%s=%s" % (server, nick, passwd))
+
+ if not found:
+ conf.append("%s.%s=%s" % (the_server, the_nick, the_passwd))
+
+ weechat.set_plugin_config("data", ",".join(conf))
+ weechat.prnt("[%s] nick '%s@%s' successfully added" % (NAME, the_nick, the_server))
+
+def auth_get(the_nick, the_server):
+ data = weechat.get_plugin_config("data")
+
+ for e in data.split(","):
+ if e.find("=") == -1:
+ continue
+ (serv_nick, passwd) = e.split("=")
+ (server, nick) = serv_nick.split(".")
+ if the_nick == nick and the_server == server:
+ return passwd
+ return None
+
+def auth_command(server, args):
+ list_args = args.split(" ")
+
+ #strip spaces
+ while '' in list_args:
+ list_args.remove('')
+ while ' ' in list_args:
+ list_args.remove(' ')
+
+ if len(list_args) == 0:
+ weechat.command("/help auth")
+ elif list_args[0] not in ["add", "del", "list", "cmd"]:
+ weechat.prnt("[%s] bad option while using /auth command, try '/help auth' for more info" % (NAME))
+ elif list_args[0] == "cmd":
+ if len(list_args[1:]) == 1 and list_args[1] in weechat.get_server_info().keys():
+ auth_cmd("", list_args[1])
+ elif len(list_args[1:]) == 1:
+ auth_cmd(list_args[1], weechat.get_info('server'))
+ elif len(list_args[1:]) >= 2:
+ if list_args[-1] in weechat.get_server_info().keys():
+ auth_cmd(" ".join(list_args[1:-1]), list_args[-1])
+ else:
+ auth_cmd(" ".join(list_args[1:]), weechat.get_info('server'))
+ else:
+ auth_cmd(" ".join(list_args[1:]), weechat.get_info(server))
+ elif list_args[0] == "list":
+ auth_list()
+ elif list_args[0] == "add":
+ if len(list_args) < 3 or (len(list_args) == 3 and weechat.get_info("server") == ''):
+ weechat.prnt("[%s] bad option while using /auth command, try '/help auth' for more info" % (NAME))
+ else:
+ if len(list_args) == 3:
+ auth_add(list_args[1], list_args[2], weechat.get_info("server"))
+ else:
+ auth_add(list_args[1], list_args[2], list_args[3])
+ elif list_args[0] == "del":
+ if len(list_args) < 2:
+ weechat.prnt("[%s] bad option while using /auth command, try '/help auth' for more info" % (NAME))
+ else:
+ if len(list_args) == 2:
+ auth_del(list_args[1], weechat.get_info("server"))
+ else:
+ auth_del(list_args[1], list_args[2])
+ else:
+ pass
+ return weechat.PLUGIN_RC_OK
diff --git a/scripts/python/autoaway.py b/scripts/python/autoaway.py
new file mode 100644
index 000000000..b61d74dfe
--- /dev/null
+++ b/scripts/python/autoaway.py
@@ -0,0 +1,153 @@
+# --------------------------------------------------------------------
+#
+# Copyright (c) 2006 by Gwenn Gueguen <weechat@grumly.info>
+#
+# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# --------------------------------------------------------------------
+# This script automatically sets away after a period of inactivity
+# --------------------------------------------------------------------
+
+
+import weechat
+
+
+"""
+/autoaway [time [message]]
+
+/autoaway whithout any parameter disables autoaway
+
+Script config:
+ time:
+ number of minutes of inactivity after which a user will be marked as away
+ message:
+ message that will be passed to the /away command
+ enabled:
+ is autoaway enabled ?
+"""
+
+
+SCRIPT_NAME="autoaway"
+SCRIPT_VERSION="0.2"
+SCRIPT_DESC="autoaway script for weechat"
+
+
+# Names of the settings
+CONFIG_TIME="time"
+CONFIG_MESSAGE="message"
+CONFIG_ENABLED="enabled"
+
+# Name of the command
+CMD_AUTOAWAY="autoaway"
+
+# Default settings
+DEFAULT_TIME="15"
+DEFAULT_MESSAGE="idle"
+
+# Interval (in seconds) between checks
+TIMER_VALUE=15
+
+
+def print_settings():
+ weechat.prnt("AutoAway settings:")
+ weechat.prnt(" time: %s minute(s)" % weechat.get_plugin_config(CONFIG_TIME))
+ weechat.prnt(" message: %s" % weechat.get_plugin_config(CONFIG_MESSAGE))
+ if weechat.get_plugin_config(CONFIG_ENABLED) == "true":
+ weechat.prnt(" enabled")
+ else:
+ weechat.prnt(" disabled")
+
+
+def autoaway(server, args):
+ weechat.remove_timer_handler("timer_handler")
+
+ params = args.split(None, 1)
+ if len(params) == 0:
+ weechat.set_plugin_config(CONFIG_ENABLED, "false")
+ else:
+ weechat.set_plugin_config(CONFIG_ENABLED, "true")
+ weechat.set_plugin_config(CONFIG_TIME, params[0])
+ if len(params) > 1:
+ weechat.set_plugin_config(CONFIG_MESSAGE, params[1])
+
+ previous_inactivity = int(weechat.get_info("inactivity"))
+ weechat.add_timer_handler(TIMER_VALUE, "timer_handler")
+
+ print_settings()
+
+ return weechat.PLUGIN_RC_OK
+
+
+def timer_handler():
+ global previous_inactivity, previous_state
+
+ # Get current away status
+ away_flag = int(weechat.get_info("away"))
+
+ # Get number of seconds of inactivity
+ idle_time = int(weechat.get_info("inactivity"))
+
+ if away_flag == previous_state:
+ # away flag was not changed outside this script
+ if away_flag and idle_time < previous_inactivity:
+ # Inactivity was reset (or overflowed ?)
+ weechat.command("/away -all")
+ elif not away_flag and idle_time >= (60 * int(weechat.get_plugin_config(CONFIG_TIME))):
+ # Time to go away
+ weechat.command("/away -all %s" % weechat.get_plugin_config(CONFIG_MESSAGE))
+
+ previous_state = int(weechat.get_info("away"))
+ previous_inactivity = idle_time
+
+ return weechat.PLUGIN_RC_OK
+
+
+if weechat.register(SCRIPT_NAME, SCRIPT_VERSION, "", SCRIPT_DESC):
+
+ try:
+ previous_state = int(weechat.get_info("away"))
+ except ValueError:
+ previous_state = 0
+
+ # Set config to default values if undefined
+ try:
+ idle_time = int(weechat.get_plugin_config(CONFIG_TIME))
+ except ValueError:
+ weechat.set_plugin_config(CONFIG_TIME, DEFAULT_TIME)
+
+ if weechat.get_plugin_config(CONFIG_MESSAGE) == None:
+ weechat.set_plugin_config(CONFIG_MESSAGE, DEFAULT_MESSAGE)
+
+ if weechat.get_plugin_config(CONFIG_ENABLED) == None:
+ weechat.set_plugin_config(CONFIG_ENABLED, "false")
+
+
+ # Display a summary of the settings
+ print_settings()
+
+
+ # Start the timer if necessary
+ if weechat.get_plugin_config(CONFIG_ENABLED) == "true":
+ previous_inactivity = int(weechat.get_info("inactivity"))
+ weechat.add_timer_handler(TIMER_VALUE, "timer_handler")
+
+
+ weechat.add_command_handler(CMD_AUTOAWAY, "autoaway", "Set autoaway",
+ "[time [message]]",
+ "time: number of minutes before being marked as away\n"
+ + "message: away message\n"
+ + "\n"
+ + "whithout any argument, autoaway will be disabled\n")
+
diff --git a/scripts/python/catapult.py b/scripts/python/catapult.py
new file mode 100644
index 000000000..2fbd43be2
--- /dev/null
+++ b/scripts/python/catapult.py
@@ -0,0 +1,429 @@
+#!/usr/bin/env python
+"""
+Catapult by Stalwart <stlwrt@gmail.com>
+Licensed under GNU GPL 2
+"""
+
+import weechat
+import random
+
+weechat.register("Catapult", "0.1", "", "Less ordinary abuse generator")
+weechat.add_command_handler("slap", "slapper", "Creative slapper", "<target>", "", "%n")
+weechat.add_command_handler("fortune", "fortune", "Fortune cookies!")
+weechat.add_command_handler("winjoke", "winjoke", "Windoze jokes")
+weechat.add_command_handler("linjoke", "linjoke", "Linux jokes")
+weechat.add_command_handler("give", "giver", "Creative giver", "<target>", "", "%n")
+weechat.add_command_handler("hate", "hater", "Creative hater", "<target>", "", "%n")
+weechat.add_command_handler("love", "lover", "Creative lover", "<target>", "", "%n")
+weechat.add_command_handler("dance", "dancer", "Creative dancer", "<target>", "", "%n")
+
+# slapper
+def slapper(server, args):
+ objects = [
+ "a rather large squid",
+ "a hydraulic pump",
+ "a book by Stephen King",
+ "a 10mbit network card",
+ "a ladies handbag",
+ "some girl scouts",
+ "a football team",
+ "a bottle",
+ "a yellow marshmellow",
+ "a match",
+ "the queen of England",
+ "a taxi",
+ "100 feet of wire",
+ "a bag of Cheerios",
+ "a hat",
+ "a fist",
+ "the back hand",
+ "with the forehead",
+ "a computer moniter",
+ "a coconut",
+ "a microfone",
+ "a cellphone",
+ "a snowplough",
+ "a doggy",
+ "Bill Clinton",
+ "a stone",
+ "a club. With a nail in it",
+ "a small asteroid, rich in iron",
+ "a small interstellar spaceship",
+ "a fresh zuccini",
+ "a laptop",
+ "a big dictionary",
+ "a baseball bat",
+ "NeverNet",
+ "some porn",
+ "a mIRC script",
+ "a canoe",
+ "a tortoise",
+ "a horse",
+ "the book of Kells",
+ "a whale",
+ "a rubber dildo",
+ "a well groomed poodle",
+ "a channel operator",
+ "a news paper (New York Times Sunday Edition)",
+ "a gnarly werewolf",
+ "a vampire. They really suck",
+ "a perl script",
+ "a bag of doggie chow",
+ "a fat walrus",
+ "an IP adress",
+ "a catholic priest",
+ "James Dean",
+ "Ronald MacDonald (he *IS* good for something)",
+ "Autoconf version 2.13",
+ "a PRIVMSG",
+ "an email adress",
+ "some ANSI color codes",
+ "a thermonuclear weapon. Yehaw",
+ "the hitch hikers guide to the galaxy, revised edition",
+ "Nessie, the Loch Ness monster",
+ "a tuna. Still in the can! *BONK* That will leave a mark",
+ "a few fluffy pillows",
+ "a red chinese dragon",
+ "a linux-manual (signed by L. Torvalds)",
+ "Stage1",
+ "Bill Gates underpants",
+ "GM Abraham and the whole OW-Staff",
+ "Sphere 1.0",
+ "a Linuxkernel",
+ "Lenin's Collected Works",
+ "Stalin's Collected Works",
+ "a iron Tux",
+ "a glowing 23",
+ "your mum (CLEAN YOUR ROOM!)",
+ "a complete GNOME-Documentation",
+ "a Portagetree",
+ "thand[Z]'s transparent Tanga",
+ "a Kernelpanic",
+ "Windoze XP",
+ "an AK-47 (die, you imperialist dog!)",
+ "a bag full with Michael Jacksons droped noses",
+ "an NBP-Manifesto (Hail Limonew! Hail our Leader! Hail!)",
+ "an NBP-Flag (Lead us to freedom, Leader Limonew!)",
+ "Mein Kampf (Doppelausgabe, Hardcover)",
+ "Invader Zim's iron fist",
+ "some ASCII-Arts",
+ "The Family Learning Channel",
+ "GOD",
+ "Dorian Grey's picture",
+ "some unlocked Grenades *BOOM*",
+ "the Win2k Buglist",
+ "a widescreen TV (it can damage your brain!)",
+ "a chain saw",
+ "a huge tree"
+ ]
+ if args <> "":
+ weechat.command("/me slaps %s with %s." % (args, random.choice(objects)))
+ return weechat.PLUGIN_RC_OK
+ else:
+ weechat.prnt("You must specify target")
+ return weechat.PLUGIN_RC_KO
+
+# fortune cookies
+def fortune(server, args):
+ objects = [
+ "There are three kinds of people: men, women, and unix.",
+ "BOFH Excuse #118: the router thinks its a printer.",
+ "CHUBBY CHECKER just had a CHICKEN SANDWICH in downtown DULUTH!",
+ "Think big. Pollute the Mississippi.",
+ "An optimist is a man who looks forward to marriage. A pessimist is a married optimist.",
+ "There are never any bugs you haven't found yet.",
+ "It don't mean a THING if you ain't got that SWING!!",
+ "Atomic batteries to power, turbines to speed. -- Robin, The Boy Wonder",
+ "Two wrongs don't make a right, but three lefts do.",
+ "A log may float in a river, but that does not make it a crocodile.",
+ "Art is Nature speeded up and God slowed down. -- Chazal",
+ "Texas law forbids anyone to have a pair of pliers in his possession.",
+ "UFOs are for real: the Air Force doesn't exist.",
+ "Expansion means complexity; and complexity decay.",
+ "I came, I saw, I deleted all your files.",
+ "The Magic of Windows: Turns a 486 back into a PC/XT.",
+ "Our vision is to speed up time, eventually eliminating it. -- Alex Schure",
+ "Breaking Windows isn't just for kids anymore...",
+ "Neckties strangle clear thinking. -- Lin Yutang",
+ "I'm prepared for all emergencies but totally unprepared for everyday life.",
+ "Yow! I just went below the poverty line!",
+ "Break into jail and claim police brutality.",
+ "BOFH Excuse #290: The CPU has shifted, and become decentralized.",
+ "Did you hear about the model who sat on a broken bottle and cut a nice figure?",
+ "We have a equal opportunity Calculus class -- it's fully integrated.",
+ "BOFH Excuse #170: popper unable to process jumbo kernel",
+ "It's later than you think.",
+ "My Aunt MAUREEN was a military advisor to IKE & TINA TURNER!!",
+ "Everyone hates me because I'm paranoid.",
+ "When you are in it up to your ears, keep your mouth shut.",
+ "Theory is gray, but the golden tree of life is green. -- Goethe",
+ "Most Texans think Hanukkah is some sort of duck call. -- Richard Lewis",
+ "grasshopotomaus: A creature that can leap to tremendous heights... once.",
+ "It takes both a weapon, and two people, to commit a murder.",
+ "Facts are the enemy of truth. -- Don Quixote",
+ "Forty two.",
+ "BOFH Excuse #424: operation failed because: there is no message for this error (#1014)",
+ "Never leave anything to chance; make sure all your crimes are premeditated.",
+ "BOFH Excuse #60: system has been recalled",
+ "Science and religion are in full accord but science and faith are in complete discord.",
+ "A likely impossibility is always preferable to an unconvincing possibility. -- Aristotle",
+ "The angry man always thinks he can do more than he can. -- Albertano of Brescia",
+ "Hello again, Peabody here... -- Mister Peabody",
+ "Nobody ever died from oven crude poisoning.",
+ "Dogs crawl under fences... software crawls under Windows 95.",
+ "Say something you'll be sorry for, I love receiving apologies.",
+ "NOTICE: -- THE ELEVATORS WILL BE OUT OF ORDER TODAY -- (The nearest working elevator is in the building across the street.)",
+ "THERE ARE PLENTY OF BUSINESSES LIKE SHOW BUSINESS -- Bart Simpson on chalkboard in episode 1F19",
+ "Life is what happens to you while you're busy making other plans. -- John Lennon, Beautiful Boy",
+ "While having never invented a sin, I'm trying to perfect several.",
+ "Emacs, n.: A slow-moving parody of a text editor.",
+ " ... with liberty and justice for all ... who can afford it.",
+ "Princess Leia: Aren't you a little short for a stormtrooper?",
+ "The Official Colorado State Vegetable is now the 'state legislator'",
+ "Abandon the search for Truth; settle for a good fantasy.",
+ "There's nothing to writing. All you do is sit at a typewriter and open a vein. -- Red Smith",
+ "Our OS who art in CPU, UNIX be thy name. Thy programs run, thy syscalls done, In kernel as it is in user!",
+ "All hope abandon, ye who enter here! -- Dante Alighieri",
+ "The human mind ordinarily operates at only ten percent of its capacity -- the rest is overhead for the operating system.",
+ "Professor: 'If a dog craps anywhere in the universe, you can bet I won't be out of loop.'",
+ "I WILL NOT MAKE FLATUENT NOISES IN CLASS -- Bart Simpson on chalkboard in episode 7F13",
+ "Listen you donkey raping shit eater.",
+ "In specifications, Murphy's Law supersedes Ohm's.",
+ "One of Bender's kids: Our dad is a giant toy!",
+ "I am a jelly donut. I am a jelly donut.",
+ "We are all in the gutter, but some of us are looking at the stars. -- Oscar Wilde",
+ "Bender to Zoidberg: 'You're looking less nuts, crabby.'",
+ "Things will be bright in P.M. A cop will shine a light in your face.",
+ "A journey of a thousand miles begins with a cash advance.",
+ "Everything that can be invented has been invented. -- Charles Duell, Director of U.S. Patent Office, 1899",
+ "Vote anarchist.",
+ "paranoia, n.: A healthy understanding of the way the universe works.",
+ "BOFH Excuse #401: Sales staff sold a product we don't offer.",
+ "BOFH Excuse #200: The monitor needs another box of pixels.",
+ "The important thing is not to stop questioning.",
+ "Not all men who drink are poets. Some of us drink because we aren't poets.",
+ "Oh my god, dude!",
+ "BOFH Excuse #441: Hash table has woodworm",
+ "BOFH Excuse #112: The monitor is plugged into the serial port",
+ "There's so much to say but your eyes keep interrupting me.",
+ "For the next hour, WE will control all that you see and hear.",
+ "Reality continues to ruin my life. -- Calvin",
+ "The shortest distance between two points is under construction. -- Noelie Alito",
+ "BOFH Excuse #192: runaway cat on system.",
+ "My haircut is totally traditional!",
+ "You! What PLANET is this! -- McCoy, 'The City on the Edge of Forever', stardate 3134.0",
+ "BOFH Excuse #433: error: one bad user found in front of screen",
+ "Dyslexics have more fnu.",
+ "I'm not stupid, I'm not expendable, and I'M NOT GOING!",
+ "It's clever, but is it art?",
+ "His life was formal; his actions seemed ruled with a ruler.",
+ "Yeah. Except for being entirely different, they're pretty much the same.",
+ "Oh, I get it!! 'The BEACH goes on', huh, SONNY??",
+ "Ban the bomb. Save the world for conventional warfare.",
+ "Everything that you know is wrong, but you can be straightened out.",
+ "If I pull this SWITCH I'll be RITA HAYWORTH!! Or a SCIENTOLOGIST!",
+ "Tex SEX! The HOME of WHEELS! The dripping of COFFEE!! Take me to Minnesota but don't EMBARRASS me!!",
+ "clovek, ktory si ako prvy kupil fax musel byt strasny kokot.",
+ "Are you a turtle?",
+ "You will be the last person to buy a Chrysler.",
+ "If in doubt, mumble.",
+ "Nice guys don't finish nice.",
+ "You cannot use your friends and have them too.",
+ "Microsoft is to Software as McDonalds is to Cuisine.",
+ "panic: can't find /",
+ "I used to be an agnostic, but now I'm not so sure.",
+ "May your SO always know when you need a hug.",
+ "We are MicroSoft. You will be assimilated. Resistance is futile. (Attributed to B.G., Gill Bates)",
+ "Life is a whim of several billion cells to be you for a while.",
+ "BOFH Excuse #347: The rubber band broke",
+ "Death has been proven to be 99% fatal in laboratory rats.",
+ "There are only two kinds of tequila. Good and better.",
+ "C for yourself.",
+ "Tact, n.: The unsaid part of what you're thinking.",
+ "Shit Happens."
+ ]
+ weechat.command(("Wanda the Fish says: %s") % random.choice(objects))
+ return weechat.PLUGIN_RC_OK
+
+# winjoke
+def winjoke(server, args):
+ objects = [
+ "Windows NT, from the people who invented EDLIN!",
+ "Windows: Microsoft's tax on computer illiterates.",
+ "The nice thing about Windows is - It does not just crash, it displays a dialog box and lets you press 'OK' first.",
+ "Why use Windows, since there is a door?",
+ "In a world without fences who needs Gates?",
+ "Another name for a Windows tutorial is crash course!",
+ "Failure is not an option -- it comes bundled with Windows.",
+ "NT... the last two letters of bowel movement",
+ "Some software money can't buy. For everything else there's Micros~1.",
+ "Sticks and Stones may break my bones but FUD will never concern me.",
+ "Every program expands until it can send mail. ...Except Exchange. ",
+ "Microsoft: 'You've got questions. We've got dancing paperclips.'",
+ ".vbs = Virus Bearing Script?",
+ "Technology is positive when the creators put the interests of their users before their bottom line.",
+ "Have you ever noticed that at trade shows Microsoft is always the one giving away stress balls?",
+ "Do you remember when you only had to pay for windows when *you* broke them? (Submitted by Noel Maddy)",
+ "National Weather Service advice for those threatened by severe thunderstorms: 'Go inside a sturdy building and stay away from WINDOWS!' (Submitted by Ben Bullock)",
+ "Microsoft is to Software as McDonalds is to Cuisine.",
+ "Microsoft should switch to the vacuum cleaner business where people actually want products that suck. (Submitted by Bruno Bratti)",
+ "Everyone seems so impatient and angry these days. I think it's because so many people use Windows at work -- do you think you'd be Politeness Man after working on Windows 8 hrs. or more? (Submitted by Chip Atkinson)",
+ "NT 5.0 so vaporous it's in danger of being added to the periodic table as a noble gas. (Spotted in a Slashdot discussion)",
+ "My Beowulf cluster will beat your Windows NT network any day. (Submitted by wbogardt[at]gte.net)",
+ "It's no wonder they call it WinNT; WNT = VMS++; (Submitted by Chris Abbey)",
+ "Double your disk space - delete Windows! (Submitted by Albert Dorofeev)",
+ "The Edsel. New Coke. Windows 2000. All mandatory case studies for bizschool students in 2020. (From a LinuxToday post by Bear Giles)",
+ "I will never trust someone called GATES that sells WINDOWS. (Submitted by Federico Roman)",
+ "'Microsoft technology' -- isn't that an oxymoron?",
+ "MCSE == Mentally Challenged Slave of the Empire.",
+ "Windows NT -- it'll drive you buggy!",
+ "Where do you want to go today? Don't ask Microsoft for directions.",
+ "MS and Y2K: Windows 95, 98, ... and back again to 01",
+ "There's the light at the end of the the Windows.",
+ "People use dummies for crash-tests. Windows is so difficult they had to educate the dummies first -- by giving them 'Windows for Dummies' books!",
+ "Windows: The first user interface where you click Start to turn it off.",
+ "NT == No Thanks",
+ "With Windows Millennium, Microsoft was able to get the boot time down to 25 seconds. That's almost as short as it's uptime.",
+ "Windows 2000: Designed for the Internet. The Internet: Designed for UNIX.",
+ "MCSE = Minesweeper Consultant, Solitaire Expert",
+ "MCSE = Meaningless Certificate, Software Expired",
+ "I'm not a programmer, but I play one at Microsoft.",
+ "Microsoft Zen - Become one with the blue screen.",
+ "The next hot technology from Microsoft will be object-oriented assembly."
+ ]
+ weechat.command(("Wanda the Fish says: %s") % random.choice(objects))
+ return weechat.PLUGIN_RC_OK
+
+# linjoke
+def linjoke(server, args):
+ objects = [
+ "Got Linux?",
+ "Microsoft gives you Windows... Linux gives you the whole house.",
+ "Linux, DOS, Windows NT -- The Good, the Bad, and the Ugly",
+ "Linux: the operating system with a CLUE... Command Line User Environment",
+ "If Bill Gates is the Devil then Linus Torvalds must be the Messiah.",
+ "Linux. Where do you want to go tomorrow?",
+ "Linux: The choice of a GNU generation",
+ "When you say I wrote a program that crashed Windows, people just stare at you blankly and say Hey, I got those with the system, *for free*. -- Linus Torvalds",
+ "We all know Linux is great...it does infinite loops in 5 seconds. -- Linus Torvalds",
+ "Some people have told me they dont think a fat penguin really embodies the grace of Linux, which just tells me they have never seen a angry penguin charging at them in excess of 100mph. Theyd be a lot more careful about what they say if they had. -- Linus Torvalds",
+ "Veni, vidi, Linux!",
+ "Type cat vmlinuz > /dev/audio to hear the Voice of God.",
+ "Linux: Because a PC is a terrible thing to waste.",
+ "Linux: Because rebooting is for adding new hardware",
+ "We are Linux. Resistance is measured in Ohms.",
+ "Free Software: the Software by the People, of the People and for the People. Develop! Share! Enhance! and Enjoy! (Submitted by Andy Tai)",
+ "Get it up, keep it up... LINUX: Viagra for the PC. (Submitted by Chris Abbey)",
+ "Peace, Love and Compile the kernel.... (Submitted by Justin L. Herreman)",
+ "Free your software, and your ass will follow",
+ "Reset button? Which reset button? - Linux, the OS that never sleeps.",
+ "Linux: Where do you want to GO... Oh, Im already there!",
+ "Windows contains FAT. Use Linux -- you wont ever have to worry about your weight.",
+ "Oh My God! They Killed init! You Bastards!",
+ "Unix: Where /sbin/init is still Job 1."
+ ]
+ weechat.command(("Wanda the Fish says: %s") % random.choice(objects))
+ return weechat.PLUGIN_RC_OK
+
+# giver
+def giver(server, args):
+ objects = [
+ "a binary four",
+ "a nice cup of SHUT THE FUCK UP",
+ "an asskick",
+ "a sign: 'Please kill yourself'",
+ "a sign: 'Please go home now'",
+ "an unlocked Grenade *tick tick BOOM*",
+ "a gun - do it for mankind!"
+
+ ]
+ if args <> "":
+ weechat.command("/me gives %s %s." % (args, random.choice(objects)))
+ return weechat.PLUGIN_RC_OK
+ else:
+ weechat.prnt("You must specify target")
+ return weechat.PLUGIN_RC_KO
+
+# hater
+def hater(server, args):
+ objects = [
+ "so much, that he spits hellfire",
+ "so much, that he want's to shoot someone",
+ "SOOOO MUUUUCH!!!"
+
+ ]
+ if args <> "":
+ weechat.command("/me hates %s %s." % (args, random.choice(objects)))
+ return weechat.PLUGIN_RC_OK
+ else:
+ weechat.prnt("You must specify target")
+ return weechat.PLUGIN_RC_KO
+
+# lover
+def lover(server, args):
+ actions = [
+ "a *mwah*",
+ "a wet kiss",
+ "a tight and long hug",
+ "an ass-squeeze",
+ "a tight hug",
+ "a wet kiss",
+ "a nice, tight hug",
+ "a kiss on the cheek",
+ "a wet, french kiss",
+ "a kiss",
+ "a hug",
+ "sex",
+ "sweet romance",
+ "some groping",
+ "bed actions",
+ "oral sex",
+ "a porn-tape",
+ "anal love",
+ ]
+ if args <> "":
+ weechat.command("/me cheers %s with %s.." % (args, random.choice(actions)))
+ return weechat.PLUGIN_RC_OK
+ else:
+ weechat.prnt("You must specify target")
+ return weechat.PLUGIN_RC_KO
+
+# dancer
+def dancer(server, args):
+ objects = [
+ "used condoms",
+ "condoms",
+ "used tampons",
+ "tampons",
+ "roses",
+ "rosebuds",
+ "rice",
+ "uncooked rice",
+ "bananas",
+ "little pieces of paper with the text *YAY!* on",
+ "little pieces of paper with the text *w00t!* on",
+ "little pieces of paper with the text *WOOHOO!* on",
+ "little pieces of paper with the text *Kiss my cheek!* on",
+ "coconuts with faces on",
+ "little pieces of paper with the text *LOVE ROCKS!* on",
+ "little pieces of paper with the text *LETS HAVE SEX!* on",
+ "little pieces of paper with the text *GOD BLESS AMERICA!* on",
+ "balloons with faces on",
+ "balloons",
+ "chocolate cakes",
+ "english teachers",
+ "pr0n magazines",
+ "vietnamese kids",
+ "snowballs",
+ "rocks",
+ "Michael Jackson (naked)",
+ "unlocked Grenades *BOOM*",
+ "Nine Inch Nails",
+ "Bodyparts (bloody, wet & sexy)",
+ ]
+ if args <> "":
+ weechat.command("/me dances around %s throwing %s.." % (args, random.choice(objects)))
+ return weechat.PLUGIN_RC_OK
+ else:
+ weechat.prnt("You must specify target")
+ return weechat.PLUGIN_RC_KO
diff --git a/scripts/python/ctcp.py b/scripts/python/ctcp.py
new file mode 100644
index 000000000..9e4679cb2
--- /dev/null
+++ b/scripts/python/ctcp.py
@@ -0,0 +1,156 @@
+"""
+ :Author: Henning Hasemann <hhasemann [at] web [dot] de>
+ :Updated: Daga <daga [at] daga [dot] dyndns [dot] org>
+
+ :What it does:
+ With this script you can configure weechat
+ to give custom responses to CTCP-Requests.
+
+ :Usage:
+ Load this file somehow.
+ You can configure replies to CTCP-requests
+ with the /set_ctcp - command. (examples below)
+
+ Released under GPL license.
+
+ Hope you enjoy it :-)
+ -- Henning aka asmanian
+"""
+
+version = "0.8"
+history = """
+ 0.1 initial
+ 0.2
+ - now displays a "CTCP FOOBAR received from ..."
+ 0.3
+ - now /help set_ctcp is available
+ 0.4
+ - corrected a few typos
+ - made special variables (e.g. version) easier to use
+ 0.5
+ - removed debugging messages
+ 0.6
+ - bugfix (sometimes /set_ctcp did not work)
+ 0.7 (Daga)
+ - added multi-server support
+ 0.8
+ - fixed on_msg (occasionally caused a minor fault)
+"""
+
+short_syntax = """[REQUEST ANSWER]"""
+
+syntax = """ Examples:
+
+ /set_ctcp
+ show settings for common CTCP-Requests.
+ where "OFF" means "use weechat default behaviour.
+
+ /set_ctcp VERSION I prefer using weechat $version
+ Reply with a fancy message.
+ $version is substituted with weechats version.
+ Other variables are: $away, $nick and $server.
+ (If you find something else that could make sense
+ here, let me know!)
+
+ /set_ctcp HOW_ARE_YOU Good.
+ Set answer to a rather unusual CTCP-request.
+
+ /set_ctcp VERSION OFF
+ Disable special behavior when CTCP VERSION comes in.
+ atm this leaves an entry in plugins.rc which
+ can be safely removed.
+"""
+
+
+import weechat as wc
+import re
+
+wc.register("ctcp", version, "", "Customize CTCP replies")
+wc.add_command_handler("set_ctcp", "set", "", short_syntax, syntax)
+wc.add_message_handler("privmsg", "on_msg")
+
+if not wc.get_plugin_config("requests"):
+ wc.set_plugin_config("requests", " ".join(["VERSION", "USERINFO", "FINGER", "TIME", "PING"]))
+
+def get_answers():
+ # Strangely, get_plugin_config sometimes returns
+ # the integer 0
+ requests = wc.get_plugin_config("requests")
+ if requests:
+ requests = requests.split()
+ else:
+ requests = ["VERSION", "USERINFO", "FINGER", "TIME", "PING"]
+
+ d = {}
+ for r in requests:
+ d[r] = wc.get_plugin_config("CTCP_" + r)
+ return d
+
+def set_answer(k, v):
+ wc.set_plugin_config("CTCP_" + k, v)
+ requests = wc.get_plugin_config("requests").split()
+ if k.upper() not in requests:
+ requests.append(k.upper())
+ wc.set_plugin_config("requests", " ".join(requests))
+
+def show_syntax():
+ wc.prnt("usage: /set_ctcp %s" % short_syntax)
+ wc.prnt("(For more information type /help set_ctcp)")
+
+def on_msg(server, args):
+ nothing, info, message = args.split(":", 2)
+ hostmask = info.split(None, 2)[0]
+ source = hostmask.split("!")[0]
+
+ answers = get_answers()
+
+ try:
+ if message.startswith("\x01") and message.endswith("\x01"):
+ req = message[1:-1]
+ ans = answers[req]
+ if not ans or ans == "OFF":
+ raise ValueError
+
+ info = {
+ "version": wc.get_info("version"),
+ "nick": wc.get_info("nick"),
+ "away": wc.get_info("away") and "away" or "there",
+ "server": server,
+ }
+
+ while True:
+ match = re.search(r'[^\\]\$([a-z]+)\b', ans) #, r'--\1--', ans)
+ if match is None: break
+ else:
+ l, r = match.span()
+ ans = ans[:l+1] + info.get(match.group(1), "$" + match.group(1)) + ans[r:]
+
+ wc.prnt("CTCP %s received from %s (on %s)" % (req, source, server))
+ wc.command("/quote NOTICE %s :\x01%s %s\x01" % (
+ source, req, ans), "", server)
+ return wc.PLUGIN_RC_OK_IGNORE_ALL
+
+ except Exception, e:
+ pass
+
+ return wc.PLUGIN_RC_OK
+
+def set(server, args):
+ try:
+ argv = args.split(None, 1)
+ answers = get_answers()
+
+ if not len(argv):
+ for k, v in answers.items():
+ wc.prnt("%10s: %s" % (k, v or "OFF"))
+
+ elif len(argv) == 2:
+ set_answer(argv[0], argv[1])
+
+ else:
+ show_syntax()
+ except Exception, e:
+ pass
+
+ return wc.PLUGIN_RC_OK
+
diff --git a/scripts/python/gimmicks.py b/scripts/python/gimmicks.py
new file mode 100644
index 000000000..3d8cc9621
--- /dev/null
+++ b/scripts/python/gimmicks.py
@@ -0,0 +1,99 @@
+# -*- coding: iso-8859-15 -*-
+
+"""
+ :Author: Henning Hasemann <hhasemann [at] web [dot] de>
+
+ Usage:
+
+ - Load this plugin
+ - In a channel or query type "/flip foo something" to
+ send the reversed text "gnihtemos oof"
+ - In a channel or query type "/leet something else" to
+ send the h4x02-5r!pT - Version of your text.
+ (Please use with caution such crap is discouraged in most channels)
+
+ Released under GPL licence.
+"""
+
+__version__ = "0.1"
+__history__ = """
+ 0.1 initial
+"""
+
+short_syntax = """TEXT"""
+syntax_flip = """ Example:
+
+ /flip foo bar
+ sends "rab oof" to the channel
+"""
+syntax_leet = """ Example:
+
+ /leet eleet
+ sends "31337" (or similar) to the channel
+"""
+
+import weechat as wc
+import string, random
+
+wc.register("gimmicks", __version__, "", "string gimmicks")
+wc.add_command_handler("flip", "flip", "", short_syntax, syntax_flip)
+wc.add_command_handler("leet", "leet", "", short_syntax, syntax_leet)
+
+leet_dict = {
+ "e": ["3"],
+ "l": ["1", "!", "|"],
+ "r": ["|2"],
+ "b": ["8"],
+ "v": [r'\/'],
+ "t": ["7"],
+ "i": ["!"],
+ "w": [r'\/\/', 'vv'],
+ "a": ["/\\", "<|", "4"],
+ "k": ["x"],
+ "n": [r'|\|'],
+ "s": ["5","$"],
+ "q": ["O."],
+ "z": ["zZz", "7_"],
+ "u": ["(_)"],
+ "p": ["|°", "|*"],
+ "d": ["|)", "I>", "ol"],
+ "f": ["i="],
+ "g": ["@"],
+ "h": ["|-|"],
+ "j": ["_I"],
+ "y": ["`/"],
+ "x": ["><"],
+ "c": ["[", "(", "{"],
+ "m": ["|v|", "nn"],
+ "o": ["0", "()"],
+}
+
+def leet(server, args):
+ casechange = True
+ strange = True
+ stay = False
+
+ r = ""
+ luflag = 0
+ for x in list(args):
+ if stay:
+ alt = [x]
+ else:
+ alt = []
+ if casechange:
+ alt.append(luflag and x.lower() or x.upper())
+ luflag = not luflag
+ if strange:
+ alt += leet_dict.get(x.lower(), [])
+ r += random.choice(alt)
+ wc.command(r)
+ return 0
+
+def flip(server, args):
+ l = list(args)
+ l.reverse()
+ wc.command("".join(l))
+ return 0
+
+
+
diff --git a/scripts/python/mpdnp.py b/scripts/python/mpdnp.py
new file mode 100644
index 000000000..37e9da6c3
--- /dev/null
+++ b/scripts/python/mpdnp.py
@@ -0,0 +1,101 @@
+"""
+ :Author: Henning Hasemann <hhasemann [at] web [dot] de>
+
+ :What it does:
+ This plugin lets you inform all users in the current
+ channel about the song which music-player-daemon (MPD)
+ is currently playing.
+
+ :Usage:
+ /mpdnp - Display file mpd is playing to current channel.
+
+ :Configuration Variables:
+ ============= ==========================================
+ Variable name Meaning
+ ============= ==========================================
+ host The host where your mpd runs
+ port The port to connect to mpd (usually 6600)
+ format How this script should display
+ whats going on.
+ You may use the following variables here:
+ $artist, $title_or_file,
+ $length_min, $length_sec, $pct,
+ $pos_min, $pos_sec
+
+ Released under GPL licence.
+"""
+
+todo = """
+ - maybe support sending commands to mpd.
+ - maybe make condional display
+ (displaying some characters only
+ if preceding or trailing variables are set)
+"""
+
+import weechat as wc
+import mpdclient as mpd
+import re
+from os.path import basename, splitext
+
+default_fmt = "/me 's MPD plays: $artist - $title_or_file ($length_min:$length_sec)"
+
+wc.register("mpdnp", "0.3", "", "np for mpd")
+
+def subst(text, values):
+ out = ""
+ n = 0
+ for match in re.finditer(findvar, text):
+ if match is None: continue
+ else:
+ l, r = match.span()
+ nam = match.group(1)
+ out += text[n:l+1] + values.get(nam, "") #"$" + nam)
+ n = r
+ return out + text[n:]
+
+def np(server, args):
+ """
+ Send information about the currently
+ played song to the channel.
+ """
+ host = wc.get_plugin_config("host")
+ port = int(wc.get_plugin_config("port"))
+ cont = mpd.MpdController(host=host, port=port)
+ song = cont.getCurrentSong()
+ pos, length, pct = cont.getSongPosition()
+
+ # insert artist, title, album, track, path
+ d = song.__dict__
+ d.update({
+ "title_or_file": song.title or splitext(basename(song.path))[0],
+ "pos_sec": "%02d" % (pos / 60),
+ "pos_min": str(pos / 60),
+ "length_sec": "%02d" % (length % 60),
+ "length_min": str(length / 60),
+ "pct": "%2.0f" % pct,
+ })
+
+ wc.command(subst(wc.get_plugin_config("format"), d))
+ return 0
+
+def dbgnp(server, args):
+ try:
+ return np(server, args)
+ except Exception, e:
+ print e
+
+wc.add_command_handler("mpdnp", "np", "", "", np.__doc__)
+
+findvar = re.compile(r'[^\\]\$([a-z_]+)(\b|[^a-z_])')
+
+default = {
+ "host": "localhost",
+ "port": "6600",
+ "format": default_fmt,
+}
+
+for k, v in default.items():
+ if not wc.get_plugin_config(k):
+ wc.set_plugin_config(k, v)
+
+
diff --git a/scripts/python/onattach.py b/scripts/python/onattach.py
new file mode 100644
index 000000000..d5117716e
--- /dev/null
+++ b/scripts/python/onattach.py
@@ -0,0 +1,445 @@
+# -*- encoding: iso-8859-1 -*-
+#
+# Copyright (c) 2006 by EgS <i@egs.name>
+#
+# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+
+#######################################################################
+# #
+# This script enables the execution of events triggered commands #
+# where the events are attach or detach of the screen weechat #
+# is running in. #
+# #
+# Name: OnAttach #
+# Licence: GPL v2 #
+# Author: Marcus Eggenberger <i@egs.name> #
+# #
+# Usage: #
+# /onattach or /ondetach to add new events #
+# /screenevents to manage events #
+# #
+# use /help command for detailed information #
+# #
+# Changelog: #
+# 0.5: added screen guessing to backup screen-detection #
+# 0.4: fixed TypeError in weechat 0.1.9 #
+# 0.3: now checking on startup if weechat runs in a screen #
+# 0.2: added usage of get/set_plugin_config to store eventlist #
+# 0.1: first version released #
+# #
+#######################################################################
+
+
+
+# ====================
+# Imports
+# ====================
+import os
+import sys
+
+# ====================
+# Constants
+# ====================
+NAME = 'OnAttach'
+VERSION = '0.5'
+DESCRIPTION = "Executing commands on screen Attach/Detach"
+
+OFF = False
+ON = True
+
+# ====================
+# Exceptions
+# ====================
+class OnAttachError(Exception):
+ pass
+
+# ====================
+# Helpers
+# ====================
+class WeePrint(object):
+ def write(self, text):
+ text = text.rstrip(' \0\n') # strip the null byte appended by pythons print
+ if text:
+ weechat.prnt(text,'')
+
+def getScreenByPpid():
+ # the screen we are in should be our parents parent
+ # aka something like:
+ # SCREEN
+ # \_ -/bin/bash
+ # \_ weechat-curses
+ ppid = os.getppid()
+
+ # get SCREEN pid
+ pipe = os.popen("ps o ppid= -p %d" % ppid)
+ screenpid = pipe.read().strip()
+ pipe.close()
+
+ # check if screen pid really belongs to a screen
+ pipe = os.popen("ps o cmd= -p %s" % screenpid)
+ cmd = pipe.read().strip()
+ pipe.close()
+
+ if 'screen' not in cmd.lower():
+ raise OnAttachError
+ else:
+ return screenpid
+
+def getScreenByList():
+ # checks if there is only one attached screen
+ # if so use: it! ;)
+ pipe = os.popen("screen -list | grep -i attached")
+ screens = pipe.read().strip()
+ pipe.close()
+ screens = screens.splitlines()
+
+ if len(screens) > 1:
+ print "There are more then one screen currently attached."
+ print "Detach all other running screens and reload OnAttach"
+ print "to ensure correct screen detection."
+ raise OnAttachError
+
+ try:
+ socket, status = screens[0].split()
+ except:
+ # thats no common screen list...
+ print "failed!"
+ raise OnAttachError
+ else:
+ print "Using screen %s" % socket
+ return socket
+
+def getScreenPid():
+ try:
+ return getScreenByPpid()
+ except OnAttachError:
+ print "!!! Unable to determine screen by parentid!"
+ print "Trying to guess screen..."
+ return getScreenByList()
+
+def registerFunction(function):
+ # Register a python function as a commandhandler
+ # Function needs to be named like weeFunction and
+ # is bound to /function
+ # docstring is used for weechat help
+ functionname = function.__name__ # guess what :)
+ weecommand = functionname[3:].lower() # strip the wee
+
+ doc = function.__doc__.splitlines()
+ arguments = doc[0] # First docstring line is the arguments string
+ description = doc[1][4:]
+ args_description = '\n'.join([line[4:] for line in doc[2:-1]]) # join rest and strip indentation
+
+ if not function.func_defaults: # use args default value as template
+ template = ''
+ elif len(function.func_defaults) == 1:
+ template = function.func_defaults[0]
+ elif len(function.func_defaults) == 2:
+ template = func.func_defaults[1]
+
+ weechat.add_command_handler(weecommand, functionname, description, arguments, args_description, template)
+
+def registerFunctions():
+ functions = [function for name, function in globals().iteritems() if name.startswith('wee') and callable(function)]
+ for func in functions:
+ registerFunction(func)
+
+# ====================
+# Classes
+# ====================
+class Event(object):
+ ESCAPECHAR = '\\'
+ SEPARATOR = ';'
+
+ def __init__(self, delay, step, channel, server, command, activehigh=True):
+ self.delay = int(delay)
+ self.step = step
+ self.channel = channel
+ self.server = server
+ self.command = command
+ self.activestate = activehigh
+ self.reset()
+
+ #@classmethod
+ def unserialize(cls, step, serial):
+ try:
+ # let's try the easy way :)
+ delay, channel, server, command, activestate = serial.split()
+ except ValueError:
+ # ok we got an escaped separator... :/
+ data = serial.split(cls.SEPARATOR)
+ for i in range(len(data)):
+ if data[i].endswith(cls.ESCAPECHAR):
+ data[i+1] = data[i] + cls.SEPARATOR + data[i+1]
+ data = [item.replace(cls.ESCAPECHAR + cls.SEPARATOR, cls.SEPARATOR) for item in data if not item.endswith(cls.ESCAPECHAR)]
+ delay, channel, server, command, activestate = data
+
+
+ delay = int(delay)
+ activestate = activestate == 'True'
+
+ return cls(delay, step, channel, server, command, activestate)
+ # lets go for 2.3 compatiblity
+ unserialize = classmethod(unserialize)
+
+ #@property
+ def serialized(self):
+ data = [self.delay, self.channel, self.server, self.command, self.activestate]
+ data = [str(item).replace(self.SEPARATOR, self.ESCAPECHAR + self.SEPARATOR) for item in data]
+ return self.SEPARATOR.join(data)
+ # lets go for 2.3 compatiblity
+ serialized = property(serialized)
+
+ def reset(self):
+ self.currentdelay = self.delay
+ self.fired = False
+
+ def fire(self):
+ weechat.command(self.command, self.channel, self.server)
+ self.fired = True
+
+ def stimulus(self, state):
+ if state != self.activestate:
+ self.reset()
+ else:
+ self.currentdelay -= self.step
+ if self.currentdelay <= 0 and not self.fired:
+ self.fire()
+
+class CheckStatus(object):
+ ESCAPECHAR = '\\'
+ SEPARATOR = '|'
+
+ eventlist = []
+ step = 5
+ def __init__(self):
+ try:
+ self.screenpid = getScreenPid()
+ except OnAttachError:
+ raise
+
+ # try to read config data
+ serializedEvents = weechat.get_plugin_config("events")
+ if not serializedEvents:
+ return
+
+ events = serializedEvents.split(self.SEPARATOR)
+ for i in range(len(events)):
+ if events[i].endswith(self.ESCAPECHAR):
+ events[i+1] = events[i] + self.SEPARATOR + ss[i+1]
+ events = [event.replace(self.ESCAPECHAR + self.SEPARATOR, self.SEPARATOR) for event in events if not event.endswith(self.ESCAPECHAR)]
+ for event in events:
+ try:
+ self.eventlist.append(Event.unserialize(self.step, event))
+ except:
+ print "Unable to unserialize event!"
+ print "Try to add the event manualy and save config again."
+
+ def __call__(self, server="", args=""):
+ # check if the screen is attached or detatched
+ pipe = os.popen("screen -list | grep %s" % self.screenpid)
+ screenlist = pipe.read().strip()
+ pipe.close()
+
+ if 'attached' in screenlist.lower():
+ state = ON
+ elif 'detached' in screenlist.lower():
+ state = OFF
+ else:
+ print "Unable to determine screen status"
+ return weechat.PLUGIN_RC_KO
+
+ for event in self.eventlist:
+ event.stimulus(state)
+
+ return weechat.PLUGIN_RC_OK
+
+ def addEvent(self, delay, channel, server, command, activehigh=True):
+ event = Event(delay, self.step, channel, server, command, activehigh)
+ self.eventlist.append(event)
+
+ def showEvents(self):
+ format = "%2s | %-10s | %-10s | %-15s | %-7s | %-2s %s"
+ separator = "---+------------+------------+-----------------+---------+----"
+ print separator
+ print format % ("ID", "Server", "Channel", "Command", "Delay", "on", "")
+ print separator
+ for i in range(len(self.eventlist)):
+ event = self.eventlist[i]
+ if event.activestate:
+ atde = 'AT'
+ else:
+ atde = 'DE'
+
+ if event.fired:
+ fired = '*'
+ else:
+ fired = ''
+ print format % (i, event.server[:10], event.channel[:10], event.command[:15], "%3d sec" % event.delay, atde, fired)
+ print separator
+
+ def save(self):
+ weechat.set_plugin_config("events",self.serialized)
+
+ #@property
+ def serialized(self):
+ events = [str(event.serialized).replace(self.SEPARATOR, self.ESCAPECHAR + self.SEPARATOR) for event in self.eventlist]
+ return self.SEPARATOR.join(events)
+ # lets go for 2.3 compatiblity
+ serialized = property(serialized)
+
+ def dropEvent(self, eventid):
+ del self.eventlist[eventid]
+
+# ====================
+# Functions
+# ====================
+def addEvent(server, args, activehigh=True):
+ delay, channel, command = args.split(' ', 2)
+ delay = int(delay)
+
+ channel = channel.strip("'\"")
+ checkStatus.addEvent(delay, channel, server, command, activehigh)
+ if activehigh:
+ atde = "at"
+ else:
+ atde = "de"
+
+ print "Added %stach event '%s' for channel %s on network %s with %d seconds delay" % (atde, command, channel, server, delay)
+
+def weeOnAttach(server, args):
+ """delay channel command
+ Adds a command which is executed after attaching the screen
+ The command is executed <delay> seconds after the attach.
+ Use "" or '' as channel if the command should be executed in
+ the server buffer.
+
+ Example:
+ /onattach 180 &bitlbee account on 0
+ """
+ try:
+ addEvent(server, args)
+ except:
+ weechat.command("/help onattach", "", server)
+ return 0
+ else:
+ return 1
+
+def weeOnDetach(server, args):
+ """delay channel command
+ Adds a command which is executed after detaching the screen
+ The command is executed <delay> seconds after the detach.
+ Use "" or '' as channel if the command should be executed in
+ the server buffer.
+
+ Example:
+ /ondetach 180 &bitlbee account on 0
+ """
+ try:
+ addEvent(server, args, activehigh=False)
+ except:
+ weechat.command("/help onattach", "", server)
+ return 0
+ else:
+ return 1
+
+def weeScreenevents(server, args="show|save|drop"):
+ """show | save | drop eventid [eventid [...]]
+ shows, saves or drops events
+ show:
+ Shows all current active events
+
+ save:
+ Saves current events permanently
+
+ drop:
+ Delete event from onAttach/onDetach list.
+ Use /showevents to get eventid
+ """
+ try:
+ action, args = args.split(' ',1)
+ except ValueError:
+ action = args.strip()
+ args = ''
+
+ actions = {'show':showEvents,
+ 'drop':dropEvent,
+ 'save':saveEvents}
+ try:
+ action = actions[action]
+ except KeyError:
+ weechat.command("/help screenevents", "", server)
+ return 0
+ else:
+ return action(server, args)
+
+
+
+def showEvents(server, args):
+ checkStatus.showEvents()
+ return 1
+
+def dropEvent(server, args):
+ try:
+ eventids = [int(id) for id in args.split()]
+ except:
+ print "eventid musst be a number!"
+ return 0
+
+ eventids.sort()
+ eventids.reverse()
+ for eventid in eventids:
+ try:
+ checkStatus.dropEvent(eventid)
+ except:
+ print "Unable to drop Event %d" % eventid
+ return 0
+ print "dropped %d events!" % len(eventids)
+ return 1
+
+def saveEvents(server, args):
+ checkStatus.save()
+ return 1
+
+# ====================
+# Let's Register!
+# ====================
+if __name__ == '__main__':
+ try:
+ import weechat
+ except ImportError:
+ print "This script is to be loaded as PythonScript in WeeChat"
+ print "Get WeeChat now at: http://weechat.flashtux.org/"
+ import sys
+ sys.exit(10)
+
+ # kick pythons print to weechat.prnt(msg, '')
+ sys.stdout = WeePrint()
+ weechat.register(NAME, VERSION, "", DESCRIPTION)
+ try:
+ checkStatus = CheckStatus()
+ except OnAttachError:
+ print "!!! Requirements for %s not met:" % NAME
+ print "!!! - WeeChat is not running in a screen or not able to get screen PID"
+ print "!!! --> Run WeeChat in a screen to fix the problem!"
+ else:
+
+ weechat.add_timer_handler(checkStatus.step, "checkStatus")
+
+ registerFunctions()
+
+
diff --git a/scripts/python/shell.py b/scripts/python/shell.py
new file mode 100644
index 000000000..1d14b3db5
--- /dev/null
+++ b/scripts/python/shell.py
@@ -0,0 +1,136 @@
+
+# =============================================================================
+# shell.py (c) March 2006 by Kolter <kolter+dev@openics.org>
+#
+# Licence : GPL v2
+# Description : running shell commands in WeeChat
+# Syntax : try /help shell to get some help on this script
+# Precond : needs weechat > 0.1.7 to run else it will crash WeeChat ;-)
+#
+#
+# ### changelog ###
+#
+# * version 0.1 :
+# - first release
+#
+# =============================================================================
+
+import weechat, os, popen2
+
+SHELL_CMD="shell"
+SHELL_PREFIX="[shell] "
+
+weechat.register ("Shell", "0.1", "", "Running shell commands in WeeChat")
+weechat.add_command_handler(
+ SHELL_CMD,
+ "shell",
+ "Running shell commands in WeeChat",
+ "[-o] <command line>",
+ " -o : print output on current server/channel\n"
+ "<command line> : shell command or builtin like cd, getenv, setenv, unsetenv",
+ "-o|cd|getenv|setenv|unsetenv cd|getenv|setenv|unsetenv"
+ )
+
+def shell_exec(command):
+ proc = popen2.Popen3(command, True)
+ status = proc.wait()
+ results = []
+ if status == 0:
+ results = proc.fromchild.readlines()
+ else:
+ results = proc.childerr.readlines()
+ return status, results
+
+def shell_output(command, inchan):
+ status, results = shell_exec(command)
+ if status == 0:
+ for line in results:
+ if inchan:
+ weechat.command(line.rstrip('\n'))
+ else:
+ weechat.prnt(line.rstrip('\n'))
+ else:
+ weechat.prnt("%san error occured while running command `%s'" % (SHELL_PREFIX, command))
+ for line in results:
+ weechat.prnt(line.rstrip('\n'))
+
+
+def shell_chdir(directory):
+ if directory == "":
+ if os.environ.has_key('HOME'):
+ directory = os.environ['HOME']
+ try:
+ os.chdir(directory)
+ except:
+ weechat.prnt("%san error occured while running command `cd %s'" % (SHELL_PREFIX, directory))
+ else:
+ pass
+
+def shell_getenv(var, inchan):
+ var = var.strip()
+ if var == "":
+ weechat.prnt("%swrong syntax, try 'getenv VAR'" % (SHELL_PREFIX))
+ return
+
+ value = os.getenv(var)
+ if value == None:
+ weechat.prnt("%s$%s is not set" % (SHELL_PREFIX, var))
+ else:
+ if inchan:
+ weechat.command("$%s=%s" % (var, os.getenv(var)))
+ else:
+ weechat.prnt("%s$%s=%s" % (SHELL_PREFIX, var, os.getenv(var)))
+
+def shell_setenv(expr, inchan):
+ expr = expr.strip()
+ lexpr = expr.split('=')
+
+ if (len(lexpr) < 2):
+ weechat.prnt("%swrong syntax, try 'setenv VAR=VALUE'" % (SHELL_PREFIX))
+ return
+
+ os.environ[lexpr[0].strip()] = "=".join(lexpr[1:])
+ if not inchan:
+ weechat.prnt("%s$%s is now set to '%s'" % (SHELL_PREFIX, lexpr[0], "=".join(lexpr[1:])))
+
+def shell_unsetenv(var, inchan):
+ var = var.strip()
+ if var == "":
+ weechat.prnt("%swrong syntax, try 'unsetenv VAR'" % (SHELL_PREFIX))
+ return
+
+ if os.environ.has_key(var):
+ del os.environ[var]
+ weechat.prnt("%s$%s is now unset" % (SHELL_PREFIX, var))
+ else:
+ weechat.prnt("%s$%s is not set" % (SHELL_PREFIX, var))
+
+def shell(server, args):
+ largs = args.split(" ")
+
+ #strip spaces
+ while '' in largs:
+ largs.remove('')
+ while ' ' in largs:
+ largs.remove(' ')
+
+ if len(largs) == 0:
+ weechat.command("/help %s" % SHELL_CMD)
+ else:
+ inchan = False
+ if largs[0] == '-o':
+ inchan = True
+ largs = largs[1:]
+
+ if largs[0] == 'cd':
+ shell_chdir(" ".join(largs[1:]), inchan)
+ elif largs[0] == 'getenv':
+ shell_getenv (" ".join(largs[1:]), inchan)
+ elif largs[0] == 'setenv':
+ shell_setenv (" ".join(largs[1:]), inchan)
+ elif largs[0] == 'unsetenv':
+ shell_unsetenv (" ".join(largs[1:]), inchan)
+ else:
+ shell_output(" ".join(largs), inchan)
+
+ return weechat.PLUGIN_RC_OK
diff --git a/scripts/python/theme.py b/scripts/python/theme.py
new file mode 100644
index 000000000..42353f390
--- /dev/null
+++ b/scripts/python/theme.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+"""
+Theme manager for WeeChat.
+It loads configuration parameters from file
+and allows to create new theme out of current configuration.
+
+by Stalwart <stlwrt@gmail.com>
+
+Licensed under GNU GPL v2
+
+"""
+
+## ---------- Code starts here ----------
+import weechat
+import os
+
+VERSION = "0.2.3"
+
+weechat.register("theme", VERSION, "", "Theme manager for WeeChat")
+
+THEMEDIR = weechat.get_info("weechat_dir") + '/themes'
+
+weechat.add_command_handler("theme", "parameter_parser", "Apply and create themes", "[load <name> | save <name>]", "", "load|save")
+
+settings = [
+ 'look_startup_logo',
+ 'look_startup_version',
+ 'look_weechat_slogan',
+ 'look_buffer_timestamp',
+ 'look_color_nicks_number',
+ 'look_color_actions',
+ 'look_nicklist',
+ 'look_nicklist_position',
+ 'look_nicklist_min_size',
+ 'look_nicklist_max_size',
+ 'look_no_nickname',
+ 'look_nickmode',
+ 'look_nickmode_empty',
+ 'look_nick_prefix',
+ 'look_nick_suffix',
+ 'look_align_nick',
+ 'look_align_other',
+ 'look_align_size',
+ 'look_align_size_max',
+ 'look_infobar',
+ 'look_infobar_timestamp',
+ 'look_infobar_seconds',
+ 'look_infobar_delay_highlight',
+ 'look_hotlist_names_count',
+ 'look_hotlist_names_level',
+ 'look_hotlist_names_length',
+ 'look_read_marker',
+ 'look_input_format',
+ 'col_separator',
+ 'col_title',
+ 'col_title_bg',
+ 'col_chat',
+ 'col_chat_time',
+ 'col_chat_time_sep',
+ 'col_chat_prefix1',
+ 'col_chat_prefix2',
+ 'col_chat_server',
+ 'col_chat_join',
+ 'col_chat_part',
+ 'col_chat_nick',
+ 'col_chat_host',
+ 'col_chat_channel',
+ 'col_chat_dark',
+ 'col_chat_highlight',
+ 'col_chat_bg',
+ 'col_chat_read_marker',
+ 'col_chat_read_marker_bg',
+ 'col_status',
+ 'col_status_delimiters',
+ 'col_status_channel',
+ 'col_status_data_msg',
+ 'col_status_private',
+ 'col_status_highlight',
+ 'col_status_data_other',
+ 'col_status_more',
+ 'col_status_bg',
+ 'col_infobar',
+ 'col_infobar_delimiters',
+ 'col_infobar_highlight',
+ 'col_infobar_bg',
+ 'col_input',
+ 'col_input_server',
+ 'col_input_channel',
+ 'col_input_nick',
+ 'col_input_delimiters',
+ 'col_input_bg',
+ 'col_nick',
+ 'col_nick_away',
+ 'col_nick_chanowner',
+ 'col_nick_chanadmin',
+ 'col_nick_op',
+ 'col_nick_halfop',
+ 'col_nick_voice',
+ 'col_nick_more',
+ 'col_nick_sep',
+ 'col_nick_self',
+ 'col_nick_color1',
+ 'col_nick_color2',
+ 'col_nick_color3',
+ 'col_nick_color4',
+ 'col_nick_color5',
+ 'col_nick_color6',
+ 'col_nick_color7',
+ 'col_nick_color8',
+ 'col_nick_color9',
+ 'col_nick_color10',
+ 'col_nick_private',
+ 'col_nick_bg',
+ 'col_chat_dcc_selected',
+ 'col_dcc_waiting',
+ 'col_dcc_connecting',
+ 'col_dcc_active',
+ 'col_dcc_done',
+ 'col_dcc_failed',
+ 'col_dcc_aborted'
+]
+
+def themes_dir_available(writeable):
+ if not os.access(THEMEDIR, os.F_OK):
+ os.mkdir(THEMEDIR, 0700)
+ if writeable:
+ if os.access(THEMEDIR, os.W_OK):
+ return 1
+ else:
+ return 0
+ else:
+ if os.access(THEMEDIR, os.R_OK):
+ return 1
+ else:
+ return 0
+
+def save_theme(theme_filename):
+ if themes_dir_available(1):
+ try:
+ themefile = open("%s/%s" % (THEMEDIR, theme_filename), 'wU')
+ except:
+ weechat.print_infobar(3, "Bad theme name, try another")
+ else:
+ themefile.write("# This WeeChat theme has been generated by Themes v.%s\n" % VERSION)
+ for variable in settings:
+ try:
+ value = weechat.get_config(variable)
+ except:
+ weechat.prnt("Unable to get the value of %s" % variable)
+ else:
+ themefile.write("%s=%s\n" % (variable, value))
+ themefile.flush()
+ themefile.close()
+ weechat.print_infobar(3, "Theme %s saved" % theme_filename)
+
+def load_theme(theme_filename):
+ if themes_dir_available(0):
+ if os.access("%s/%s" % (THEMEDIR, theme_filename), os.F_OK):
+ themefile = open("%s/%s" % (THEMEDIR, theme_filename), 'rU')
+ lines = themefile.readlines()
+ for line in lines:
+ if ((len(line) > 3) and (line[0] != '#') and (line.find("="))):
+ try:
+ weechat.set_config(line[:line.find("=")], line[line.find("=")+1:].replace("\n", ""))
+ except:
+ weechat.prnt("Unable to set the value of %s" % variable)
+ weechat.print_infobar(3, "Theme %s applied" % theme_filename)
+ else:
+ weechat.print_infobar(3, "Theme %s doesn't exist" % theme_filename)
+ themefile.close()
+
+def list_themes():
+ if themes_dir_available(0):
+ files = os.listdir(THEMEDIR)
+ if len(files):
+ weechat.prnt('Available themes:')
+ for filename in files:
+ if filename[-9:] == '.weetheme':
+ weechat.prnt(" %s" % filename[:-9])
+ else:
+ weechat.prnt('Theme directory is empty, you can create new theme out of your current configuration by executing "/theme save <name>". Additional themes available on http://weechat.flashtux.org')
+ else:
+ weechat.prnt('Theme directory is not available. Please, check access rights')
+
+def parameter_parser(server, args):
+ if ((args != '') & (len(args.split()) == 2)):
+ if args.split()[0] == 'save':
+ save_theme(args.split()[1] + '.weetheme')
+ elif args.split()[0] == 'load':
+ load_theme(args.split()[1] + '.weetheme')
+ else:
+ weechat.prnt('Invalid parameter, must be "load" or "save"')
+ else:
+ list_themes()
+ return weechat.PLUGIN_RC_OK
+
+
diff --git a/scripts/python/tinyurl.py b/scripts/python/tinyurl.py
new file mode 100644
index 000000000..878630722
--- /dev/null
+++ b/scripts/python/tinyurl.py
@@ -0,0 +1,334 @@
+#!/bin/env python
+#
+# TinyUrl, version 3.3, for weechat version 0.1.9
+#
+# Listens to all channels for long URLs, and submits them to tinyurl.com
+# for easier links.
+#
+# Usage:
+#
+# By default, any URL longer than 30 characters in length is grabbed,
+# submitted to 'tinyurl', and printed in the channel for your eyes only.
+# For example, you may see something like this:
+#
+# [11:21] <@lack> http://www.cbc.ca/story/canada/national/2005/11/12/mcdona
+# lds-051112.html?ref=rss
+# [11:21] -P- [AKA] http://tinyurl.com/9dthl
+#
+# Now you can just cut&paste the easier, shorter URL into your favourite
+# browser.
+#
+# If you want to be extra-helpful (or annoying) to certain channels you
+# are in, you can actually have the script say the tinyurl.com equivalent
+# of all long URLs, by adding the channel to the 'activechans' list. In
+# that case, everyone in the channel would see the following:
+#
+# [11:25] <testuser> http://www.cbc.ca/story/canada/national/2005/11/12/mcdona
+# lds-051112.html?ref=rss
+# [11:25] <@lack> [AKA] http://tinyurl.com/9dthl
+#
+# Configuration:
+#
+# Run '/help tinyurl' for the actual usage for setting these options:
+#
+# activechans
+# A comma-delimited list of channels you will actually "say" the
+# tinyurl in. By default the list is empty. Be warned, some channels
+# won't appreciate extra help (or 'noise' as they like to call it), and
+# some channels already have bots that do this. Please only enable
+# this in channels where the ops have given you permission.
+#
+# urllength
+# An integer, default value 30. Any URL this long or longer will
+# trigger a tinyurl event.
+#
+# printall
+# Either "on" or "off", default "on". When ON, you will see the
+# tinyurl printed in your window for any channels not in your
+# activechans list. When OFF, you will not see any tinyurls except in
+# your activechans list.
+#
+# Requirements:
+#
+# - Designed to run with weechat version 0.1.9 or better.
+# http://weechat.flashtux.org/
+#
+# - Requires that 'curl' is in the path (tested with curl 7.15.0).
+# http://curl.haxx.se/
+#
+# 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.
+#
+# Changelog:
+#
+# Version 3.3, July 4, 2006
+# Catches possible error in os.waitpid
+# Properly prints tinyurls in query windows
+#
+# Version 3.2, June 15, 2006
+# Multiple configuration bugfixes, pointed out by Stalwart on #weechat.
+#
+# Version 3.1, June 15, 2006
+# Now kills any leftover curl processes when the script is unloaded.
+# Thanks again to kolter for the great idea!
+# Also cleaned up /tinyurl command, added comletion_template, updated
+# help text, improved option parsing logic, etc.
+#
+# Version 3.0, June 15, 2006
+# Fixes "tinyurl script sometimes makes weechat freeze" issue by using
+# the new timer handlers available in Weechat 0.1.9
+# Also includes URL detection fix from Raimund Specht
+# <raimund@spemaus.de>.
+#
+# Version 2.0, Dec 13, 2005
+# Also catches https, ftp, and ftps URLs, thanks to kolter for the
+# suggestion!
+#
+# Version 1.1, Dec 2, 2005
+# Fixed undefined 'urlend' thanks to kolter@irc.freenode.org#weechat
+#
+# TODO:
+#
+# - Handle outgoing messages and replace long urls with the tinyurl
+# equivalent automatically.
+# - On load, check that 'curl' is installed, and fail if not.
+#
+
+import os, tempfile, re
+try:
+ import urllib
+except:
+ raise ImportError("You need to reload the python plugin to reload urllib")
+import weechat
+
+# Register with weechat
+weechat.register( "TinyUrl", "3.3", "tinyurlShutdown", "Waits for URLs and sends them to 'tinyurl' for you" )
+
+# Global variables
+tinyurlParams = ("urllength","activechans","printall")
+tinyurlProcessList = {}
+
+# Set default settings values:
+if weechat.get_plugin_config('urllength') == "":
+ weechat.set_plugin_config('urllength', "30")
+if weechat.get_plugin_config('printall') != "on" and \
+ weechat.get_plugin_config('printall') != "off":
+ weechat.set_plugin_config('printall', "on")
+
+# Start the timer thread and register handlers
+weechat.add_timer_handler( 1, "tinyurlCheckComplete" )
+weechat.add_message_handler("privmsg", "tinyurlHandleMessage")
+weechat.add_command_handler("tinyurl", "tinyurlMain", \
+ "Sets/Gets 'tinyurl' settings.",
+ "[<variable> [[=] <value>]]",
+"""When run without arguments, displays all tinyurl settings
+
+<variable> : Sets or displays a single tinyurl setting. One of:
+ activechans [[=] #chan1[,#chan2...]]
+ List of channels where others will see your tinyurls.
+ Default: None
+ urllength [[=] length]
+ Will not create tinyurls for any URLs shorter than this.
+ Default: 30
+ printall [[=] on|off]
+ When off, will not display private tinyurls, just those
+ displayed publicly in your "active channels"
+ Default: on""",
+ "urllength|activechans|printall"
+ )
+
+def tinyurlShutdown():
+ """Cleanup - Kills any leftover child processes"""
+ if len(tinyurlProcessList.keys()) > 0:
+ weechat.prnt( "-TinyUrl- Cleaning up unfinished processes:" )
+ for pid in tinyurlProcessList.keys():
+ weechat.prnt( " Process %d" % pid )
+ try:
+ os.kill(pid, 9)
+ os.waitpid( pid, 0 )
+ except:
+ weechat.prnt( " Cleanup failed, skipping" )
+ return weechat.PLUGIN_RC_OK
+
+def tinyurlGet( name = "" ):
+ """Gets a variable value"""
+ if name == "":
+ weechat.prnt( "-TinyUrl- Get all:" )
+ for name in tinyurlParams:
+ weechat.prnt( " %s = %s" % (name, weechat.get_plugin_config(name)) )
+ else:
+ weechat.prnt( "-TinyUrl- Get:" )
+ if name in tinyurlParams:
+ weechat.prnt( " %s = %s" % (name, weechat.get_plugin_config(name)) )
+ else:
+ weechat.prnt( " Unknown parameter \"%s\", try '/help tinyurl'" % name )
+ return
+
+def tinyurlSet( name, value ):
+ """Sets a variable value"""
+ if value == "":
+ tinyurlGet( name )
+ else:
+ weechat.prnt( "-TinyUrl- Set:" )
+ if name in tinyurlParams:
+ if name == "printall":
+ if value == "0" or value.lower() == "no" or value.lower() == "off":
+ weechat.set_plugin_config(name, "off")
+ elif value == "1" or value.lower() == "yes" or value.lower() == "on":
+ weechat.set_plugin_config(name, "on")
+ else:
+ weechat.prnt( " printall must be one of 'on' or 'off'" )
+ weechat.prnt( " value = '%s'" % value )
+ return
+ else:
+ if name == "activechans":
+ vs = re.split(", |,| ", value)
+ values = []
+ for v in vs:
+ if v.startswith("#"):
+ values.append(v)
+ value = ",".join(values)
+ weechat.set_plugin_config(name, value)
+ weechat.prnt( " %s = %s" % (name, weechat.get_plugin_config(name)) )
+ else:
+ weechat.prnt( " Unknown parameter \'%s\'" % name )
+ return
+
+def tinyurlMain( server, args ):
+ """Main handler for the /tinyurl command"""
+ args = args.split( " " )
+ while '' in args:
+ args.remove('')
+ while ' ' in args:
+ args.remove(' ')
+ if len(args) == 0:
+ tinyurlGet()
+ else:
+ name = args[0]
+ value = ""
+ if len(args) > 1:
+ if args[1] == "=":
+ value = " ".join(args[2:])
+ else:
+ value = " ".join(args[1:])
+ tinyurlSet( args[0], value )
+ else:
+ tinyurlGet( name )
+ return weechat.PLUGIN_RC_OK
+
+def tinyurlGetUrl( url, channel, server ):
+ """Starts a background process which will query 'tinyurl.com' and put the
+ result in a file that the timer function 'tinyurlCheck' will find and
+ parse."""
+ global tinyurlProcessList
+ handle, filename = tempfile.mkstemp( prefix="weechat-tinyurl.py-" )
+ os.close(handle)
+ cmd = ("curl -d url=%s http://tinyurl.com/create.php --stderr /dev/null -o %s" % \
+ (urllib.quote(url), filename)).split()
+ try:
+ pid = os.spawnvp( os.P_NOWAIT, cmd[0], cmd )
+ tinyurlProcessList[pid] = (filename, channel, server)
+ except Exception, e:
+ weechat.prnt( "-TinyUrl- Error: Could not spawn curl: %s" % e )
+
+def tinyurlParsefile( filename ):
+ """Parses the given HTML file and pulls out the tinyurl."""
+ turl = None
+ try:
+ html = open(filename, "r")
+ for line in html:
+ if( line.startswith("<input type=hidden name=tinyurl value=\"") ):
+ turlend = line[39:].find("\"")
+ if turlend > -1:
+ turl = line[39:][:turlend]
+ break
+ html.close()
+ except Exception, e:
+ weechat.prnt( "-TinyUrl- Error: Could not open result file %s: %s" % (filename, e) )
+ return turl
+
+def tinyurlPrint( url, channel, server ):
+ """Prints the new tinyurl either to just you, or to the whole channel"""
+ activeChans = weechat.get_plugin_config('activechans').split(',')
+ if channel in activeChans:
+ weechat.command( "/msg %s [AKA] %s" % ( channel, url) )
+ else:
+ weechat.prnt( "[AKA] %s" % (url), channel, server )
+
+def tinyurlFindUrlstart( msg, start = 0 ):
+ """Finds the beginnings of URLs"""
+ index = -1
+ if start < 0 or start >= len(msg):
+ return index
+ for prefix in ( "http://", "https://", "ftp://", "ftps://" ):
+ index = msg.find( prefix, start )
+ if index > -1:
+ break
+ return index
+
+def tinyurlFindUrlend( msg, urlstart ):
+ """Finds the ends of URLs (Strips following punctuation)"""
+ m = msg[urlstart:]
+ index = m.find( " " )
+ if index == -1:
+ index = len(m)
+ while msg[index-1] in ( "?", ".", "!" ):
+ index -= 1
+ return index + urlstart
+
+def tinyurlCheckComplete():
+ """The periodic poll of all waiting processes"""
+ global tinyurlProcessList
+ for pid in tinyurlProcessList.keys():
+ (filename, channel, server) = tinyurlProcessList[pid]
+ try:
+ (p, er) = os.waitpid( pid, os.WNOHANG )
+ if p != 0:
+ if er == 0:
+ tinyurl = tinyurlParsefile(filename)
+ if tinyurl is not None:
+ tinyurlPrint( tinyurl, channel, server )
+ else:
+ weechat.prnt( "-TinyUrl- Error: 'curl' did not run properly" )
+ os.unlink(filename)
+ del tinyurlProcessList[pid]
+ except OSError, e:
+ weechat.prnt( "-TinyUrl- Error: 'curl' process not found: %s", e )
+ os.unlink(filename)
+ del tinyurlProcessList[pid]
+ return weechat.PLUGIN_RC_OK
+
+def tinyurlHandleMessage( server, args ):
+ """Handles IRC PRIVMSG and checks for URLs"""
+ maxlen = int(weechat.get_plugin_config( "urllength" ))
+ activeChans = weechat.get_plugin_config('activechans').split(',')
+ onlyActiveChans = weechat.get_plugin_config('printall') == "off"
+ (source, type, channel, msg) = args.split(" ", 3)
+ if onlyActiveChans and channel not in activeChans:
+ return weechat.PLUGIN_RC_OK
+ if not channel.startswith("#"):
+ channel = source.split("!", 2)[0][1:]
+ urlstart = tinyurlFindUrlstart( msg )
+ while urlstart > -1 and urlstart is not None:
+ urlend = tinyurlFindUrlend( msg, urlstart )
+ url = msg[urlstart:urlend]
+ if len(url) >= maxlen:
+ tinyurlGetUrl(url, channel, server)
+ # Check for more URLs
+ urlstart = tinyurlFindUrlstart( msg, urlend+1 )
+ return weechat.PLUGIN_RC_OK
+
diff --git a/scripts/python/todo.py b/scripts/python/todo.py
new file mode 100644
index 000000000..7189b280e
--- /dev/null
+++ b/scripts/python/todo.py
@@ -0,0 +1,69 @@
+"""
+ :Author: Henning Hasemann <hhasemann [at] web [dot] de>
+
+ :What it does:
+ This script listens for messages beginning
+ with a special token and appends these messages
+ to a file.
+ This way people can post you short assignments which
+ you cant forget and dont have to look up in your look.
+ (try appending "cat /path/to/mytodofile" at your .bashrc)
+
+ :Usage:
+ - Load this file
+ - Make sure to set suitable configuration values.
+ token: The piece of text that signals a TODO
+ file: The file where the TODOs should be appended
+ allowed_sources: A space-seperated list of nicknames
+ which are allowed to send TODOs to you.
+ - Whenever any allowed person sends a message beginning
+ with your desired token, the rest of that message is
+ append to the desired TODO-file.
+
+ Released under GPL licence.
+"""
+__version__ = "0.1"
+
+import weechat as wc
+
+wc.register("todo", __version__, "", "automatic TODO")
+wc.add_message_handler("privmsg", "on_msg")
+
+default = {
+ "token": "##todo ",
+ "file": "/home/USER/todo",
+ "allowed_sources": "",
+}
+
+for k, v in default.items():
+ if not wc.get_plugin_config(k):
+ wc.set_plugin_config(k, v)
+
+def source_allowed(src):
+ return src in wc.get_plugin_config("allowed_sources").split()
+
+def on_msg(server, args):
+ # args looks like:
+ # :foo!foo@host PRIVMSG #channel :Hello, how are you?
+
+ token = wc.get_plugin_config("token")
+ filename = wc.get_plugin_config("file")
+
+ try:
+ nothing, info, message = args.split(":", 2)
+ hostmask, privmsg, channel = info.split(None, 2)
+ source = hostmask.split("!")[0]
+ except ValueError:
+ # Parsing didnt work,
+ # this happens mostly when strange messages
+ # arrive that dont have the format described above
+ return 0
+
+ if source_allowed(source) and message.lower().startswith(token):
+ wc.print_infobar(5, "NEW TASK: " + str(message[7:]))
+ f = open(filename, "a")
+ f.write("%s (%s)\n" % (message[7:], source))
+ f.close()
+
+ return 0
+
diff --git a/scripts/python/toggle.py b/scripts/python/toggle.py
new file mode 100644
index 000000000..1edb12ca7
--- /dev/null
+++ b/scripts/python/toggle.py
@@ -0,0 +1,131 @@
+# -*- encoding: iso-8859-1 -*-
+#
+# Copyright (c) 2006 by EgS <i@egs.name>
+#
+# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+
+#######################################################################
+# #
+# This script adds a simple command to toggle weechat options #
+# #
+# Name: Toggle #
+# Licence: GPL v2 #
+# Author: Marcus Eggenberger <i@egs.name> #
+# #
+# Usage: #
+# /toggle look_nicklist #
+# #
+# use /help command for detailed information #
+# #
+# Changelog: #
+# 0.1: first version released #
+# #
+#######################################################################
+
+
+
+# ====================
+# Imports
+# ====================
+import sys
+
+# ====================
+# Constants
+# ====================
+NAME = 'Toggle'
+VERSION = '0.1'
+DESCRIPTION = "Simple tool to toggle ON/OFF settings"
+
+VALUES = ['OFF','ON']
+
+# ====================
+# Exceptions
+# ====================
+
+# ====================
+# Helpers
+# ====================
+class WeePrint(object):
+ def write(self, text):
+ text = text.rstrip(' \0\n') # strip the null byte appended by pythons print
+ if text:
+ weechat.prnt(text,'')
+
+def registerFunction(function):
+ # Register a python function as a commandhandler
+ # Function needs to be named like weeFunction and
+ # is bound to /function
+ # docstring is used for weechat help
+ functionname = function.__name__ # guess what :)
+ weecommand = functionname[3:].lower() # strip the wee
+
+ doc = function.__doc__.splitlines()
+ arguments = doc[0] # First docstring line is the arguments string
+ description = doc[1][4:]
+ args_description = '\n'.join([line[4:] for line in doc[2:-1]]) # join rest and strip indentation
+
+ if not function.func_defaults: # use args default value as template
+ template = ''
+ elif len(function.func_defaults) == 1:
+ template = function.func_defaults[0]
+ elif len(function.func_defaults) == 2:
+ template = func.func_defaults[1]
+
+ weechat.add_command_handler(weecommand, functionname, description, arguments, args_description, template)
+
+def registerFunctions():
+ functions = [function for name, function in globals().iteritems() if name.startswith('wee') and callable(function)]
+ for func in functions:
+ registerFunction(func)
+
+# ====================
+# Functions
+# ====================
+def weeToggle(server, args="%o"):
+ """<setting>
+ Toggles any setting from ON to OFF and vice versa.
+ Example:
+ /toggle look_nicklist
+ """
+ option = args
+ currentvalue = weechat.get_config(option).upper()
+ if currentvalue not in VALUES:
+ print "%s cannot be toggled!" % option
+ else:
+ newvalue = VALUES[VALUES.index(currentvalue) - 1]
+ weechat.set_config(option, newvalue)
+ print "%s = %s" % (option, newvalue)
+ return weechat.PLUGIN_RC_OK
+
+# ====================
+# Let's Register!
+# ====================
+if __name__ == '__main__':
+ try:
+ import weechat
+ except ImportError:
+ print "This script is to be loaded as PythonScript in WeeChat"
+ print "Get WeeChat now at: http://weechat.flashtux.org/"
+ import sys
+ sys.exit(10)
+
+ # kick pythons print to weechat.prnt(msg, '')
+ sys.stdout = WeePrint()
+ weechat.register(NAME, VERSION, "", DESCRIPTION)
+ registerFunctions()
+
+
diff --git a/scripts/python/uname.py b/scripts/python/uname.py
new file mode 100644
index 000000000..c95ad3f17
--- /dev/null
+++ b/scripts/python/uname.py
@@ -0,0 +1,18 @@
+# This script sends "uname -a" output to current channel.
+# Just type /uname while chatting on some channel ;)
+
+# by Stalwart <stlwrt doggy gmail.com>
+#
+# Released under GPL licence.
+
+import weechat
+from os import popen
+
+def senduname(server, args):
+ unameout = popen ('uname -a')
+ uname = unameout.readline()
+ weechat.command(uname[:-1])
+ return 0
+
+weechat.register ('uname', '1.0', '', """Sends "uname -a" output to current channel""")
+weechat.add_command_handler ('uname', 'senduname')
diff --git a/scripts/python/urlgrab.py b/scripts/python/urlgrab.py
new file mode 100644
index 000000000..b34b73eb4
--- /dev/null
+++ b/scripts/python/urlgrab.py
@@ -0,0 +1,447 @@
+#
+# 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') )