🢀︎ weechat :: 6983fdd


commit 6983fddcc0af8a79b88e2adab7aa5c876d3dd5fb
Author: acidvegas <acid.vegas@acid.vegas>
Date:   Sun Jul 21 02:19:12 2019 -0400

    Updated

diff --git a/README.md b/README.md
index 63a76ae..da0a36b 100644
--- a/README.md
+++ b/README.md
@@ -14,20 +14,13 @@
 - [Notes](#notes)
 
 ### Requirements
-- [python-potr](https://pypi.org/project/python-potr/)
+- [certbot](https://certbot.eff.org/) *(optional: for relay security)*
+- [perl](https://www.perl.org/)/[python](https://www.python.org/) *(for scripts)*
+- [python-potr](https://pypi.org/project/python-potr/) *(optional: for [otr.py](scripts/otr.py) script)*
+- [weechat](https://weechat.org/)
 
 ### Setup
-```
-#!/bin/sh
-cd $HOME/.weechat && rm -r fifo.conf logger.conf lua.conf weechat.log xfer.conf logs/ lua/ xfer/
-git clone --depth 1 https://github.com/acidvegas/weechat.git $HOME/weechat
-mv $HOME/weechat/alias.conf $HOME/.weechat/alias.conf
-mv $HOME/weechat/scripts/*.pl $HOME/.weechat/perl/autoload/ && mv $HOME/weechat/scripts/*.py $HOME/.weechat/python/autoload/
-nano $HOME/.weechat/cert.pem && chmod 400 $HOME/.weechat/cert.pem
-# todo: certbot generation for relay (~/.weechat/ssl/relay.pem)
-#cat /etc/letsencrypt/live/localhost/{fullchain,privkey}.pem > ~username/.weechat/ssl/relay.pem
-#chown -R username:username ~username/.weechat/ssl/
-```
+See [setup](setup) script for help.
 
 ### Key Bindings
 | Key             | Description                        |
@@ -517,15 +510,15 @@ nano $HOME/.weechat/cert.pem && chmod 400 $HOME/.weechat/cert.pem
 ### Proxy
 ```
 /proxy add tor socks5 127.0.0.1 9050
-/set irc.server.networkname.proxy "tor"
+/set irc.server.CHANGEME.proxy tor
 ```
 
 ### Relay
 ```
-/set relay.network.password "mypassword"
-/set relay.network.totp_secret "secretpasswordbase32"
+/set relay.network.password "CHANGEME"
+/set relay.network.totp_secret "CHANGEME"
 /relay sslcertkey
-/relay add ssl.weechat 9000
+/relay add ssl.weechat CHANGEME
 ```
 
 ### Notes
diff --git a/scripts/cflood.pl b/scripts/cflood.pl
index f236a72..49825da 100644
--- a/scripts/cflood.pl
+++ b/scripts/cflood.pl
@@ -1,12 +1,40 @@
-#!/usr/bin/perl
-# original source by hzu & ported by wowaname (https://git.volatile.bz/cgit/wowaname/weechat-etc/plain/scripts/colourflood.pl)
-# modified by acidvegas (https://acid.vegas/weechat)
+#{{{ BSD License
+# Copyright (c) 2008 hzu/zionist
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. The name of the author may not be used to endorse or promote products
+#    derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+# THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#}}}
 
+# Ported from irssi to WeeChat by the Krusty Krab
 
 use strict;
 use warnings;
 no strict 'subs';
 
+my $SCRIPT_NAME = 'colourflood';
+my $SCRIPT_AUTHOR = 'hzu';
+my $SCRIPT_VERSION = '0.3';
+my $SCRIPT_LICENCE = 'BSD';
+my $SCRIPT_DESC = 'A-rab style ircing';
+
 my $USAGE = <<EOF;
 options:
     -r      Random back & foreground colours (default)
@@ -42,6 +70,25 @@ our %clr = (
   lightgray    => 15,
 );
 
+if (weechat::register($SCRIPT_NAME, $SCRIPT_AUTHOR, $SCRIPT_VERSION,
+ $SCRIPT_LICENCE, $SCRIPT_DESC, '', '')) {
+	weechat::hook_command('cflood', $SCRIPT_DESC, '[options] text',
+		$USAGE, '', 'cmd_cflood', '');
+
+	my %OPTIONS = (
+		dir => ['Database directory',
+			weechat::info_get('weechat_dir', '').'/yiffs'],
+		db => ['Default database', 'yiffs'],
+		solodb => ['Default database when nick is omitted', 'solos'],
+		);
+
+	for my $option (keys %OPTIONS) {
+		weechat::config_set_plugin($option, $OPTIONS{$option}[1])
+		 unless weechat::config_is_set_plugin($option);
+		weechat::config_set_desc_plugin($option, $OPTIONS{$option}[0]);
+	}
+}
+
 sub colour {
 	my ($fg, $bg, $text) = @_;
 	my $fore = ($fg =~ /^[0-9][0-9]?$/) ? $fg : $clr{$fg};
@@ -55,6 +102,7 @@ sub colour {
 sub parse {
 	my @args = ( split / +/, shift );
 	my ( %todo, $text, $body );
+
 	while ( ($_ = shift @args) ne '' ) {
 		/^-r$/ and next;
 		/^-f$/ and $todo{f} = shift @args, next;
@@ -65,6 +113,7 @@ sub parse {
 		$text = @args < 1 ? $_ : "$_ " . join ' ', @args;
 		last;
 	}
+
 	if (!(defined $todo{fg}) || !(defined $todo{bg})) {
 		$body = "";
 		my @rnd_clr = keys %clr;
@@ -86,15 +135,16 @@ sub parse {
 sub cmd_cflood {
 	my (undef, $buffer, $data) = @_;
 	my $ret;
+
 	return weechat::WEECHAT_RC_OK if ($data eq '');
+
 	chomp( $ret = parse($data) );
+
 	if ($ret =~ /\n/) {
 		map { weechat::command($buffer, "/msg * $_") } (split /\n/, $ret);
 	} else { 
 		weechat::command($buffer, "/msg * $ret");
 	}
+
 	return weechat::WEECHAT_RC_OK;
 }
-
-weechat::register("cflood", "acidvegas", "1.0", "ISC", "random text foreground/background", "", ""))
-weechat::hook_command("cflood", "random text foreground/background", "[options] text", $USAGE, "", "cmd_cflood", "");
\ No newline at end of file
diff --git a/scripts/clean/cflood.pl b/scripts/clean/cflood.pl
new file mode 100644
index 0000000..f236a72
--- /dev/null
+++ b/scripts/clean/cflood.pl
@@ -0,0 +1,100 @@
+#!/usr/bin/perl
+# original source by hzu & ported by wowaname (https://git.volatile.bz/cgit/wowaname/weechat-etc/plain/scripts/colourflood.pl)
+# modified by acidvegas (https://acid.vegas/weechat)
+
+
+use strict;
+use warnings;
+no strict 'subs';
+
+my $USAGE = <<EOF;
+options:
+    -r      Random back & foreground colours (default)
+    -f      Amount of times the message is flooded
+    -fg     font colour, available colours:
+                black, blue, green
+                lightred, red, magenta, orange
+                yellow, lightgreen, cyan,
+                lightcyan, lightblue,
+                lightmagenta, gray, lightgray.
+    -bg     background colour, available colours:
+                black, blue, green, red,
+                magenta, orange, green, cyan,
+                lightcyan, lightblue,
+                lightmagenta, gray, lightgray
+EOF
+
+our %clr = (
+  black        => 1,
+  blue         => 2,
+  green        => 3,
+  lightred     => 4,
+  red          => 5,
+  magenta      => 6,
+  orange       => 7,
+  yellow       => 8,
+  lightgreen   => 9,
+  cyan         => 10,
+  lightcyan    => 11,
+  lightblue    => 12,
+  lightmagenta => 13,
+  gray         => 14,
+  lightgray    => 15,
+);
+
+sub colour {
+	my ($fg, $bg, $text) = @_;
+	my $fore = ($fg =~ /^[0-9][0-9]?$/) ? $fg : $clr{$fg};
+	my $back = ($fg =~ /^[0-9][0-9]?$/) ? $bg : $clr{$bg};
+	$fore-- if $fore == $back;
+	$text = "\003$fore,$back $text \003$back,$fore $text ";
+	$text x= (int 400 / length $text);
+	return "$text\003";
+}
+
+sub parse {
+	my @args = ( split / +/, shift );
+	my ( %todo, $text, $body );
+	while ( ($_ = shift @args) ne '' ) {
+		/^-r$/ and next;
+		/^-f$/ and $todo{f} = shift @args, next;
+		/^-fg$/ and $todo{fg} = shift @args, next;
+		/^-bg$/ and $todo{bg} = shift @args, next;
+		/^-/ and weechat::print('', weechat::prefix('error').
+			'Invalid arguments (see /help cflood)'), return;
+		$text = @args < 1 ? $_ : "$_ " . join ' ', @args;
+		last;
+	}
+	if (!(defined $todo{fg}) || !(defined $todo{bg})) {
+		$body = "";
+		my @rnd_clr = keys %clr;
+		foreach ( 1 .. (defined $todo{f} ? $todo{f} : 1 ) ) {
+			$body .= colour($rnd_clr[rand @rnd_clr],
+				$rnd_clr[rand @rnd_clr], $text, $todo{f});
+			$body .= "\n";
+		}
+	} else {
+		$body = "";
+		foreach ( 1 .. (defined $todo{f} ? $todo{f} : 1 ) ) {
+			$body .= colour( $todo{fg}, $todo{bg}, $text );
+			$body .= "\n";
+		}
+	}
+	return $body;
+}
+
+sub cmd_cflood {
+	my (undef, $buffer, $data) = @_;
+	my $ret;
+	return weechat::WEECHAT_RC_OK if ($data eq '');
+	chomp( $ret = parse($data) );
+	if ($ret =~ /\n/) {
+		map { weechat::command($buffer, "/msg * $_") } (split /\n/, $ret);
+	} else { 
+		weechat::command($buffer, "/msg * $ret");
+	}
+	return weechat::WEECHAT_RC_OK;
+}
+
+weechat::register("cflood", "acidvegas", "1.0", "ISC", "random text foreground/background", "", ""))
+weechat::hook_command("cflood", "random text foreground/background", "[options] text", $USAGE, "", "cmd_cflood", "");
\ No newline at end of file
diff --git a/scripts/clean/fullwidth.py b/scripts/clean/fullwidth.py
new file mode 100644
index 0000000..c3b6a3a
--- /dev/null
+++ b/scripts/clean/fullwidth.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# original source by germainz (https://weechat.org/scripts/source/fullwidth.py.html)
+# modified by acidvegas (https://acid.vegas/weechat)
+
+import weechat
+
+def cmd_fullwidth(data, buf, args):
+	chars = []
+	for char in list(args):
+		ord_char = ord(char)
+		if ord_char == 32:
+			char = chr(12288)
+		elif ord_char > 32 and ord_char <= 126:
+			char = chr(ord_char + 65248)
+		chars.append(char)
+	weechat.command(buf, '/input send '+''.join(chars))
+	return weechat.WEECHAT_RC_OK
+
+if __name__ == '__main__':
+	weechat.register('fullwidth', 'acidvegas', '1.0', 'ISC', 'convert text to wide characters.', '', '')
+	weechat.hook_command('fullwidth', 'convert text to wide characters.', '<text>', '', '', 'cmd_fullwidth', '')
diff --git a/scripts/clean/masshl.py b/scripts/clean/masshl.py
new file mode 100644
index 0000000..149ac7e
--- /dev/null
+++ b/scripts/clean/masshl.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# original source by wowaname (https://git.volatile.bz/cgit/wowaname/weechat-etc/plain/scripts/masshl.py)
+# modified by acidvegas (https://acid.vegas/weechat)
+
+import weechat
+
+def cmd_masshl(data, buffer, args):
+	if not '%N' in args and '%n' not in args:
+		return weechat.WEECHAT_RC_OK
+	server   = weechat.buffer_get_string(buffer, 'localvar_server')
+	channel  = weechat.buffer_get_string(buffer, 'localvar_channel')
+	nicklist = weechat.infolist_get('irc_nick', '', server+','+channel)
+	nicks = []
+	while weechat.infolist_next(nicklist):
+		nicks.append(weechat.infolist_string(nicklist, 'name'))
+	weechat.infolist_free(nicklist)
+	nicks.pop(0)
+	i = -1
+	N_nicks = ''
+	output = args
+	for nick in nicks:
+		i += 1
+		if '%N' in args:
+			N_nicks += ' '+nick
+			if (nick != nicks[-1] and len(output) + len(N_nicks) + len(nicks[i]) < 300):
+				continue
+		else:
+			output = args.replace('%n', nick)
+		N_nicks = N_nicks.lstrip()
+		output = output.replace('%N', N_nicks)
+		weechat.command(buffer, output)
+		output = args
+		N_nicks = ''
+	return weechat.WEECHAT_RC_OK
+
+if __name__ == '__main__':
+	weechat.register('masshl', 'acidvegas', '1.0', 'ISC', 'mass highlight all nicks in a channel.', '', '')
+	weechat.hook_command('masshl', 'mass highlight all nicks in a channel.', '%n - 1 nick per message\n%N - all nicks in one message', 'cmd_masshl', '')
\ No newline at end of file
diff --git a/scripts/replace.py b/scripts/clean/replace.py
similarity index 100%
rename from scripts/replace.py
rename to scripts/clean/replace.py
diff --git a/scripts/fullwidth.py b/scripts/fullwidth.py
index 4d83ef5..d5b1263 100644
--- a/scripts/fullwidth.py
+++ b/scripts/fullwidth.py
@@ -1,20 +1,66 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# original source by germainz (https://weechat.org/scripts/source/fullwidth.py.html)
-# modified by acidvegas (https://acid.vegas/weechat)
+#
+# Copyright (C) 2013-2014 Germain Z. <germanosz@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
+#
 
+#
+# Convert text to its fullwidth equivalent and send it to buffer.
+#
+
+
+import sys
 import weechat
 
-def cmd_fullwidth(data, buf, args):
-	chars = []
-	for char in list(args):
-		ord_char = ord(char)
-		if ord_char >= 32 and ord_char <= 126:
-			char = chr(ord_char + 65248)
-		chars.append(char)
-	weechat.command(buf, '/input send ' + ''.join(chars))
-	return weechat.WEECHAT_RC_OK
-
-if __name__ == '__main__':
-	weechat.register('fullwidth', 'acidvegas', '1.0', 'ISC', 'convert text to wide characters.', '', '')
-	weechat.hook_command('fullwidth', 'convert text to wide characters.', '<text>', '', '', 'cmd_fullwidth', '')
+
+SCRIPT_NAME = "fullwidth"
+SCRIPT_AUTHOR = "GermainZ <germanosz@gmail.com>"
+SCRIPT_VERSION = "0.1.1"
+SCRIPT_LICENSE = "GPL3"
+SCRIPT_DESC = ("Convert text to its fullwidth equivalent and send it "
+               "to buffer.")
+
+PY3 = sys.version > '3'
+
+
+if PY3:
+    unichr = chr
+    def send(buf, text):
+        weechat.command(buf, "/input send {}".format(text))
+else:
+    def send(buf, text):
+        weechat.command(buf, "/input send {}".format(text.encode("utf-8")))
+
+def cb_fullwidth_cmd(data, buf, args):
+    """Callback for ``/fullwidth``, convert and send the given text."""
+    chars = []
+    if not PY3:
+        args = args.decode("utf-8")
+    for char in list(args):
+        ord_char = ord(char)
+        if ord_char == 32:
+            char = unichr(12288)
+        elif ord_char > 32 and ord_char <= 126:
+            char = unichr(ord_char + 65248)
+        chars.append(char)
+    send(buf, ''.join(chars))
+    return weechat.WEECHAT_RC_OK
+
+
+if __name__ == "__main__":
+    weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION,
+                     SCRIPT_LICENSE, SCRIPT_DESC, '', '')
+    weechat.hook_command("fullwidth", SCRIPT_DESC, "<text>", '', '',
+                         "cb_fullwidth_cmd", '')
diff --git a/scripts/masshl.py b/scripts/masshl.py
index 5d0f679..cec121b 100644
--- a/scripts/masshl.py
+++ b/scripts/masshl.py
@@ -1,67 +1,80 @@
+# Released into the Public Domain
+
 import random
+#from threading import Thread
+#from time import sleep
 import weechat
 
-SCRIPT_NAME    = 'masshl'
-SCRIPT_AUTHOR  = 'The Krusty Krab <wowaname@volatile.ch>'
-SCRIPT_VERSION = '1.0'
-SCRIPT_LICENSE = 'Public domain'
-SCRIPT_DESC    = 'Provides nicklist hooks.'
+SCRIPT_NAME    = "masshl"
+SCRIPT_AUTHOR  = "The Krusty Krab <wowaname@volatile.ch>"
+SCRIPT_VERSION = "1.0"
+SCRIPT_LICENSE = "Public domain"
+SCRIPT_DESC    = "Provides nicklist hooks."
 
-if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, '', ''):
-	weechat.hook_command('masshl', SCRIPT_DESC,
-		'[-do <delay>] text (broken, currently no-op)',
-		'-d  Specify a delay at the beginning (e.g. -d 1 for\n'
-		'    one second) to insert a delay between messages.\n'
-		'    %n - replace with next nick\n'
-		'    %N - replace with as many nicks as possible per line\n'
-		'    %r - replace with random hex value to thwart antispam\n'
-		'-o  Include your own nick in output',
-		'-od', 'masshl_cmd_cb', '')
+if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION,
+	SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
+	weechat.hook_command("masshl",
+		SCRIPT_DESC,
+		"[-do <delay>] text (broken, currently no-op)",
+		"-d  Specify a delay at the beginning (e.g. -d 1 for\n"
+		"    one second) to insert a delay between messages.\n"
+		"    %n - replace with next nick\n"
+		"    %N - replace with as many nicks as possible per line\n"
+		"    %r - replace with random hex value to thwart antispam\n"
+		"-o  Include your own nick in output",
+		"-od", "masshl_cmd_cb", "")
 
 class Loop():
 	def __init__(self, buffer, nicks, input, input_method, N_param, delay, opts):
-		self.buffer       = buffer
-		self.nicks        = nicks
-		self.input        = input
+		self.buffer = buffer
+		self.nicks = nicks
+		self.input = input
 		self.input_method = input_method
-		self.N_param      = N_param
-		self.delay        = delay
-		self.opts         = opts
+		self.N_param = N_param
+		self.delay = delay
+		self.opts = opts
 
 	def run(self):
 		i = -('o' not in self.opts)
 		if i == -1: self.nicks.pop(0)
-		N_nicks = ''
+		N_nicks = ""
 		output = self.input
 		for nick in self.nicks:
 			i += 1
 			if self.N_param:
-				N_nicks += ' %s' % nick
+				N_nicks += " %s" % nick
 				if (nick != self.nicks[-1] and
 				 len(output) + len(N_nicks) + len(self.nicks[i]) < 300):
 					continue
-			else: output = self.input.replace('%n',nick)
+			else: output = self.input.replace("%n",nick)
 			N_nicks = N_nicks.lstrip()
-			output = output.replace('%N',N_nicks)
-			output = output.replace('%r','%08x' % random.randint(0,0xffffffff))
-			if self.input_method == 'keybinding':
-				weechat.buffer_set(self.buffer, 'input', output)
+			output = output.replace("%N",N_nicks)
+			output = output.replace("%r","%08x" % random.randint(0,0xffffffff))
+			if self.input_method == "keybinding":
+				weechat.buffer_set(self.buffer, "input", output)
 			else:
 				weechat.command(self.buffer, output)
+#			sleep(self.delay)
 			output = self.input
-			N_nicks = ''
+			N_nicks = ""
 
 def masshl_cmd_cb(data, buffer, args):
 	input = args
-	input_method = 'command'
+
+	input_method = "command"
 	server = weechat.buffer_get_string(buffer, 'localvar_server')
 	channel = weechat.buffer_get_string(buffer, 'localvar_channel')
+
 	if not input or (input[0] == '-' and input.find(' ') == -1):
-		input = (input + ' ' if input else '') + weechat.buffer_get_string(buffer, 'input')
-		input_method = 'keybinding'
-	N_param = '%N' in input
-	if not N_param and '%n' not in input and '%r' not in input:
+		input = (input + ' ' if input else '') + weechat.buffer_get_string(buffer, "input")
+		input_method = "keybinding"
+
+	N_param = "%N" in input
+	if not N_param and "%n" not in input and "%r" not in input:
+		# if we bind this to Enter key, we don't want useless flooding on
+		# normal messages
 		return weechat.WEECHAT_RC_OK
+
 	optstop = input and input[0] == '-' and input.find(' ')
 	opts = input[1:optstop] if optstop else ''
 	cmdstop = 'd' in opts and input.find(' ', optstop+1)
@@ -71,16 +84,23 @@ def masshl_cmd_cb(data, buffer, args):
 		where = input.find(find, cmdstop+1)
 		try: delay = float(find)
 		except ValueError:
-			weechat.prnt(buffer, 'delay must be a float value!')
+			weechat.prnt(buffer, "delay must be a float value!")
 			return weechat.WEECHAT_RC_ERROR
 		input = input[where+len(find):]
-	else:
-		input = input[optstop+bool(optstop):]
-	nicklist = weechat.infolist_get('irc_nick', '', '%s,%s' % (server,channel))
+	else: input = input[optstop+bool(optstop):]
+
+	nicklist = weechat.infolist_get("irc_nick", "", "%s,%s" % (server,channel))
+
+	# dealing with the cursor can get a little tricky. let's use a dict
+	# instead, that way we can manipulate just what we need and we can
+	# do that with builtins
 	nicks = []
 	while weechat.infolist_next(nicklist):
-		nicks.append(weechat.infolist_string(nicklist, 'name'))
+		nicks.append(weechat.infolist_string(nicklist, "name"))
+
 	weechat.infolist_free(nicklist)
+
 	workhorse = Loop(buffer, nicks, input, input_method, N_param, delay, opts)
 	workhorse.run()
+
 	return weechat.WEECHAT_RC_OK
diff --git a/scripts/text_replace.py b/scripts/text_replace.py
new file mode 100644
index 0000000..2138670
--- /dev/null
+++ b/scripts/text_replace.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2009 by xt <xt@bash.no>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+#
+# (this script requires WeeChat 0.3.0 or newer)
+#
+# History:
+# 2019-06-17, Brad Hubbard <bhubbard@redhat.com>
+#   version 0.6: replace iteritems with items for python3 compatability
+# 2011-07-17, Sébastien Helleu <flashcode@flashtux.org>
+#   version 0.5: allow empty value for pairs or words
+# 2011-02-01, xt
+#   version 0.4: improve regexp for word replacement
+# 2010-11-26, xt <xt@bash.no>
+#   version 0.3: don't replace in /set commands
+# 2009-10-27, xt <xt@bash.no>
+#   version 0.2: also replace on words
+# 2009-10-22, xt <xt@bash.no>
+#   version 0.1: initial release
+
+import weechat as w
+import re
+
+SCRIPT_NAME    = "text_replace"
+SCRIPT_AUTHOR  = "xt <xt@bash.no>"
+SCRIPT_VERSION = "0.6"
+SCRIPT_LICENSE = "GPL3"
+SCRIPT_DESC    = "Replaces text you write with replacement text"
+
+# script options
+settings = {
+        'replacement_pairs': '(:=:),):=:(',   # pairs separated by , orig text and replacement separated by =
+        'replacement_words': 'hhe=heh',       # words separated by , orig text and replacement separated by =
+}
+
+
+
+if w.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE,
+                    SCRIPT_DESC, "", ""):
+    for option, default_value in settings.items():
+        if not w.config_is_set_plugin(option):
+            w.config_set_plugin(option, default_value)
+
+    # Hooks we want to hook
+    hook_command_run = {
+        "input" : ("/input return",  "command_run_input"),
+    }
+    # Hook all hooks !
+    for hook, value in hook_command_run.items():
+        w.hook_command_run(value[0], value[1], "")
+
+
+def command_run_input(data, buffer, command):
+    """ Function called when a command "/input xxxx" is run """
+    if command == "/input return": # As in enter was pressed.
+
+        # Get input contents
+        input_s = w.buffer_get_string(buffer, 'input')
+
+        # Skip modification of settings
+        if input_s.startswith('/set '):
+            return w.WEECHAT_RC_OK
+
+        # Iterate transformation pairs
+        for replace_item in w.config_get_plugin('replacement_pairs').split(','):
+            if replace_item:
+                orig, replaced = replace_item.split('=')
+                input_s = input_s.replace(orig, replaced)
+        # Iterate words
+        for replace_item in w.config_get_plugin('replacement_words').split(','):
+            if replace_item:
+                orig, replaced = replace_item.split('=')
+                # Search for whitespace+word+whitespace and replace the word
+                input_s = re.sub('(\s+|^)%s(\s+|$)' %orig, '\\1%s\\2' %replaced, input_s)
+
+        # Spit it out
+        w.buffer_set(buffer, 'input', input_s)
+    return w.WEECHAT_RC_OK
diff --git a/setup b/setup
new file mode 100755
index 0000000..31686b9
--- /dev/null
+++ b/setup
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+setup_weechat() {
+	weechat -r "/set weechat.plugin.autoload *,!fifo,!guile,!logger,!lua,!ruby,!spell,!tcl,!xfer;/quit"
+	cd $HOME/.weechat && rm -r fifo.conf logger.conf lua.conf weechat.log xfer.conf logs/ lua/ xfer/
+	git clone --depth 1 https://github.com/acidvegas/weechat.git $HOME/weechat
+	mv $HOME/weechat/alias.conf $HOME/.weechat/alias.conf
+	mv $HOME/weechat/scripts/*.pl $HOME/.weechat/perl/autoload/ && mv $HOME/weechat/scripts/*.py $HOME/.weechat/python/autoload/
+	nano $HOME/.weechat/cert.pem && chmod 400 $HOME/.weechat/cert.pem
+}
+
+setup_relay() {
+	certbot certonly --standalone -d chat.acid.vegas -m acid.vegas@acid.vegas
+	cat /etc/letsencrypt/live/localhost/{fullchain,privkey}.pem > $HOME/.weechat/ssl/relay.pem
+	chown -R $USER:$USER $HOME/.weechat/ssl/
+	echo -e "[Unit]\nDescription=Lets Encrypt renewal\n\n[Service]\nType=oneshot\nExecStart=/usr/bin/certbot renew -n -q --agree-tos --post-hook=\"systemctl reload nginx\"" > /etc/systemd/system/certbot.service
+	echo -e "[Unit]\nDescription=Twice daily renewal of Let's Encrypts certificates\n\n[Timer]\nOnCalendar=0/12:00:00\nRandomizedDelaySec=1h\nPersistent=true\n\n[Install]\nWantedBy=timers.target" > /etc/systemd/system/certbot.timer
+	systemctl enable certbot.timer && systemctl start certbot.timer
+}
\ No newline at end of file