aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/skype
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/skype')
-rw-r--r--protocols/skype/.mailmap1
-rw-r--r--protocols/skype/HACKING64
-rw-r--r--protocols/skype/Makefile77
-rw-r--r--protocols/skype/README70
-rw-r--r--protocols/skype/asciidoc.conf7
-rw-r--r--protocols/skype/skype.c176
-rw-r--r--protocols/skype/skyped.py279
-rw-r--r--protocols/skype/skyped.txt42
-rw-r--r--protocols/skype/t/Makefile33
-rw-r--r--protocols/skype/t/add-yes-bitlbee.mock8
-rw-r--r--protocols/skype/t/add-yes-skyped.mock23
-rw-r--r--protocols/skype/t/added-no-bitlbee.mock9
-rw-r--r--protocols/skype/t/added-no-skyped.mock15
-rw-r--r--protocols/skype/t/added-yes-bitlbee.mock9
-rw-r--r--protocols/skype/t/added-yes-skyped.mock25
-rw-r--r--protocols/skype/t/bitlbee.conf0
-rw-r--r--protocols/skype/t/call-bitlbee.mock11
-rw-r--r--protocols/skype/t/call-failed-bitlbee.mock9
-rw-r--r--protocols/skype/t/call-failed-skyped.mock21
-rw-r--r--protocols/skype/t/call-skyped.mock26
-rw-r--r--protocols/skype/t/called-no-bitlbee.mock10
-rw-r--r--protocols/skype/t/called-no-skyped.mock24
-rw-r--r--protocols/skype/t/called-yes-bitlbee.mock9
-rw-r--r--protocols/skype/t/called-yes-skyped.mock22
-rw-r--r--protocols/skype/t/ctcp-help-bitlbee.mock9
-rw-r--r--protocols/skype/t/ctcp-help-skyped.mock16
-rw-r--r--protocols/skype/t/filetransfer-bitlbee.mock10
-rw-r--r--protocols/skype/t/filetransfer-skyped.mock37
-rw-r--r--protocols/skype/t/group-read-bitlbee.mock14
-rw-r--r--protocols/skype/t/group-read-skyped.mock36
-rw-r--r--protocols/skype/t/groupchat-invite-bitlbee.mock11
-rw-r--r--protocols/skype/t/groupchat-invite-skyped.mock48
-rw-r--r--protocols/skype/t/groupchat-invited-bitlbee.mock8
-rw-r--r--protocols/skype/t/groupchat-invited-skyped.mock58
-rw-r--r--protocols/skype/t/groupchat-leave-bitlbee.mock11
-rw-r--r--protocols/skype/t/groupchat-leave-skyped.mock63
-rw-r--r--protocols/skype/t/info-bitlbee.mock9
-rw-r--r--protocols/skype/t/info-skyped.mock46
-rwxr-xr-xprotocols/skype/t/irssi/livetest-irssi.sh109
-rw-r--r--protocols/skype/t/irssi/skype-call.test13
-rw-r--r--protocols/skype/t/irssi/skype-info.test12
-rw-r--r--protocols/skype/t/irssi/skype-login.test10
-rw-r--r--protocols/skype/t/irssi/skype-msg.test17
-rw-r--r--protocols/skype/t/irssi/trigger.pl1225
-rwxr-xr-xprotocols/skype/t/livetest-bitlbee.sh116
-rw-r--r--protocols/skype/t/login-bitlbee.mock7
-rw-r--r--protocols/skype/t/login-skyped.mock16
-rw-r--r--protocols/skype/t/msg-bitlbee.mock9
-rw-r--r--protocols/skype/t/msg-skyped.mock49
-rw-r--r--protocols/skype/t/set-mood-text-bitlbee.mock9
-rw-r--r--protocols/skype/t/set-mood-text-skyped.mock14
-rwxr-xr-xprotocols/skype/test.py135
52 files changed, 1218 insertions, 1869 deletions
diff --git a/protocols/skype/.mailmap b/protocols/skype/.mailmap
deleted file mode 100644
index cc8d43f9..00000000
--- a/protocols/skype/.mailmap
+++ /dev/null
@@ -1 +0,0 @@
-Miklos Vajna <vmiklos@frugalware.org>
diff --git a/protocols/skype/HACKING b/protocols/skype/HACKING
index f5516832..935856a7 100644
--- a/protocols/skype/HACKING
+++ b/protocols/skype/HACKING
@@ -17,10 +17,64 @@ python skyped.py -n -d
4) irssi
-== Get the code from git
-To get the code directly from git, you need:
+== Tests
-git clone git://vmiklos.hu/bitlbee-skype
-cd bitlbee-skype
-make autogen
+The plugin is tested with a mocked IRC client and a mocked skyped.
+
+=== Requirements
+
+Python pexpect module is required to run the tests.
+
+To run tests with bitlbee built in a development tree and not (the one)
+installed in the system (e.g. /usr), make sure to specify --plugindir= option to
+./configure script during the build process:
+
+bitlbee% ./configure --skype=1 --plugindir="$(realpath .)"
+
+Otherwise bitlbee will try to load skype.so (among other things) from /usr/lib,
+which is probably not what you want to test, or produce "Unknown protocol"
+error.
+
+=== Running
+
+Tests can be run by running test.py script in this ("protocols/skype")
+directory.
+
+For more control over how/which tests are being run from there, use "python -m
+unittest" command:
+
+bitlbee/protocols/skype% python -m unittest test
+bitlbee/protocols/skype% python -m unittest -f test
+bitlbee/protocols/skype% python -m unittest test.Test.testMsg
+
+If bitlbee crashes during tests with SIGSEGV (segmentation fault), it's likely
+that there is some problem with skype.c plugin.
+To get a backtrace of such crash, use:
+
+bitlbee/protocols/skype% ATTACH_GDB=true python -m unittest test.Test.testMsg
+
+Example shows running "testMsg" test with gdb attached to bitlbee, which will
+produce full backtrace in "t/gdb-<pid>.log" files (see pid in pexpect error
+output of the test).
+
+=== Adding new tests
+
+To add a new test, the following steps are necessary:
+
+1) Add a new -skyped.mock file: just do the test manually, copy&paste the
+skyped output and clean it up, so Alice talks to Bob. You can test the created
+mock file by starting skyped with the -m option, and testing it from an IRC
+client manually.
+
+2) Add a new -bitlbee.mock file: do the test manually from irssi, and use:
+
+/connect -rawlog rawlog localhost
+
+Then clean up the rawlog: the input lines are parsed as matching patterns, so
+boring prefix/suffix text can be left out, non-interesting lines can be
+deleted. The output lines still have to be strict IRC commands, as usual.
+
+3) Add the new test to test.py and run it!
+
+// vim: ft=asciidoc
diff --git a/protocols/skype/Makefile b/protocols/skype/Makefile
index 455a21f2..6548bfb9 100644
--- a/protocols/skype/Makefile
+++ b/protocols/skype/Makefile
@@ -3,10 +3,7 @@ ifdef _SRCDIR_
_SRCDIR_ := $(_SRCDIR_)protocols/skype/
endif
-VERSION = 0.9.0
DATE := $(shell date +%Y-%m-%d)
-# latest stable
-BITLBEE_VERSION = 3.0.1
INSTALL = install
ASCIIDOC = yes
@@ -16,69 +13,17 @@ else
MANPAGES =
endif
-ifeq ($(BITLBEE),yes)
-LIBS = skype.$(SHARED_EXT)
-else
-LIBS =
-endif
-
-all: $(LIBS) $(MANPAGES)
-
-skype.$(SHARED_EXT): $(_SRCDIR_)skype.c config.mak
-ifeq ($(BITLBEE),yes)
- $(CC) $(CFLAGS) $(SHARED_FLAGS) -o skype.$(SHARED_EXT) $(_SRCDIR_)skype.c $(LDFLAGS)
-endif
-
-install: all install-doc
-ifeq ($(BITLBEE),yes)
- $(INSTALL) -d $(DESTDIR)$(plugindir)
- $(INSTALL) skype.$(SHARED_EXT) $(DESTDIR)$(plugindir)
-endif
-ifeq ($(SKYPE4PY),yes)
- $(INSTALL) -d $(DESTDIR)$(bindir)
- $(INSTALL) -d $(DESTDIR)$(sysconfdir)
- $(INSTALL) skyped.py $(DESTDIR)$(bindir)/skyped
- perl -p -i -e 's|/usr/local/etc/skyped|$(sysconfdir)|' $(DESTDIR)$(bindir)/skyped
- $(INSTALL) -m644 skyped.conf.dist $(DESTDIR)$(sysconfdir)/skyped.conf
- perl -p -i -e 's|\$${prefix}|$(prefix)|' $(DESTDIR)$(sysconfdir)/skyped.conf
- $(INSTALL) -m644 skyped.cnf $(DESTDIR)$(sysconfdir)
-endif
-
-client: $(_SRCDIR_)client.c
-
-autogen: configure.ac
- cp $(shell ls /usr/share/automake-*/install-sh | tail -n1) ./
- autoconf
+all: $(MANPAGES)
clean:
- rm -f $(LIBS) $(MANPAGES)
-
-distclean: clean
- rm -f config.log config.mak config.status $(MANPAGES)
-
-autoclean: distclean
- rm -rf aclocal.m4 autom4te.cache configure install-sh
+ rm -f $(MANPAGES)
# take this from the kernel
check:
- perl checkpatch.pl --no-tree --file skype.c
+ perl checkpatch.pl --show-types --ignore LONG_LINE,CAMELCASE --no-tree --file skype.c
test: all
- $(MAKE) -C t/ all
-
-dist:
- git archive --format=tar --prefix=bitlbee-skype-$(VERSION)/ HEAD | tar xf -
- mkdir -p bitlbee-skype-$(VERSION)
- git log --no-merges |git name-rev --tags --stdin > bitlbee-skype-$(VERSION)/Changelog
- make -C bitlbee-skype-$(VERSION) autogen
- tar czf bitlbee-skype-$(VERSION).tar.gz bitlbee-skype-$(VERSION)
- rm -rf bitlbee-skype-$(VERSION)
-
-release:
- git tag $(VERSION)
- $(MAKE) dist
- gpg --comment "See http://vmiklos.hu/gpg/ for info" \
- -ba bitlbee-skype-$(VERSION).tar.gz
+ ./test.py
doc: $(MANPAGES)
@@ -91,17 +36,5 @@ endif
uninstall-doc:
rm -f $(DESTDIR)$(MANDIR)/man1/skyped.1*
-HEADER.html: README Makefile
- asciidoc -a toc -a numbered -a sectids -o HEADER.html -a icons -a data-uri --attribute iconsdir=./images/icons README
- sed -i 's|@VERSION@|$(VERSION)|g' HEADER.html
- sed -i 's|@BITLBEE_VERSION@|$(BITLBEE_VERSION)|g' HEADER.html
-
-Changelog: .git/refs/heads/master
- git log --no-merges |git name-rev --tags --stdin >Changelog
-
-AUTHORS: .git/refs/heads/master
- git shortlog -s -n |sed 's/.*\t//'> AUTHORS
-
%.1: $(_SRCDIR_)%.txt $(_SRCDIR_)asciidoc.conf
- a2x --asciidoc-opts="-f $(_SRCDIR_)asciidoc.conf" \
- -a bs_version=$(VERSION) -a bs_date=$(DATE) -f manpage -D . $<
+ a2x --asciidoc-opts="-f $(_SRCDIR_)asciidoc.conf" -a bee_date=$(DATE) -f manpage -D . $<
diff --git a/protocols/skype/README b/protocols/skype/README
index 2c962d54..b9f22481 100644
--- a/protocols/skype/README
+++ b/protocols/skype/README
@@ -30,7 +30,7 @@ not..)
== Requirements
-* Skype >= 1.4.0.99. The latest version I've tested is 2.1.0.81.
+* Skype >= 1.4.0.99. The latest version I've tested is 4.1.0.20.
* BitlBee >= 3.0. The latest version I've tested is @BITLBEE_VERSION@. Use
old versions (see the NEWS file about which one) if you have older BitlBee
installed.
@@ -144,62 +144,7 @@ This will install the plugin to where BitlBee expects them, which is
=== Configuring
-- Set up `~/.skyped/skyped.conf`: Create the `~/.skyped` directory, copy
- `skyped.conf` and `skyped.cnf` from
- `/usr/local/etc/skyped/skyped.conf` to `~/.skyped`, adjust `username`
- and `password`. The `username` should be your Skype login and the
- `password` can be whatever you want, but you will have to specify that
- one when adding the Skype account to BitlBee (see later).
-
-NOTE: Here, and later - `/usr/local/etc` can be different on your installation
-if you used the `--sysconfdir` switch when running bitlbee-skype's `configure`.
-
-- Generate the SSL pem files:
-
-----
-# cd ~/.skyped
-# openssl req -new -x509 -days 365 -nodes -config skyped.cnf -out skyped.cert.pem \
- -keyout skyped.key.pem
-----
-
-NOTE: Maybe you want to adjust the permissions in the `~/.skyped`
-dir. For example make it readable by just your user.
-
-- Start `skyped` (the tcp server):
-
-----
-$ skyped
-----
-
-- Start your `IRC` client, connect to BitlBee and add your account:
-
-----
-account add skype <user> <pass>
-account skype set server localhost
-----
-
-<user> should be your Skype account name, <pass> should be the one you declared
-in `skyped.conf`. If you want to run skyped on a remote machine, replace
-`localhost` with the name of the machine.
-
-If you are running skyped on a custom port:
-
-----
-account skype set port <port>
-----
-
-If you want to set your full name (optional):
-
-----
-account skype set display_name "John Smith"
-----
-
-If you want to see your skypeout contacts online as well (they are
-offline by default):
-
-----
-account skype set skypeout_offline false
-----
+See the manpage of `skyped`.
== Setting up Skype in a VNC server (optional)
@@ -346,12 +291,14 @@ $ skyped -n -d
* `account skype set test_join true`
-- Mood texts are not shown by default. If you want to see it:
+- Mood texts are not shown by default.
- * `account skype set show_moods true`
+ * If you want to see them: `account skype set show_moods true`
+ * If you want to change your mood text: `account skype set mood_text 'foo bar'`
- Group support:
+ * To enable: `account skype set read_groups true`
* Skype groups are told to BitlBee
* The usual `/invite` in a group channel adds the buddy to the group in skype
as well (and if necessary, it creates a new group in Skype)
@@ -371,7 +318,7 @@ $ skyped -n -d
== I would like to have support for ...
If something does not work and it's not in the TODO section, then please
-contact me! Please also try the link:HACKING[git version] before reporting a bug, your
+contact me! Please also try the bzr version before reporting a bug, your
problem may be already fixed there.
In fact, of course, I wrote this documentation after figured out how to do this
@@ -391,9 +338,6 @@ You can reach some screenshots link:shot[here].
== Additional resources
-You can reach the Changelog link:Changelog[here], and a gitweb interface
-http://vmiklos.hu/gitweb/?p=bitlbee-skype.git[here].
-
The Skype API documentation is
http://developer.skype.com/resources/public_api_ref.zip[here] if you're
interested.
diff --git a/protocols/skype/asciidoc.conf b/protocols/skype/asciidoc.conf
index 24a649c1..f52b3ad6 100644
--- a/protocols/skype/asciidoc.conf
+++ b/protocols/skype/asciidoc.conf
@@ -4,14 +4,13 @@ ifdef::backend-docbook[]
template::[header-declarations]
<refentry>
<refentryinfo>
- <date>{bs_date}</date>
+ <date>{bee_date}</date>
</refentryinfo>
<refmeta>
<refentrytitle>{mantitle}</refentrytitle>
<manvolnum>{manvolnum}</manvolnum>
- <refmiscinfo class="source">bitlbee-skype</refmiscinfo>
- <refmiscinfo class="version">{bs_version}</refmiscinfo>
- <refmiscinfo class="manual">bitlbee-skype manual</refmiscinfo>
+ <refmiscinfo class="source">BitlBee</refmiscinfo>
+ <refmiscinfo class="manual">BitlBee manual</refmiscinfo>
</refmeta>
<refnamediv>
<refname>{manname}</refname>
diff --git a/protocols/skype/skype.c b/protocols/skype/skype.c
index 8638b5c1..7ce562d4 100644
--- a/protocols/skype/skype.c
+++ b/protocols/skype/skype.c
@@ -1,7 +1,7 @@
/*
* skype.c - Skype plugin for BitlBee
*
- * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012 by Miklos Vajna <vmiklos@frugalware.org>
+ * Copyright (c) 2007-2013 by Miklos Vajna <vmiklos@vmiklos.hu>
*
* 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
@@ -28,7 +28,7 @@
#define SKYPE_DEFAULT_SERVER "localhost"
#define SKYPE_DEFAULT_PORT "2727"
-#define IRC_LINE_SIZE 1024
+#define IRC_LINE_SIZE 16384
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
/*
@@ -45,6 +45,8 @@ enum {
enum {
SKYPE_FILETRANSFER_NEW = 1,
+ SKYPE_FILETRANSFER_TRANSFERRING,
+ SKYPE_FILETRANSFER_COMPLETED,
SKYPE_FILETRANSFER_FAILED
};
@@ -80,6 +82,8 @@ struct skype_data {
int call_out;
/* Same for file transfers. */
int filetransfer_status;
+ /* Path of the file being transferred. */
+ char *filetransfer_path;
/* Using /j #nick we want to have a groupchat with two people. Usually
* not (default). */
char *groupchat_with;
@@ -113,6 +117,8 @@ struct skype_data {
/* Pending user which has to be added to the next group which is
* created. */
char *pending_user;
+ /* If the info command was used, to determine what to do with FULLNAME result. */
+ int is_info;
};
struct skype_away_state {
@@ -189,7 +195,7 @@ int skype_printf(struct im_connection *ic, char *fmt, ...)
static void skype_buddy_ask_yes(void *data)
{
struct skype_buddy_ask_data *bla = data;
- skype_printf(bla->ic, "SET USER %s ISAUTHORIZED TRUE",
+ skype_printf(bla->ic, "SET USER %s ISAUTHORIZED TRUE\n",
bla->handle);
g_free(bla->handle);
g_free(bla);
@@ -198,7 +204,7 @@ static void skype_buddy_ask_yes(void *data)
static void skype_buddy_ask_no(void *data)
{
struct skype_buddy_ask_data *bla = data;
- skype_printf(bla->ic, "SET USER %s ISAUTHORIZED FALSE",
+ skype_printf(bla->ic, "SET USER %s ISAUTHORIZED FALSE\n",
bla->handle);
g_free(bla->handle);
g_free(bla);
@@ -213,8 +219,7 @@ void skype_buddy_ask(struct im_connection *ic, char *handle, char *message)
bla->ic = ic;
bla->handle = g_strdup(handle);
- buf = g_strdup_printf("The user %s wants to add you to "
- "his/her buddy list, saying: '%s'.", handle, message);
+ buf = g_strdup_printf("The user %s wants to add you to his/her buddy list, saying: '%s'.", handle, message);
imcb_ask(ic, buf, bla, skype_buddy_ask_yes, skype_buddy_ask_no);
g_free(buf);
}
@@ -222,7 +227,7 @@ void skype_buddy_ask(struct im_connection *ic, char *handle, char *message)
static void skype_call_ask_yes(void *data)
{
struct skype_buddy_ask_data *bla = data;
- skype_printf(bla->ic, "SET CALL %s STATUS INPROGRESS",
+ skype_printf(bla->ic, "SET CALL %s STATUS INPROGRESS\n",
bla->handle);
g_free(bla->handle);
g_free(bla);
@@ -231,7 +236,7 @@ static void skype_call_ask_yes(void *data)
static void skype_call_ask_no(void *data)
{
struct skype_buddy_ask_data *bla = data;
- skype_printf(bla->ic, "SET CALL %s STATUS FINISHED",
+ skype_printf(bla->ic, "SET CALL %s STATUS FINISHED\n",
bla->handle);
g_free(bla->handle);
g_free(bla);
@@ -316,8 +321,10 @@ static void skype_parse_users(struct im_connection *ic, char *line)
char **i, **nicks;
nicks = g_strsplit(line + 6, ", ", 0);
- for (i = nicks; *i; i++)
+ for (i = nicks; *i; i++) {
skype_printf(ic, "GET USER %s ONLINESTATUS\n", *i);
+ skype_printf(ic, "GET USER %s FULLNAME\n", *i);
+ }
g_strfreev(nicks);
}
@@ -371,9 +378,17 @@ static void skype_parse_user(struct im_connection *ic, char *line)
*buf ? buf : NULL);
if (set_getbool(&ic->acc->set, "show_moods"))
imcb_log(ic, "User `%s' changed mood text to `%s'", user, buf);
- } else if (!strncmp(ptr, "FULLNAME ", 9))
- sd->info_fullname = g_strdup(ptr + 9);
- else if (!strncmp(ptr, "PHONE_HOME ", 11))
+ } else if (!strncmp(ptr, "FULLNAME ", 9)) {
+ char *name = ptr + 9;
+ if (sd->is_info) {
+ sd->is_info = FALSE;
+ sd->info_fullname = g_strdup(name);
+ } else {
+ char *buf = g_strdup_printf("%s@skype.com", user);
+ imcb_rename_buddy(ic, buf, name);
+ g_free(buf);
+ }
+ } else if (!strncmp(ptr, "PHONE_HOME ", 11))
sd->info_phonehome = g_strdup(ptr + 11);
else if (!strncmp(ptr, "PHONE_OFFICE ", 13))
sd->info_phoneoffice = g_strdup(ptr + 13);
@@ -408,8 +423,7 @@ static void skype_parse_user(struct im_connection *ic, char *line)
sd->info_about = g_strdup(st->str);
g_string_free(st, TRUE);
}
- }
- else if (!strncmp(ptr, "BIRTHDAY ", 9)) {
+ } else if (!strncmp(ptr, "BIRTHDAY ", 9)) {
sd->info_birthday = g_strdup(ptr + 9);
GString *st = g_string_new("Contact Information\n");
@@ -565,10 +579,30 @@ static void skype_parse_user(struct im_connection *ic, char *line)
}
}
-static void skype_parse_chatmessage(struct im_connection *ic, char *line)
+static void skype_parse_chatmessage_said_emoted(struct im_connection *ic, struct groupchat *gc, char *body)
{
struct skype_data *sd = ic->proto_data;
char buf[IRC_LINE_SIZE];
+ if (!strcmp(sd->type, "SAID")) {
+ if (!sd->is_edit)
+ g_snprintf(buf, IRC_LINE_SIZE, "%s", body);
+ else {
+ g_snprintf(buf, IRC_LINE_SIZE, "%s %s", set_getstr(&ic->acc->set, "edit_prefix"), body);
+ sd->is_edit = 0;
+ }
+ } else
+ g_snprintf(buf, IRC_LINE_SIZE, "/me %s", body);
+ if (!gc)
+ /* Private message */
+ imcb_buddy_msg(ic, sd->handle, buf, 0, 0);
+ else
+ /* Groupchat message */
+ imcb_chat_msg(gc, sd->handle, buf, 0, 0);
+}
+
+static void skype_parse_chatmessage(struct im_connection *ic, char *line)
+{
+ struct skype_data *sd = ic->proto_data;
char *id = strchr(line, ' ');
if (!++id)
@@ -626,27 +660,7 @@ static void skype_parse_chatmessage(struct im_connection *ic, char *line)
char *body = g_list_nth_data(sd->body, i);
if (!strcmp(sd->type, "SAID") ||
!strcmp(sd->type, "EMOTED")) {
- if (!strcmp(sd->type, "SAID")) {
- if (!sd->is_edit)
- g_snprintf(buf, IRC_LINE_SIZE, "%s",
- body);
- else {
- g_snprintf(buf, IRC_LINE_SIZE, "%s %s",
- set_getstr(&ic->acc->set, "edit_prefix"),
- body);
- sd->is_edit = 0;
- }
- } else
- g_snprintf(buf, IRC_LINE_SIZE, "/me %s",
- body);
- if (!gc)
- /* Private message */
- imcb_buddy_msg(ic,
- sd->handle, buf, 0, 0);
- else
- /* Groupchat message */
- imcb_chat_msg(gc,
- sd->handle, buf, 0, 0);
+ skype_parse_chatmessage_said_emoted(ic, gc, body);
} else if (!strcmp(sd->type, "SETTOPIC") && gc)
imcb_chat_topic(gc,
sd->handle, body, 0);
@@ -715,8 +729,7 @@ static void skype_parse_call(struct im_connection *ic, char *line)
switch (sd->call_status) {
case SKYPE_CALL_RINGING:
if (sd->call_out)
- imcb_log(ic, "You are currently ringing "
- "the user %s.", info);
+ imcb_log(ic, "You are currently ringing the user %s.", info);
else {
g_snprintf(buf, IRC_LINE_SIZE,
"The user %s is currently ringing you.",
@@ -785,6 +798,15 @@ static void skype_parse_filetransfer(struct im_connection *ic, char *line)
skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n",
id);
sd->filetransfer_status = SKYPE_FILETRANSFER_FAILED;
+ } else if (!strcmp(info, "STATUS COMPLETED")) {
+ skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n", id);
+ sd->filetransfer_status = SKYPE_FILETRANSFER_COMPLETED;
+ } else if (!strcmp(info, "STATUS TRANSFERRING")) {
+ skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n", id);
+ sd->filetransfer_status = SKYPE_FILETRANSFER_TRANSFERRING;
+ } else if (!strncmp(info, "FILEPATH ", 9)) {
+ info += 9;
+ sd->filetransfer_path = g_strdup(info);
} else if (!strncmp(info, "PARTNER_HANDLE ", 15)) {
info += 15;
if (!sd->filetransfer_status)
@@ -798,6 +820,16 @@ static void skype_parse_filetransfer(struct im_connection *ic, char *line)
imcb_log(ic, "Failed to transfer file from user %s.",
info);
break;
+ case SKYPE_FILETRANSFER_COMPLETED:
+ imcb_log(ic, "File transfer from user %s completed.", info);
+ break;
+ case SKYPE_FILETRANSFER_TRANSFERRING:
+ if (sd->filetransfer_path) {
+ imcb_log(ic, "File transfer from user %s started, saving to %s.", info, sd->filetransfer_path);
+ g_free(sd->filetransfer_path);
+ sd->filetransfer_path = NULL;
+ }
+ break;
}
sd->filetransfer_status = 0;
}
@@ -897,7 +929,7 @@ static void skype_parse_group(struct im_connection *ic, char *line)
if (!sd->pending_user) {
/* Number of users changed in this group, query its type to see
* if it's a custom one we should care about. */
- skype_printf(ic, "GET GROUP %s TYPE", id);
+ skype_printf(ic, "GET GROUP %s TYPE\n", id);
return;
}
@@ -906,7 +938,7 @@ static void skype_parse_group(struct im_connection *ic, char *line)
struct skype_group *sg = skype_group_by_id(ic, atoi(id));
if (sg) {
- skype_printf(ic, "ALTER GROUP %d ADDUSER %s", sg->id, sd->pending_user);
+ skype_printf(ic, "ALTER GROUP %d ADDUSER %s\n", sg->id, sd->pending_user);
g_free(sd->pending_user);
sd->pending_user = NULL;
} else
@@ -914,7 +946,7 @@ static void skype_parse_group(struct im_connection *ic, char *line)
"No skype group with id %s. That's probably a bug.", id);
} else if (!strcmp(info, "TYPE CUSTOM_GROUP"))
/* This one is interesting, query its users. */
- skype_printf(ic, "GET GROUP %s USERS", id);
+ skype_printf(ic, "GET GROUP %s USERS\n", id);
}
static void skype_parse_chat(struct im_connection *ic, char *line)
@@ -982,8 +1014,8 @@ static void skype_parse_chat(struct im_connection *ic, char *line)
g_free(sd->adder);
sd->adder = NULL;
}
- } else if (!strncmp(info, "ACTIVEMEMBERS ", 14)) {
- info += 14;
+ } else if (!strncmp(info, "MEMBERS ", 8) || !strncmp(info, "ACTIVEMEMBERS ", 14) ) {
+ info += 8;
gc = bee_chat_by_title(ic->bee, ic, id);
/* Hack! We set ->data to TRUE
* while we're on the channel
@@ -1045,6 +1077,9 @@ static void skype_parse_chats(struct im_connection *ic, char *line)
static void skype_parse_groups(struct im_connection *ic, char *line)
{
+ if (!set_getbool(&ic->acc->set, "read_groups"))
+ return;
+
char **i;
char **groups = g_strsplit(line + 7, ", ", 0);
@@ -1123,6 +1158,13 @@ static gboolean skype_read_callback(gpointer data, gint fd,
return FALSE;
/* Read the whole data. */
st = ssl_read(sd->ssl, buf, sizeof(buf));
+ if (st >= IRC_LINE_SIZE-1) {
+ /* As we don't buffer incoming data, if IRC_LINE_SIZE amount of bytes
+ * were received, there's a good chance last message was truncated
+ * and the next recv() will yield garbage. */
+ imcb_error(ic, "Unable to handle incoming data from skyped");
+ st = 0;
+ }
if (st > 0) {
buf[st] = '\0';
/* Then split it up to lines. */
@@ -1177,8 +1219,12 @@ gboolean skype_start_stream(struct im_connection *ic)
skype_printf(ic, "SET USERSTATUS ONLINE\n");
/* Auto join to bookmarked chats if requested.*/
- if (set_getbool(&ic->acc->set, "auto_join"))
+ if (set_getbool(&ic->acc->set, "auto_join")) {
skype_printf(ic, "SEARCH BOOKMARKEDCHATS\n");
+ skype_printf(ic, "SEARCH ACTIVECHATS\n");
+ skype_printf(ic, "SEARCH MISSEDCHATS\n");
+ skype_printf(ic, "SEARCH RECENTCHATS\n");
+ }
return st;
}
@@ -1227,7 +1273,7 @@ static void skype_logout(struct im_connection *ic)
skype_printf(ic, "SET USERSTATUS OFFLINE\n");
- while( ic->groupchats )
+ while (ic->groupchats)
imcb_chat_free(ic->groupchats->data);
for (i = 0; i < g_list_length(sd->groups); i++) {
@@ -1314,7 +1360,16 @@ static char *skype_set_display_name(set_t *set, char *value)
account_t *acc = set->data;
struct im_connection *ic = acc->ic;
- skype_printf(ic, "SET PROFILE FULLNAME %s", value);
+ skype_printf(ic, "SET PROFILE FULLNAME %s\n", value);
+ return value;
+}
+
+static char *skype_set_mood_text(set_t *set, char *value)
+{
+ account_t *acc = set->data;
+ struct im_connection *ic = acc->ic;
+
+ skype_printf(ic, "SET PROFILE MOOD_TEXT %s\n", value);
return value;
}
@@ -1323,7 +1378,7 @@ static char *skype_set_balance(set_t *set, char *value)
account_t *acc = set->data;
struct im_connection *ic = acc->ic;
- skype_printf(ic, "GET PROFILE PSTN_BALANCE");
+ skype_printf(ic, "GET PROFILE PSTN_BALANCE\n");
return value;
}
@@ -1334,7 +1389,7 @@ static void skype_call(struct im_connection *ic, char *value)
if (ptr)
*ptr = '\0';
- skype_printf(ic, "CALL %s", nick);
+ skype_printf(ic, "CALL %s\n", nick);
g_free(nick);
}
@@ -1343,7 +1398,7 @@ static void skype_hangup(struct im_connection *ic)
struct skype_data *sd = ic->proto_data;
if (sd->call_id) {
- skype_printf(ic, "SET CALL %s STATUS FINISHED",
+ skype_printf(ic, "SET CALL %s STATUS FINISHED\n",
sd->call_id);
g_free(sd->call_id);
sd->call_id = 0;
@@ -1383,10 +1438,10 @@ static void skype_add_buddy(struct im_connection *ic, char *who, char *group)
if (!sg) {
/* No such group, we need to create it, then have to
* add the user once it's created. */
- skype_printf(ic, "CREATE GROUP %s", group);
+ skype_printf(ic, "CREATE GROUP %s\n", group);
sd->pending_user = g_strdup(nick);
} else {
- skype_printf(ic, "ALTER GROUP %d ADDUSER %s", sg->id, nick);
+ skype_printf(ic, "ALTER GROUP %d ADDUSER %s\n", sg->id, nick);
}
}
}
@@ -1463,11 +1518,13 @@ struct groupchat *skype_chat_with(struct im_connection *ic, char *who)
static void skype_get_info(struct im_connection *ic, char *who)
{
+ struct skype_data *sd = ic->proto_data;
char *ptr, *nick;
nick = g_strdup(who);
ptr = strchr(nick, '@');
if (ptr)
*ptr = '\0';
+ sd->is_info = TRUE;
skype_printf(ic, "GET USER %s FULLNAME\n", nick);
skype_printf(ic, "GET USER %s PHONE_HOME\n", nick);
skype_printf(ic, "GET USER %s PHONE_OFFICE\n", nick);
@@ -1490,11 +1547,6 @@ static void skype_get_info(struct im_connection *ic, char *who)
skype_printf(ic, "GET USER %s BIRTHDAY\n", nick);
}
-static void skype_set_my_name(struct im_connection *ic, char *info)
-{
- skype_set_display_name(set_find(&ic->acc->set, "display_name"), info);
-}
-
static void skype_init(account_t *acc)
{
set_t *s;
@@ -1510,6 +1562,9 @@ static void skype_init(account_t *acc)
acc);
s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY;
+ s = set_add(&acc->set, "mood_text", NULL, skype_set_mood_text, acc);
+ s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY;
+
s = set_add(&acc->set, "call", NULL, skype_set_call, acc);
s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY;
@@ -1535,6 +1590,8 @@ static void skype_init(account_t *acc)
s = set_add(&acc->set, "edit_prefix", "EDIT:",
NULL, acc);
+
+ s = set_add(&acc->set, "read_groups", "false", set_eval_bool, acc);
}
#if BITLBEE_VERSION_CODE > BITLBEE_VER(3, 0, 1)
@@ -1546,12 +1603,14 @@ GList *skype_buddy_action_list(bee_user_t *bu)
bu = bu;
if (ret == NULL) {
- static const struct buddy_action ba[3] = {
+ static const struct buddy_action ba[2] = {
{"CALL", "Initiate a call" },
{"HANGUP", "Hang up a call" },
};
+ int i;
- ret = g_list_prepend(ret, (void *) ba + 0);
+ for (i = 0; i < ARRAY_SIZE(ba); i++)
+ ret = g_list_prepend(ret, (void *)(ba + i));
}
return ret;
@@ -1582,7 +1641,6 @@ void init_plugin(void)
ret->logout = skype_logout;
ret->buddy_msg = skype_buddy_msg;
ret->get_info = skype_get_info;
- ret->set_my_name = skype_set_my_name;
ret->away_states = skype_away_states;
ret->set_away = skype_set_away;
ret->add_buddy = skype_add_buddy;
diff --git a/protocols/skype/skyped.py b/protocols/skype/skyped.py
index 07c08435..86b1e96a 100644
--- a/protocols/skype/skyped.py
+++ b/protocols/skype/skyped.py
@@ -1,32 +1,30 @@
#!/usr/bin/env python2.7
-#
+#
# skyped.py
-#
-# Copyright (c) 2007, 2008, 2009, 2010, 2011 by Miklos Vajna <vmiklos@frugalware.org>
+#
+# Copyright (c) 2007-2013 by Miklos Vajna <vmiklos@vmiklos.hu>
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
# USA.
#
import sys
import os
import signal
-import locale
import time
import socket
-import getopt
import Skype4Py
import hashlib
from ConfigParser import ConfigParser, NoOptionError
@@ -53,11 +51,12 @@ def eh(type, value, tb):
gobject.MainLoop().quit()
if options.conn:
options.conn.close()
- # shut down client if it's running
- try:
- skype.skype.Client.Shutdown()
- except NameError:
- pass
+ if not options.dont_start_skype:
+ # shut down client if it's running
+ try:
+ skype.skype.Client.Shutdown()
+ except NameError:
+ pass
sys.exit("Exiting.")
sys.excepthook = eh
@@ -119,39 +118,35 @@ def skype_idle_handler(skype):
try:
c = skype.skype.Command("PING", Block=True)
skype.skype.SendCommand(c)
- except Skype4Py.SkypeAPIError, s:
+ except (Skype4Py.SkypeAPIError, AttributeError), s:
dprint("Warning, pinging Skype failed (%s)." % (s))
+ time.sleep(1)
return True
-def send(sock, txt):
+def send(sock, txt, tries=10):
global options
- from time import sleep
- count = 1
- done = False
if hasgobject:
- while (not done) and (count < 10):
- try:
- sock.send(txt)
- done = True
- except Exception, s:
- count += 1
- dprint("Warning, sending '%s' failed (%s). count=%d" % (txt, s, count))
- sleep(1)
- if not done:
+ if not options.conn: return
+ try:
+ done = sock.sendall(txt)
+ except socket.error as s:
+ dprint("Warning, sending '%s' failed (%s)." % (txt, s))
options.conn.close()
+ options.conn = False
else:
- while (not done) and (count < 10) and options.conn:
+ for attempt in xrange(1, tries+1):
+ if not options.conn: break
if wait_for_lock(options.lock, 3, 10, "socket send"):
try:
- if options.conn: sock.send(txt)
+ if options.conn: done = sock.sendall(txt)
options.lock.release()
- done = True
- except Exception, s:
+ except socket.error as s:
options.lock.release()
- count += 1
dprint("Warning, sending '%s' failed (%s). count=%d" % (txt, s, count))
- sleep(1)
- if not done:
+ time.sleep(1)
+ else:
+ break
+ else:
if options.conn:
options.conn.close()
options.conn = False
@@ -206,9 +201,13 @@ def listener(sock, skype):
certfile=options.config.sslcert,
keyfile=options.config.sslkey,
ssl_version=ssl.PROTOCOL_TLSv1)
- except ssl.SSLError:
- dprint("Warning, SSL init failed, did you create your certificate?")
- return False
+ except (ssl.SSLError, socket.error) as err:
+ if isinstance(err, ssl.SSLError):
+ dprint("Warning, SSL init failed, did you create your certificate?")
+ return False
+ else:
+ dprint('Warning, SSL init failed')
+ return True
if hasattr(options.conn, 'handshake'):
try:
options.conn.handshake()
@@ -254,11 +253,13 @@ def dprint(msg):
from time import strftime
global options
- now = strftime("%Y-%m-%d %H:%M:%S")
-
if options.debug:
+ import inspect
+ prefix = strftime("[%Y-%m-%d %H:%M:%S]") + " %s:%d" % inspect.stack()[1][1:3]
+ sanitized = msg
+
try:
- print now + ": " + msg
+ print prefix + ": " + msg
except Exception, s:
try:
sanitized = msg.encode("ascii", "backslashreplace")
@@ -267,18 +268,57 @@ def dprint(msg):
sanitized = "hex [" + msg.encode("hex") + "]"
except Error, s:
sanitized = "[unable to print debug message]"
- print now + "~=" + sanitized
+ print prefix + "~=" + sanitized
+
+ if options.log:
+ sock = open(options.log, "a")
+ sock.write(prefix + ": " + sanitized)
+ sock.close()
+
sys.stdout.flush()
- if options.log:
- sock = open(options.log, "a")
- sock.write("%s: %s\n" % (now, msg))
- sock.close()
+
+class MockedSkype:
+ """Mock class for Skype4Py.Skype(), in case the -m option is used."""
+ def __init__(self, mock):
+ sock = open(mock)
+ self.lines = sock.readlines()
+
+ def SendCommand(self, c):
+ pass
+
+ def Command(self, msg, Block):
+ if msg == "PING":
+ return ["PONG"]
+ line = self.lines[0].strip()
+ if not line.startswith(">> "):
+ raise Exception("Corrupted mock input")
+ line = line[3:]
+ if line != msg:
+ raise Exception("'%s' != '%s'" % (line, msg))
+ self.lines = self.lines[1:] # drop the expected incoming line
+ ret = []
+ while True:
+ # and now send back all the following lines, up to the next expected incoming line
+ if len(self.lines) == 0:
+ break
+ if self.lines[0].startswith(">> "):
+ break
+ if not self.lines[0].startswith("<< "):
+ raise Exception("Corrupted mock input")
+ ret.append(self.lines[0][3:].strip())
+ self.lines = self.lines[1:]
+ return ret
class SkypeApi:
- def __init__(self):
- self.skype = Skype4Py.Skype()
- self.skype.OnNotify = self.recv
- self.skype.Client.Start()
+ def __init__(self, mock):
+ global options
+ if not mock:
+ self.skype = Skype4Py.Skype()
+ self.skype.OnNotify = self.recv
+ if not options.dont_start_skype:
+ self.skype.Client.Start()
+ else:
+ self.skype = MockedSkype(mock)
def recv(self, msg_text):
global options
@@ -333,48 +373,16 @@ class SkypeApi:
try:
c = self.skype.Command(e, Block=True)
self.skype.SendCommand(c)
- self.recv(c.Reply)
+ if hasattr(c, "Reply"):
+ self.recv(c.Reply) # Skype4Py answer
+ else:
+ for i in c: # mock may return multiple iterable answers
+ self.recv(i)
except Skype4Py.SkypeError:
pass
except Skype4Py.SkypeAPIError, s:
dprint("Warning, sending '%s' failed (%s)." % (e, s))
-class Options:
- def __init__(self):
- self.cfgpath = os.path.join(os.environ['HOME'], ".skyped", "skyped.conf")
- # fall back to system-wide settings
- self.syscfgpath = "/usr/local/etc/skyped/skyped.conf"
- if os.path.exists(self.syscfgpath) and not os.path.exists(self.cfgpath):
- self.cfgpath = self.syscfgpath
- self.daemon = True
- self.debug = False
- self.help = False
- self.host = "0.0.0.0"
- self.log = None
- self.port = None
- self.version = False
- # well, this is a bit hackish. we store the socket of the last connected client
- # here and notify it. maybe later notify all connected clients?
- self.conn = None
- # this will be read first by the input handler
- self.buf = None
-
-
- def usage(self, ret):
- print """Usage: skyped [OPTION]...
-
-skyped is a daemon that acts as a tcp server on top of a Skype instance.
-
-Options:
- -c --config path to configuration file (default: %s)
- -d --debug enable debug messages
- -h --help this help
- -H --host set the tcp host, supports IPv4 and IPv6 (default: %s)
- -l --log set the log file in background mode (default: none)
- -n --nofork don't run as daemon in the background
- -p --port set the tcp port (default: %s)
- -v --version display version information""" % (self.cfgpath, self.host, self.port)
- sys.exit(ret)
def serverloop(options, skype):
timeout = 1; # in seconds
@@ -417,58 +425,72 @@ def serverloop(options, skype):
else:
options.last_bitlbee_pong = now
-if __name__=='__main__':
- options = Options()
- try:
- opts, args = getopt.getopt(sys.argv[1:], "c:dhH:l:np:v", ["config=", "debug", "help", "host=", "log=", "nofork", "port=", "version"])
- except getopt.GetoptError:
- options.usage(1)
- for opt, arg in opts:
- if opt in ("-c", "--config"):
- options.cfgpath = arg
- elif opt in ("-d", "--debug"):
- options.debug = True
- elif opt in ("-h", "--help"):
- options.help = True
- elif opt in ("-H", "--host"):
- options.host = arg
- elif opt in ("-l", "--log"):
- options.log = arg
- elif opt in ("-n", "--nofork"):
- options.daemon = False
- elif opt in ("-p", "--port"):
- options.port = int(arg)
- elif opt in ("-v", "--version"):
- options.version = True
- if options.help:
- options.usage(0)
- elif options.version:
+
+def main(args=None):
+ global options
+ global skype
+
+ cfgpath = os.path.join(os.environ['HOME'], ".skyped", "skyped.conf")
+ syscfgpath = "/usr/local/etc/skyped/skyped.conf"
+ if not os.path.exists(cfgpath) and os.path.exists(syscfgpath):
+ cfgpath = syscfgpath # fall back to system-wide settings
+ port = 2727
+
+ import argparse
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-c', '--config',
+ metavar='path', default=cfgpath,
+ help='path to configuration file (default: %(default)s)')
+ parser.add_argument('-H', '--host', default='0.0.0.0',
+ help='set the tcp host, supports IPv4 and IPv6 (default: %(default)s)')
+ parser.add_argument('-p', '--port', type=int,
+ help='set the tcp port (default: %(default)s)')
+ parser.add_argument('-l', '--log', metavar='path',
+ help='set the log file in background mode (default: none)')
+ parser.add_argument('-v', '--version', action='store_true', help='display version information')
+ parser.add_argument('-n', '--nofork',
+ action='store_true', help="don't run as daemon in the background")
+ parser.add_argument('-s', '--dont-start-skype', action='store_true',
+ help="assume that skype is running independently, don't try to start/stop it")
+ parser.add_argument('-m', '--mock', help='fake interactions with skype (only useful for tests)')
+ parser.add_argument('-d', '--debug', action='store_true', help='enable debug messages')
+ options = parser.parse_args(sys.argv[1:] if args is None else args)
+
+ if options.version:
print "skyped %s" % __version__
sys.exit(0)
- # parse our config
- if not os.path.exists(options.cfgpath):
- print "Can't find configuration file at '%s'." % options.cfgpath
- print "Use the -c option to specify an alternate one."
- sys.exit(1)
+
+ # well, this is a bit hackish. we store the socket of the last connected client
+ # here and notify it. maybe later notify all connected clients?
+ options.conn = None
+ # this will be read first by the input handler
+ options.buf = None
+
+ if not os.path.exists(options.config):
+ parser.error(( "Can't find configuration file at '%s'. "
+ "Use the -c option to specify an alternate one." )% options.config)
+
+ cfgpath = options.config
options.config = ConfigParser()
- options.config.read(options.cfgpath)
- options.config.username = options.config.get('skyped', 'username').split('#')[0]
- options.config.password = options.config.get('skyped', 'password').split('#')[0]
- options.config.sslkey = os.path.expanduser(options.config.get('skyped', 'key').split('#')[0])
- options.config.sslcert = os.path.expanduser(options.config.get('skyped', 'cert').split('#')[0])
+ options.config.read(cfgpath)
+ options.config.username = options.config.get('skyped', 'username').split('#', 1)[0]
+ options.config.password = options.config.get('skyped', 'password').split('#', 1)[0]
+ options.config.sslkey = os.path.expanduser(options.config.get('skyped', 'key').split('#', 1)[0])
+ options.config.sslcert = os.path.expanduser(options.config.get('skyped', 'cert').split('#', 1)[0])
+
# hack: we have to parse the parameters first to locate the
# config file but the -p option should overwrite the value from
# the config file
try:
- options.config.port = int(options.config.get('skyped', 'port').split('#')[0])
+ options.config.port = int(options.config.get('skyped', 'port').split('#', 1)[0])
if not options.port:
options.port = options.config.port
except NoOptionError:
pass
if not options.port:
- options.port = 2727
- dprint("Parsing config file '%s' done, username is '%s'." % (options.cfgpath, options.config.username))
- if options.daemon:
+ options.port = port
+ dprint("Parsing config file '%s' done, username is '%s'." % (cfgpath, options.config.username))
+ if not options.nofork:
pid = os.fork()
if pid == 0:
nullin = file(os.devnull, 'r')
@@ -484,7 +506,7 @@ if __name__=='__main__':
if hasgobject:
server(options.host, options.port)
try:
- skype = SkypeApi()
+ skype = SkypeApi(options.mock)
except Skype4Py.SkypeAPIError, s:
sys.exit("%s. Are you sure you have started Skype?" % s)
if hasgobject:
@@ -496,3 +518,6 @@ if __name__=='__main__':
options.conn = False
options.lock = threading.Lock()
server(options.host, options.port, skype)
+
+
+if __name__ == '__main__': main()
diff --git a/protocols/skype/skyped.txt b/protocols/skype/skyped.txt
index 53f2626d..c5f9abb9 100644
--- a/protocols/skype/skyped.txt
+++ b/protocols/skype/skyped.txt
@@ -11,7 +11,7 @@ skyped [<options>]
== DESCRIPTION
Skype supports remote control of the GUI client only via X11 or DBus
-messages. This is hard in care you want remote control. This daemon
+messages. This is hard in case you want remote control. This daemon
listens on a TCP port and runs on the same machine where the GUI client
runs. It passes all the input it gets to Skype directly, except for a
few commands which is related to authentication. The whole communication
@@ -19,7 +19,37 @@ is done via SSL.
== CONFIGURATION
-See the README for information about how to configure this daemon.
+- Set up `~/.skyped/skyped.conf`: Create the `~/.skyped` directory, copy
+ `skyped.conf` and `skyped.cnf` from `/usr/local/etc/skyped/` to `~/.skyped`,
+ adjust `username` and `password`. The `username` should be your Skype login and
+ the `password` can be whatever you want, but you will have to specify that one
+ when adding the Skype account to BitlBee (see later).
+
+NOTE: Here, and later - `/usr/local/etc` can be different on your installation
+if you used the `--sysconfdir` switch when running the `configure` of BitlBee.
+
+- Generate the SSL pem files:
+
+----
+$ cd ~/.skyped
+$ openssl req -new -x509 -days 365 -nodes -config skyped.cnf -out skyped.cert.pem \
+ -keyout skyped.key.pem
+----
+
+- Start `skyped` (the TCP server), initially without detaching and enabling debug messages:
+
+----
+$ skyped -d -n
+----
+
+- Start your `IRC` client, connect to BitlBee and add your account:
+
+----
+account add skype <user> <pass>
+----
+
+`<user>` should be your Skype account name, `<pass>` should be the one you declared
+in `skyped.conf`.
== OPTIONS
@@ -38,9 +68,15 @@ See the README for information about how to configure this daemon.
-l, --log::
Set the log file in background mode (default: none)
+-m, --mock=<file>::
+ Mock mode: replay session from file, instead of connecting to Skype.
+
-n, --nofork::
Don't run as daemon in the background
+-s, --dont-start-skype::
+ Assume that skype is running independently, don't try to start/stop it.
+
-p, --port::
Set the tcp port (default: 2727)
@@ -49,4 +85,4 @@ See the README for information about how to configure this daemon.
== AUTHOR
-Written by Miklos Vajna <vmiklos@frugalware.org>
+Written by Miklos Vajna <vmiklos@vmiklos.hu>
diff --git a/protocols/skype/t/Makefile b/protocols/skype/t/Makefile
deleted file mode 100644
index 9c5e95f9..00000000
--- a/protocols/skype/t/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-PORT=9876
-BITLBEE=/usr/sbin/bitlbee
-
-export TEST_SKYPE_ID=user
-export TEST_SKYPE_PASSWORD=pass
-
-testfiles := $(wildcard irssi/*.test)
-tests := $(patsubst %.test,%,$(testfiles))
-
-.PHONY: $(tests)
-
-all: $(tests)
- @echo "passed $$(echo $(testfiles)|wc -w) tests."
-
-$(tests): % : %.test
- @echo "--- Running test $@ ---"; \
- if [ -r "$(BITLBEE)" -a -x "$(BITLBEE)" ]; then \
- bitlbee_binary="$(BITLBEE)"; \
- else \
- bitlbee_basename=`basename $(BITLBEE)`; \
- bitlbee_binary=`which $$bitlbee_basename`; \
- fi; \
- if ! ./livetest-bitlbee.sh "$$bitlbee_binary" $(PORT) irssi/livetest-irssi.sh $< >$@.log; then \
- echo Test failed, log: ;\
- cat $@.log;\
- exit 1;\
- fi;\
- echo "--- OK ---" ;\
- sleep 1
-clean:
- rm -r irssi/*.log bitlbeetest.pid dotirssi livetest
-
-
diff --git a/protocols/skype/t/add-yes-bitlbee.mock b/protocols/skype/t/add-yes-bitlbee.mock
new file mode 100644
index 00000000..5f17fd33
--- /dev/null
+++ b/protocols/skype/t/add-yes-bitlbee.mock
@@ -0,0 +1,8 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+<< PRIVMSG &bitlbee :add skype bob
+>> :bob!bob@skype.com JOIN :&bitlbee
diff --git a/protocols/skype/t/add-yes-skyped.mock b/protocols/skype/t/add-yes-skyped.mock
new file mode 100644
index 00000000..dea175a3
--- /dev/null
+++ b/protocols/skype/t/add-yes-skyped.mock
@@ -0,0 +1,23 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> SET USER bob BUDDYSTATUS 2 Please authorize me
+<< USER bob BUDDYSTATUS 2
+<< USER bob ISAUTHORIZED TRUE
+<< USER bob ISBLOCKED FALSE
+<< USER bob BUDDYSTATUS 2
+<< USER bob ONLINESTATUS OFFLINE
+<< USER bob FULLNAME skype test203
+<< USER bob BUDDYSTATUS 3
+<< USER bob ONLINESTATUS OFFLINE
+<< USER bob ONLINESTATUS ONLINE
+<< USER bob TIMEZONE 90000
diff --git a/protocols/skype/t/added-no-bitlbee.mock b/protocols/skype/t/added-no-bitlbee.mock
new file mode 100644
index 00000000..d7a70c66
--- /dev/null
+++ b/protocols/skype/t/added-no-bitlbee.mock
@@ -0,0 +1,9 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> PRIVMSG &bitlbee :skype - New request: The user bob wants to add you
+<< PRIVMSG &bitlbee :no
+>> PRIVMSG &bitlbee :skype - Rejected
diff --git a/protocols/skype/t/added-no-skyped.mock b/protocols/skype/t/added-no-skyped.mock
new file mode 100644
index 00000000..0e4bfc8a
--- /dev/null
+++ b/protocols/skype/t/added-no-skyped.mock
@@ -0,0 +1,15 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+<< USER bob RECEIVEDAUTHREQUEST Please allow me to see when you are online
+>> SET USER bob ISAUTHORIZED FALSE
+<< USER bob ISAUTHORIZED FALSE
diff --git a/protocols/skype/t/added-yes-bitlbee.mock b/protocols/skype/t/added-yes-bitlbee.mock
new file mode 100644
index 00000000..df068f89
--- /dev/null
+++ b/protocols/skype/t/added-yes-bitlbee.mock
@@ -0,0 +1,9 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> PRIVMSG &bitlbee :skype - New request: The user bob wants to add you
+<< PRIVMSG &bitlbee :yes
+>> :bob!bob@skype.com JOIN :&bitlbee
diff --git a/protocols/skype/t/added-yes-skyped.mock b/protocols/skype/t/added-yes-skyped.mock
new file mode 100644
index 00000000..fc3d756f
--- /dev/null
+++ b/protocols/skype/t/added-yes-skyped.mock
@@ -0,0 +1,25 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+<< USER bob RECEIVEDAUTHREQUEST Please allow me to see when you are online
+>> SET USER bob ISAUTHORIZED TRUE
+<< USER bob ISAUTHORIZED TRUE
+<< USER bob RECEIVEDAUTHREQUEST
+<< USER bob ISAUTHORIZED TRUE
+<< USER bob ISBLOCKED FALSE
+<< USER bob BUDDYSTATUS 3
+<< USER bob ONLINESTATUS OFFLINE
+<< USER bob ONLINESTATUS ONLINE
+<< USER bob TIMEZONE 90000
+<< USER bob FULLNAME Miklos V
+<< USER bob LANGUAGE hu Hungarian
+<< USER bob COUNTRY hu Hungary
diff --git a/protocols/skype/t/bitlbee.conf b/protocols/skype/t/bitlbee.conf
deleted file mode 100644
index e69de29b..00000000
--- a/protocols/skype/t/bitlbee.conf
+++ /dev/null
diff --git a/protocols/skype/t/call-bitlbee.mock b/protocols/skype/t/call-bitlbee.mock
new file mode 100644
index 00000000..e480e7f3
--- /dev/null
+++ b/protocols/skype/t/call-bitlbee.mock
@@ -0,0 +1,11 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> :bob!bob@skype.com JOIN :&bitlbee
+<< PRIVMSG bob :CALL
+>> PRIVMSG &bitlbee :skype - You are currently ringing the user bob.
+<< PRIVMSG bob :HANGUP
+>> PRIVMSG &bitlbee :skype - You cancelled the call to the user bob.
diff --git a/protocols/skype/t/call-failed-bitlbee.mock b/protocols/skype/t/call-failed-bitlbee.mock
new file mode 100644
index 00000000..aae1d99a
--- /dev/null
+++ b/protocols/skype/t/call-failed-bitlbee.mock
@@ -0,0 +1,9 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> PRIVMSG &bitlbee :skype - Logging in: Logged in
+<< PRIVMSG bob :CALL
+>> PRIVMSG &bitlbee :skype - Error: Call failed: User is offline
diff --git a/protocols/skype/t/call-failed-skyped.mock b/protocols/skype/t/call-failed-skyped.mock
new file mode 100644
index 00000000..30699f91
--- /dev/null
+++ b/protocols/skype/t/call-failed-skyped.mock
@@ -0,0 +1,21 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS OFFLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+>> CALL bob
+<< CALL 216 STATUS UNPLACED
+<< CALL 216 STATUS ROUTING
+<< CALL 216 FAILUREREASON 3
+<< CALL 216 STATUS FAILED
diff --git a/protocols/skype/t/call-skyped.mock b/protocols/skype/t/call-skyped.mock
new file mode 100644
index 00000000..92947ba9
--- /dev/null
+++ b/protocols/skype/t/call-skyped.mock
@@ -0,0 +1,26 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS OFFLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS ONLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+>> CALL bob
+<< CALL 178 STATUS UNPLACED
+<< CALL 178 STATUS ROUTING
+<< CALL 178 STATUS RINGING
+>> GET CALL 178 PARTNER_HANDLE
+<< CALL 178 PARTNER_HANDLE bob
+>> SET CALL 178 STATUS FINISHED
+<< CALL 178 STATUS CANCELLED
+>> GET CALL 178 PARTNER_HANDLE
+<< CALL 178 PARTNER_HANDLE bob
diff --git a/protocols/skype/t/called-no-bitlbee.mock b/protocols/skype/t/called-no-bitlbee.mock
new file mode 100644
index 00000000..c69a0c8b
--- /dev/null
+++ b/protocols/skype/t/called-no-bitlbee.mock
@@ -0,0 +1,10 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> PRIVMSG &bitlbee :skype - New request: The user bob is currently ringing you.
+<< PRIVMSG &bitlbee :no
+>> PRIVMSG &bitlbee :skype - Rejected: The user bob is currently ringing you.
+>> PRIVMSG &bitlbee :skype - You refused the call from user bob.
diff --git a/protocols/skype/t/called-no-skyped.mock b/protocols/skype/t/called-no-skyped.mock
new file mode 100644
index 00000000..5152fe9e
--- /dev/null
+++ b/protocols/skype/t/called-no-skyped.mock
@@ -0,0 +1,24 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS ONLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+<< CALL 212 CONF_ID 0
+<< CALL 212 STATUS RINGING
+>> GET CALL 212 PARTNER_HANDLE
+<< CALL 212 PARTNER_HANDLE bob
+>> SET CALL 212 STATUS FINISHED
+<< CALL 212 STATUS REFUSED
+>> GET CALL 212 PARTNER_HANDLE
+<< CALL 212 PARTNER_HANDLE bob
diff --git a/protocols/skype/t/called-yes-bitlbee.mock b/protocols/skype/t/called-yes-bitlbee.mock
new file mode 100644
index 00000000..47c54799
--- /dev/null
+++ b/protocols/skype/t/called-yes-bitlbee.mock
@@ -0,0 +1,9 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> PRIVMSG &bitlbee :skype - New request: The user bob is currently ringing you.
+<< PRIVMSG &bitlbee :yes
+>> PRIVMSG &bitlbee :skype - Accepted: The user bob is currently ringing you.
diff --git a/protocols/skype/t/called-yes-skyped.mock b/protocols/skype/t/called-yes-skyped.mock
new file mode 100644
index 00000000..67cdffe3
--- /dev/null
+++ b/protocols/skype/t/called-yes-skyped.mock
@@ -0,0 +1,22 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS ONLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+<< CALL 208 CONF_ID 0
+<< CALL 208 STATUS RINGING
+>> GET CALL 208 PARTNER_HANDLE
+<< CALL 208 PARTNER_HANDLE bob
+>> SET CALL 208 STATUS INPROGRESS
+<< CALL 208 STATUS INPROGRESS
diff --git a/protocols/skype/t/ctcp-help-bitlbee.mock b/protocols/skype/t/ctcp-help-bitlbee.mock
new file mode 100644
index 00000000..98522ec1
--- /dev/null
+++ b/protocols/skype/t/ctcp-help-bitlbee.mock
@@ -0,0 +1,9 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> :bob!bob@skype.com JOIN :&bitlbee
+<< PRIVMSG bob :HELP
+>> :bob!bob@skype.com NOTICE alice :HELP Supported CTCPs: HANGUP (Hang up a call), CALL (Initiate a call)
diff --git a/protocols/skype/t/ctcp-help-skyped.mock b/protocols/skype/t/ctcp-help-skyped.mock
new file mode 100644
index 00000000..eacff2e6
--- /dev/null
+++ b/protocols/skype/t/ctcp-help-skyped.mock
@@ -0,0 +1,16 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS ONLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
diff --git a/protocols/skype/t/filetransfer-bitlbee.mock b/protocols/skype/t/filetransfer-bitlbee.mock
new file mode 100644
index 00000000..a08e52bc
--- /dev/null
+++ b/protocols/skype/t/filetransfer-bitlbee.mock
@@ -0,0 +1,10 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> :bob!bob@skype.com JOIN :&bitlbee
+>> PRIVMSG &bitlbee :skype - The user bob offered a new file for you.
+>> PRIVMSG &bitlbee :skype - File transfer from user bob started, saving to /home/alice/text.odt.
+>> PRIVMSG &bitlbee :skype - File transfer from user bob completed.
diff --git a/protocols/skype/t/filetransfer-skyped.mock b/protocols/skype/t/filetransfer-skyped.mock
new file mode 100644
index 00000000..b24fcc94
--- /dev/null
+++ b/protocols/skype/t/filetransfer-skyped.mock
@@ -0,0 +1,37 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS ONLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+<< FILETRANSFER 208 TYPE INCOMING
+<< FILETRANSFER 208 PARTNER_HANDLE bob
+<< FILETRANSFER 208 PARTNER_DISPNAME bob
+<< FILETRANSFER 208 FILENAME text.odt
+<< FILETRANSFER 208 STATUS NEW
+<< FILETRANSFER 208 FILESIZE 83534193
+<< FILETRANSFER 208 STARTTIME 1358458276
+<< FILETRANSFER 208 FINISHTIME 0
+<< FILETRANSFER 208 BYTESPERSECOND 0
+<< FILETRANSFER 208 BYTESTRANSFERRED 0
+<< FILETRANSFER 208 FILESIZE 83534193
+>> GET FILETRANSFER 208 PARTNER_HANDLE
+<< FILETRANSFER 208 PARTNER_HANDLE bob
+<< FILETRANSFER 208 FILEPATH /home/alice/text.odt
+<< FILETRANSFER 208 STATUS CONNECTING
+<< FILETRANSFER 208 STATUS TRANSFERRING
+>> GET FILETRANSFER 208 PARTNER_HANDLE
+<< FILETRANSFER 208 PARTNER_HANDLE bob
+<< FILETRANSFER 208 STATUS COMPLETED
+>> GET FILETRANSFER 208 PARTNER_HANDLE
+<< FILETRANSFER 208 PARTNER_HANDLE bob
diff --git a/protocols/skype/t/group-read-bitlbee.mock b/protocols/skype/t/group-read-bitlbee.mock
new file mode 100644
index 00000000..0f001400
--- /dev/null
+++ b/protocols/skype/t/group-read-bitlbee.mock
@@ -0,0 +1,14 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype set read_groups true
+<< PRIVMSG &bitlbee :account skype on
+>> :bob!bob@skype.com JOIN :&bitlbee
+>> :cecil!cecil@skype.com JOIN :&bitlbee
+>> :daniel!daniel@skype.com JOIN :&bitlbee
+<< JOIN &family
+>> 353 alice = &family :@alice +bob +cecil @root
+<< JOIN &work
+>> 353 alice = &work :@alice +daniel @root
diff --git a/protocols/skype/t/group-read-skyped.mock b/protocols/skype/t/group-read-skyped.mock
new file mode 100644
index 00000000..148661a1
--- /dev/null
+++ b/protocols/skype/t/group-read-skyped.mock
@@ -0,0 +1,36 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 70, 71
+>> SEARCH FRIENDS
+<< USERS echo123, bob, cecil, daniel, emily
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET GROUP 70 DISPLAYNAME
+<< GROUP 70 DISPLAYNAME Family
+>> GET GROUP 70 USERS
+<< GROUP 70 USERS bob, cecil
+>> GET GROUP 71 DISPLAYNAME
+<< GROUP 71 DISPLAYNAME Work
+>> GET GROUP 71 USERS
+<< GROUP 71 USERS daniel, emily
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS ONLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+>> GET USER cecil ONLINESTATUS
+<< USER cecil ONLINESTATUS ONLINE
+>> GET USER cecil FULLNAME
+<< USER cecil FULLNAME Cecil
+>> GET USER daniel ONLINESTATUS
+<< USER daniel ONLINESTATUS ONLINE
+>> GET USER daniel FULLNAME
+<< USER daniel FULLNAME Daniel
+>> GET USER emily ONLINESTATUS
+<< USER emily ONLINESTATUS OFFLINE
+>> GET USER emily FULLNAME
+<< USER emily FULLNAME Emily
diff --git a/protocols/skype/t/groupchat-invite-bitlbee.mock b/protocols/skype/t/groupchat-invite-bitlbee.mock
new file mode 100644
index 00000000..7b44427f
--- /dev/null
+++ b/protocols/skype/t/groupchat-invite-bitlbee.mock
@@ -0,0 +1,11 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> :bob!bob@skype.com JOIN :&bitlbee
+<< PRIVMSG &bitlbee :chat with bob
+>> 353 alice = ##alice/$bob;a7ab206ec780 :@alice bob @root
+<< INVITE cecil ##alice/$bob;a7ab206ec780
+>> cecil@skype.com JOIN :##alice/$bob;a7ab206ec780
diff --git a/protocols/skype/t/groupchat-invite-skyped.mock b/protocols/skype/t/groupchat-invite-skyped.mock
new file mode 100644
index 00000000..214ebec0
--- /dev/null
+++ b/protocols/skype/t/groupchat-invite-skyped.mock
@@ -0,0 +1,48 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob, cecil
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS ONLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+>> GET USER cecil ONLINESTATUS
+<< USER cecil ONLINESTATUS ONLINE
+>> GET USER cecil FULLNAME
+<< USER cecil FULLNAME Cecil
+>> CHAT CREATE bob
+<< CHAT #alice/$bob;a7ab206ec78060f1 STATUS DIALOG
+>> GET CHAT #alice/$bob;a7ab206ec78060f1 ADDER
+<< CHAT #alice/$bob;a7ab206ec78060f1 ADDER
+<< CHAT #alice/$bob;a7ab206ec78060f1 NAME #alice/$bob;a7ab206ec78060f1
+>> GET CHAT #alice/$bob;a7ab206ec78060f1 TOPIC
+<< CHAT #alice/$bob;a7ab206ec78060f1 TOPIC
+<< CHATMESSAGE 206 STATUS SENDING
+<< CHAT #alice/$bob;a7ab206ec78060f1 STATUS DIALOG
+<< CHATMEMBER 204 ROLE USER
+<< CHAT #alice/$bob;a7ab206ec78060f1 MYROLE USER
+<< CHAT #alice/$bob;a7ab206ec78060f1 MEMBERS bob alice
+<< CHAT #alice/$bob;a7ab206ec78060f1 ACTIVEMEMBERS alice
+<< CHAT #alice/$bob;a7ab206ec78060f1 STATUS DIALOG
+<< CHAT #alice/$bob;a7ab206ec78060f1 TIMESTAMP 1358344213
+<< CHAT #alice/$bob;a7ab206ec78060f1 DIALOG_PARTNER bob
+<< CHAT #alice/$bob;a7ab206ec78060f1 MEMBERS bob alice
+<< CHAT #alice/$bob;a7ab206ec78060f1 FRIENDLYNAME bob
+>> ALTER CHAT #alice/$bob;a7ab206ec78060f1 ADDMEMBERS cecil
+<< ALTER CHAT ADDMEMBERS
+<< CHAT #alice/$bob;a7ab206ec78060f1 STATUS MULTI_SUBSCRIBED
+<< CHAT #alice/$bob;a7ab206ec78060f1 MEMBERS bob cecil alice
+>> GET CHAT #alice/$bob;a7ab206ec78060f1 ADDER
+<< CHAT #alice/$bob;a7ab206ec78060f1 ADDER
+<< CHAT #alice/$bob;a7ab206ec78060f1 FRIENDLYNAME bob, cecil
+>> GET CHAT #alice/$bob;a7ab206ec78060f1 TOPIC
+<< CHAT #alice/$bob;a7ab206ec78060f1 TOPIC
+<< CHATMESSAGE 210 STATUS SENDING
diff --git a/protocols/skype/t/groupchat-invited-bitlbee.mock b/protocols/skype/t/groupchat-invited-bitlbee.mock
new file mode 100644
index 00000000..f63b7d5c
--- /dev/null
+++ b/protocols/skype/t/groupchat-invited-bitlbee.mock
@@ -0,0 +1,8 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> JOIN :##cecil/$bob;4d8cc9965791
+>> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root
diff --git a/protocols/skype/t/groupchat-invited-skyped.mock b/protocols/skype/t/groupchat-invited-skyped.mock
new file mode 100644
index 00000000..a5c754ce
--- /dev/null
+++ b/protocols/skype/t/groupchat-invited-skyped.mock
@@ -0,0 +1,58 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob, cecil
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS OFFLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+>> GET USER cecil ONLINESTATUS
+<< USER cecil ONLINESTATUS OFFLINE
+>> GET USER cecil FULLNAME
+<< USER cecil FULLNAME Cecil
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 NAME #cecil/$bob;4d8cc9965791c6b9
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED
+<< CHATMEMBER 186 ROLE USER
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 MYROLE USER
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 MEMBERS bob cecil alice
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 FRIENDLYNAME bob, cecil
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob alice
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 TIMESTAMP 1358276196
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED
+<< CHATMESSAGE 188 STATUS RECEIVED
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+>> GET CHATMESSAGE 188 FROM_HANDLE
+<< CHATMESSAGE 188 FROM_HANDLE bob
+>> GET CHATMESSAGE 188 BODY
+<< CHATMESSAGE 188 BODY
+>> GET CHATMESSAGE 188 TYPE
+<< CHATMESSAGE 188 TYPE ADDEDMEMBERS
+>> GET CHATMESSAGE 188 CHATNAME
+<< CHATMESSAGE 188 CHATNAME #cecil/$bob;4d8cc9965791c6b9
+<< CHATMESSAGE 189 STATUS READ
+<< CHATMESSAGE 189 STATUS READ
+<< CHATMEMBER 186 IS_ACTIVE TRUE
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob cecil alice
+<< CHATMESSAGE 190 STATUS SENT
diff --git a/protocols/skype/t/groupchat-leave-bitlbee.mock b/protocols/skype/t/groupchat-leave-bitlbee.mock
new file mode 100644
index 00000000..36447cee
--- /dev/null
+++ b/protocols/skype/t/groupchat-leave-bitlbee.mock
@@ -0,0 +1,11 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype set skypeconsole_receive true
+<< PRIVMSG &bitlbee :account skype on
+>> JOIN :##cecil/$bob;4d8cc9965791
+>> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root
+<< PART ##cecil/$bob;4d8cc9965791
+>> PRIVMSG &bitlbee :alice: CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS UNSUBSCRIBED
diff --git a/protocols/skype/t/groupchat-leave-skyped.mock b/protocols/skype/t/groupchat-leave-skyped.mock
new file mode 100644
index 00000000..86150d1c
--- /dev/null
+++ b/protocols/skype/t/groupchat-leave-skyped.mock
@@ -0,0 +1,63 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob, cecil
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS OFFLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+>> GET USER cecil ONLINESTATUS
+<< USER cecil ONLINESTATUS OFFLINE
+>> GET USER cecil FULLNAME
+<< USER cecil FULLNAME Cecil
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 NAME #cecil/$bob;4d8cc9965791c6b9
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED
+<< CHATMEMBER 186 ROLE USER
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 MYROLE USER
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 MEMBERS bob cecil alice
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 FRIENDLYNAME bob, cecil
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob alice
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 TIMESTAMP 1358276196
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS MULTI_SUBSCRIBED
+<< CHATMESSAGE 188 STATUS RECEIVED
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
+>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
+>> GET CHATMESSAGE 188 FROM_HANDLE
+<< CHATMESSAGE 188 FROM_HANDLE bob
+>> GET CHATMESSAGE 188 BODY
+<< CHATMESSAGE 188 BODY
+>> GET CHATMESSAGE 188 TYPE
+<< CHATMESSAGE 188 TYPE ADDEDMEMBERS
+>> GET CHATMESSAGE 188 CHATNAME
+<< CHATMESSAGE 188 CHATNAME #cecil/$bob;4d8cc9965791c6b9
+<< CHATMESSAGE 189 STATUS READ
+<< CHATMESSAGE 189 STATUS READ
+<< CHATMEMBER 186 IS_ACTIVE TRUE
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob cecil alice
+<< CHATMESSAGE 190 STATUS SENT
+>> ALTER CHAT #cecil/$bob;4d8cc9965791c6b9 LEAVE
+<< ALTER CHAT LEAVE
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 MEMBERS bob cecil
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob cecil
+<< CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS UNSUBSCRIBED
diff --git a/protocols/skype/t/info-bitlbee.mock b/protocols/skype/t/info-bitlbee.mock
new file mode 100644
index 00000000..a8896f6d
--- /dev/null
+++ b/protocols/skype/t/info-bitlbee.mock
@@ -0,0 +1,9 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> :bob!bob@skype.com JOIN :&bitlbee
+<< PRIVMSG &bitlbee :info bob
+>> PRIVMSG &bitlbee :Full Name: Bob
diff --git a/protocols/skype/t/info-skyped.mock b/protocols/skype/t/info-skyped.mock
new file mode 100644
index 00000000..63076b09
--- /dev/null
+++ b/protocols/skype/t/info-skyped.mock
@@ -0,0 +1,46 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS ONLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+>> GET USER bob PHONE_HOME
+<< USER bob PHONE_HOME
+>> GET USER bob PHONE_OFFICE
+<< USER bob PHONE_OFFICE
+>> GET USER bob PHONE_MOBILE
+<< USER bob PHONE_MOBILE
+>> GET USER bob NROF_AUTHED_BUDDIES
+<< USER bob NROF_AUTHED_BUDDIES 145
+>> GET USER bob TIMEZONE
+<< USER bob TIMEZONE 90000
+>> GET USER bob LASTONLINETIMESTAMP
+<< USER bob LASTONLINETIMESTAMP 1358023469
+>> GET USER bob SEX
+<< USER bob SEX MALE
+>> GET USER bob LANGUAGE
+<< USER bob LANGUAGE hu Hungarian
+>> GET USER bob COUNTRY
+<< USER bob COUNTRY hu Hungary
+>> GET USER bob PROVINCE
+<< USER bob PROVINCE
+>> GET USER bob CITY
+<< USER bob CITY Budapest
+>> GET USER bob HOMEPAGE
+<< USER bob HOMEPAGE
+>> GET USER bob ABOUT
+<< USER bob ABOUT
+>> GET USER bob BIRTHDAY
+<< USER bob BIRTHDAY 19781108
diff --git a/protocols/skype/t/irssi/livetest-irssi.sh b/protocols/skype/t/irssi/livetest-irssi.sh
deleted file mode 100755
index a8e136cf..00000000
--- a/protocols/skype/t/irssi/livetest-irssi.sh
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/bin/env bash
-ISCRIPT=$1
-OPT=$2
-
-[ -n "$ISCRIPT" ] || { echo Syntax: `basename "$0"` irssi-test-script; exit 1; }
-
-# Load variables from test
-eval `sed -e '1,/^###/!d;/^###/d' "$ISCRIPT"`
-
-#if [ "$OPT" == "checkvars" ]; then echo $TESTNEEDEDVARS; fi
-RET=0
-
-# Check if we have the neccessary environment variables for this test
-for var in $TESTNEEDEDVARS; do
- if [ -z `eval echo \$\{$var\}` ]; then
- if [ "$OPT" != "checkvars" ]; then
- echo Need environment variable "$var" for this test.
- exit 66
- else
- echo $var
- RET=66
- fi
- fi
-done
-
-# if we got this far we're OK
-if [ "$OPT" == "checkvars" ]; then exit $RET; fi
-
-[ -n "$PORT" ] || { echo 'Need the bitlbee listening port as environment variable PORT'; exit 1; }
-
-# Setup the irssi dir
-(
- rm -r dotirssi
- mkdir -p dotirssi/scripts dotirssi/logs
- cp "`dirname $0`"/trigger.pl dotirssi/scripts &&
- echo 'script load trigger.pl' >dotirssi/startup
-) &>/dev/null || { echo Failed to setup irssi testdir; exit 1; }
-
-# write irssi config
-
-echo '
-
-aliases = {
- runtest = "'`sed -e "1,/^###/d;s/@LOGIN@/$TESTLOGIN/;s/@PASSWORD@/$TESTPASSWORD/" "$ISCRIPT" | tr '\n' ';'`'";
- expectbee = "/trigger add -publics -channels &bitlbee -regexp";
- expectjoin = "/trigger add -joins -masks *!$0@* $1-";
- expectmsg = "/trigger add -privmsgs -masks *!$0@* $1-";
-};
-
-servers = ( { address = "localhost"; chatnet = "local"; port = "'$PORT'"; autoconnect="yes";});
-
-settings = {
- settings_autosave = "no";
- core = { real_name = "bitlbee-test"; user_name = "bitlbee-test"; nick = "bitlbeetest"; };
- "fe-text" = { actlist_sort = "refnum"; };
-};
-
-chatnets = { local = { type = "IRC"; autosendcmd = "/runtest"; }; };
-
-logs = {
-"dotirssi/logs/status.log" = { auto_open = "yes"; level = "ALL"; items = ( { type = "window"; name = "1"; } ); };
-"dotirssi/logs/control.log" = { auto_open = "yes"; level = "ALL"; items = ( { type = "target"; name = "&bitlbee"; } ); };
-' >dotirssi/config
-
-for nick in $TESTLOGNICKS; do
- echo '
- "dotirssi/logs/'$nick'.log" = { auto_open = "yes"; level = "ALL"; items = ( { type = "target"; name = "'$nick'"; } ); };
- ' >>dotirssi/config
-done
-
-echo '};' >>dotirssi/config
-
-# Go!
-
-echo Running irssi...
-screen -D -m irssi --config=dotirssi/config --home=dotirssi/ &
-
-# output logs
-
-submitlogs() {
- perl -p -i -e "s/$TESTLOGIN/---TESTLOGIN---/;s/$TESTPASSWORD/---TESTPASSWORD---/" dotirssi/logs/*.log
-
- if [ "$OPT" == "tgz" ]; then
- tar czf "`dirname $0`"/"`basename "$ISCRIPT"`".logs.tgz dotirssi/logs/*.log
- elif [ "$OPT" == "ctest" ]; then
- echo CTEST_FULL_OUTPUT
- for log in dotirssi/logs/*.log; do
- echo -n '<DartMeasurement name="'$log'" type="text/string"><![CDATA['
- cat "$log"
- echo "]]></DartMeasurement>"
- done
- else
- echo Test logs: dotirssi/logs/*.log
- fi
-}
-
-# timeout stuff
-
-t=$TESTDURATION
-intval=1
-while (( t >= intval )); do
- sleep $intval
- kill -0 $! &>/dev/null || { echo screen/irssi terminated.; submitlogs; bash -c "cd dotirssi/logs && $TESTCHECKRESULT" >/dev/null; exit $?; }
- t=$(( t - $intval ))
-done
-echo Killing screen/irssi...
-kill $!
-submitlogs
-exit 22
diff --git a/protocols/skype/t/irssi/skype-call.test b/protocols/skype/t/irssi/skype-call.test
deleted file mode 100644
index 8f502a59..00000000
--- a/protocols/skype/t/irssi/skype-call.test
+++ /dev/null
@@ -1,13 +0,0 @@
-TESTNEEDEDVARS="TEST_SKYPE_ID TEST_SKYPE_PASSWORD"
-TESTDURATION=60
-TESTCHECKRESULT="grep '\[Test Passed\]' status.log"
-TESTLOGIN="$TEST_SKYPE_ID"
-TESTPASSWORD="$TEST_SKYPE_PASSWORD"
-### Test receiving call output
-/expectbee 'Welcome to the BitlBee' -command 'msg $$C register testing'
-/expectbee 'Account successfully created' -command 'msg $$C account add skype @LOGIN@ @PASSWORD@'
-/expectbee 'Account successfully added' -command 'msg $$C account 0 set test_join true'
-/expectbee 'test_join' -command 'msg $$C account 0 on'
-/expectjoin echo123 -command 'ctcp echo123 call'
-/expectbee 'You are currently ringing the user' -command 'ctcp echo123 hangup'
-/expectbee '(You cancelled the call|You finished the call)' -command 'quit Test Passed'
diff --git a/protocols/skype/t/irssi/skype-info.test b/protocols/skype/t/irssi/skype-info.test
deleted file mode 100644
index e8507321..00000000
--- a/protocols/skype/t/irssi/skype-info.test
+++ /dev/null
@@ -1,12 +0,0 @@
-TESTNEEDEDVARS="TEST_SKYPE_ID TEST_SKYPE_PASSWORD"
-TESTDURATION=60
-TESTCHECKRESULT="grep '\[Test Passed\]' status.log"
-TESTLOGIN="$TEST_SKYPE_ID"
-TESTPASSWORD="$TEST_SKYPE_PASSWORD"
-### Test receiving info output
-/expectbee 'Welcome to the BitlBee' -command 'msg $$C register testing'
-/expectbee 'Account successfully created' -command 'msg $$C account add skype @LOGIN@ @PASSWORD@'
-/expectbee 'Account successfully added' -command 'msg $$C account 0 set test_join true'
-/expectbee 'test_join' -command 'msg $$C account 0 on'
-/expectjoin echo123 -command 'msg $$C info echo123'
-/expectbee 'Full Name: Echo / Sound Test Service' -command 'quit Test Passed'
diff --git a/protocols/skype/t/irssi/skype-login.test b/protocols/skype/t/irssi/skype-login.test
deleted file mode 100644
index ca627002..00000000
--- a/protocols/skype/t/irssi/skype-login.test
+++ /dev/null
@@ -1,10 +0,0 @@
-TESTNEEDEDVARS="TEST_SKYPE_ID TEST_SKYPE_PASSWORD"
-TESTDURATION=10
-TESTCHECKRESULT="grep '\[Test Passed\]' status.log"
-TESTLOGIN="$TEST_SKYPE_ID"
-TESTPASSWORD="$TEST_SKYPE_PASSWORD"
-### Test login
-/expectbee 'Welcome to the BitlBee' -command 'msg $$C register testing'
-/expectbee 'Account successfully created' -command 'msg $$C account add skype @LOGIN@ @PASSWORD@'
-/expectbee 'Account successfully added' -command 'msg $$C account 0 on'
-/expectbee 'Logged in' -command 'quit Test Passed'
diff --git a/protocols/skype/t/irssi/skype-msg.test b/protocols/skype/t/irssi/skype-msg.test
deleted file mode 100644
index d35615cd..00000000
--- a/protocols/skype/t/irssi/skype-msg.test
+++ /dev/null
@@ -1,17 +0,0 @@
-TESTNEEDEDVARS="TEST_SKYPE_ID TEST_SKYPE_PASSWORD"
-TESTDURATION=60
-TESTCHECKRESULT="grep '\[Test Passed\]' status.log"
-TESTLOGIN="$TEST_SKYPE_ID"
-TESTPASSWORD="$TEST_SKYPE_PASSWORD"
-### Test sending and receiving messages
-/expectbee 'Welcome to the BitlBee' -command 'msg $$C register testing'
-/expectbee 'Account successfully created' -command 'msg $$C account add skype @LOGIN@ @PASSWORD@'
-/expectbee 'Account successfully added' -command 'msg $$C account 0 set test_join true'
-/expectbee 'test_join' -command 'msg $$C account 0 on'
-# use builtin test service
-/expectjoin echo123 -command 'msg $$C echo123: ping, say pong'
-/expectbee 'pong' -command 'quit Test Passed'
-# use a public bot as well, just in case the above one would fail
-/expectjoin echo123 -command 'msg $$C add skype pam_bot'
-/expectjoin pam_bot -command 'msg $$C pam_bot: pambot help'
-/expectbee 'PamBot, thanks for chatting with me' -command 'quit Test Passed'
diff --git a/protocols/skype/t/irssi/trigger.pl b/protocols/skype/t/irssi/trigger.pl
deleted file mode 100644
index 02f8951f..00000000
--- a/protocols/skype/t/irssi/trigger.pl
+++ /dev/null
@@ -1,1225 +0,0 @@
-# trigger.pl - execute a command or replace text, triggered by an event in irssi
-# Do /TRIGGER HELP or look at http://wouter.coekaerts.be/irssi/ for help
-
-# Copyright (C) 2002-2006 Wouter Coekaerts <wouter@coekaerts.be>
-#
-# 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
-
-use strict;
-use Irssi 20020324 qw(command_bind command_runsub command signal_add_first signal_continue signal_stop signal_remove);
-use Text::ParseWords;
-use IO::File;
-use vars qw($VERSION %IRSSI);
-
-$VERSION = '1.0';
-%IRSSI = (
- authors => 'Wouter Coekaerts',
- contact => 'wouter@coekaerts.be',
- name => 'trigger',
- description => 'execute a command or replace text, triggered by an event in irssi',
- license => 'GPLv2 or later',
- url => 'http://wouter.coekaerts.be/irssi/',
- changed => '$LastChangedDate: 2006-01-23 13:10:19 +0100 (Mon, 23 Jan 2006) $',
-);
-
-sub cmd_help {
- Irssi::print (<<'SCRIPTHELP_EOF', MSGLEVEL_CLIENTCRAP);
-
-TRIGGER LIST
-TRIGGER SAVE
-TRIGGER RELOAD
-TRIGGER MOVE <number> <number>
-TRIGGER DELETE <number>
-TRIGGER CHANGE <number> ...
-TRIGGER ADD ...
-
-When to match:
-On which types of event to trigger:
- These are simply specified by -name_of_the_type
- The normal IRC event types are:
- publics, %|privmsgs, pubactions, privactions, pubnotices, privnotices, joins, parts, quits, kicks, topics, invites, nick_changes, dcc_msgs, dcc_actions, dcc_ctcps
- mode_channel: %|a mode on the (whole) channel (like +t, +i, +b)
- mode_nick: %|a mode on someone in the channel (like +o, +v)
- -all is an alias for all of those.
- Additionally, there is:
- rawin: %|raw text incoming from the server
- send_command: %|commands you give to irssi
- send_text: %|lines you type that aren't commands
- beep: %|when irssi beeps
- notify_join: %|someone in you notify list comes online
- notify_part: %|someone in your notify list goes offline
- notify_away: %|someone in your notify list goes away
- notify_unaway: %|someone in your notify list goes unaway
- notify_unidle: %|someone in your notify list stops idling
-
-Filters (conditions) the event has to satisfy. They all take one parameter.
-If you can give a list, seperate elements by space and use quotes around the list.
- -pattern: %|The message must match the given pattern. ? and * can be used as wildcards
- -regexp: %|The message must match the given regexp. (see man perlre)
- %|if -nocase is given as an option, the regexp or pattern is matched case insensitive
- -tags: %|The servertag must be in the given list of tags
- -channels: %|The event must be in one of the given list of channels.
- Examples: %|-channels '#chan1 #chan2' or -channels 'IRCNet/#channel'
- %|-channels 'EFNet/' means every channel on EFNet and is the same as -tags 'EFNet'
- -masks: %|The person who triggers it must match one of the given list of masks
- -hasmode: %|The person who triggers it must have the give mode
- Examples: %|'-o' means not opped, '+ov' means opped OR voiced, '-o&-v' means not opped AND not voiced
- -hasflag: %|Only trigger if if friends.pl (friends_shasta.pl) or people.pl is loaded and the person who triggers it has the given flag in the script (same syntax as -hasmode)
- -other_masks
- -other_hasmode
- -other_hasflag: %|Same as above but for the victim for kicks or mode_nick.
-
-What to do when it matches:
- -command: Execute the given Irssi-command
- %|You are able to use $1, $2 and so on generated by your regexp pattern.
- %|For multiple commands ; (or $;) can be used as seperator
- %|The following variables are also expanded:
- $T: %|Server tag
- $C: %|Channel name
- $N: %|Nickname of the person who triggered this command
- $A: %|His address (foo@bar.com),
- $I: %|His ident (foo)
- $H: %|His hostname (bar.com)
- $M: %|The complete message
- ${other}: %|The victim for kicks or mode_nick
- ${mode_type}: %|The type ('+' or '-') for a mode_channel or mode_nick
- ${mode_char}: %|The mode char ('o' for ops, 'b' for ban,...)
- ${mode_arg} : %|The argument to the mode (if there is one)
- %|$\X, with X being one of the above expands (e.g. $\M), escapes all non-alphanumeric characters, so it can be used with /eval or /exec. Don't use /eval or /exec without this, it's not safe.
-
- -replace: %|replaces the matching part with the given replacement in the event (requires a -regexp or -pattern)
- -once: %|remove the trigger if it is triggered, so it only executes once and then is forgotten.
- -stop: %|stops the signal. It won't get displayed by Irssi. Like /IGNORE
- -debug: %|print some debugging info
-
-Other options:
- -disabled: %|Same as removing it, but keeps it in case you might need it later
- -name: %|Give the trigger a name. You can refer to the trigger with this name in add/del/change commands
-
-Examples:
- Knockout people who do a !list:
- /TRIGGER ADD %|-publics -channels "#channel1 #channel2" -nocase -regexp ^!list -command "KN $N This is not a warez channel!"
- React to !echo commands from people who are +o in your friends-script:
- /TRIGGER ADD %|-publics -regexp '^!echo (.*)' -hasflag '+o' -command 'say echo: $1'
- Ignore all non-ops on #channel:
- /TRIGGER ADD %|-publics -actions -channels "#channel" -hasmode '-o' -stop
- Send a mail to yourself every time a topic is changed:
- /TRIGGER ADD %|-topics -command 'exec echo $\N changed topic of $\C to: $\M | mail you@somewhere.com -s topic'
-
-
-Examples with -replace:
- %|Replace every occurence of shit with sh*t, case insensitive:
- /TRIGGER ADD %|-all -nocase -regexp shit -replace sh*t
- %|Strip all colorcodes from *!lamer@*:
- /TRIGGER ADD %|-all -masks *!lamer@* -regexp '\x03\d?\d?(,\d\d?)?|\x02|\x1f|\x16|\x06' -replace ''
- %|Never let *!bot1@foo.bar or *!bot2@foo.bar hilight you
- %|(this works by cutting your nick in 2 different parts, 'myn' and 'ick' here)
- %|you don't need to understand the -replace argument, just trust that it works if the 2 parts separately don't hilight:
- /TRIGGER ADD %|-all masks '*!bot1@foo.bar *!bot2@foo.bar' -regexp '(myn)(ick)' -nocase -replace '$1\x02\x02$2'
- %|Avoid being hilighted by !top10 in eggdrops with stats.mod (but show your nick in bold):
- /TRIGGER ADD %|-publics -regexp '(Top.0\(.*\): 1.*)(my)(nick)' -replace '$1\x02$2\x02\x02$3\x02'
- %|Convert a Windows-1252 Euro to an ISO-8859-15 Euro (same effect as euro.pl):
- /TRIGGER ADD %|-regexp '\x80' -replace '\xA4'
- %|Show tabs as spaces, not the inverted I (same effect as tab_stop.pl):
- /TRIGGER ADD %|-all -regexp '\t' -replace ' '
-SCRIPTHELP_EOF
-} # /
-
-my @triggers; # array of all triggers
-my %triggers_by_type; # hash mapping types on triggers of that type
-my $recursion_depth = 0;
-my $changed_since_last_save = 0;
-
-###############
-### formats ###
-###############
-
-Irssi::theme_register([
- 'trigger_header' => 'Triggers:',
- 'trigger_line' => '%#$[-4]0 $1',
- 'trigger_added' => 'Trigger $0 added: $1',
- 'trigger_not_found' => 'Trigger {hilight $0} not found',
- 'trigger_saved' => 'Triggers saved to $0',
- 'trigger_loaded' => 'Triggers loaded from $0'
-]);
-
-#########################################
-### catch the signals & do your thing ###
-#########################################
-
-# trigger types with a message and a channel
-my @allchanmsg_types = qw(publics pubactions pubnotices pubctcps pubctcpreplies parts quits kicks topics);
-# trigger types with a message
-my @allmsg_types = (@allchanmsg_types, qw(privmsgs privactions privnotices privctcps privctcpreplies dcc_msgs dcc_actions dcc_ctcps));
-# trigger types with a channel
-my @allchan_types = (@allchanmsg_types, qw(mode_channel mode_nick joins invites));
-# trigger types in -all
-my @all_types = (@allmsg_types, qw(mode_channel mode_nick joins invites nick_changes));
-# trigger types with a server
-my @all_server_types = (@all_types, qw(rawin notify_join notify_part notify_away notify_unaway notify_unidle));
-# all trigger types
-my @trigger_types = (@all_server_types, qw(send_command send_text beep));
-#trigger types that are not in -all
-#my @notall_types = grep {my $a=$_; return (!grep {$_ eq $a} @all_types);} @trigger_types;
-my @notall_types = qw(rawin notify_join notify_part notify_away notify_unaway notify_unidle send_command send_text beep);
-
-my @signals = (
-# "message public", SERVER_REC, char *msg, char *nick, char *address, char *target
-{
- 'types' => ['publics'],
- 'signal' => 'message public',
- 'sub' => sub {check_signal_message(\@_,1,$_[0],$_[4],$_[2],$_[3],'publics');},
-},
-# "message private", SERVER_REC, char *msg, char *nick, char *address
-{
- 'types' => ['privmsgs'],
- 'signal' => 'message private',
- 'sub' => sub {check_signal_message(\@_,1,$_[0],undef,$_[2],$_[3],'privmsgs');},
-},
-# "message irc action", SERVER_REC, char *msg, char *nick, char *address, char *target
-{
- 'types' => ['privactions','pubactions'],
- 'signal' => 'message irc action',
- 'sub' => sub {
- if ($_[4] eq $_[0]->{nick}) {
- check_signal_message(\@_,1,$_[0],undef,$_[2],$_[3],'privactions');
- } else {
- check_signal_message(\@_,1,$_[0],$_[4],$_[2],$_[3],'pubactions');
- }
- },
-},
-# "message irc notice", SERVER_REC, char *msg, char *nick, char *address, char *target
-{
- 'types' => ['privnotices','pubnotices'],
- 'signal' => 'message irc notice',
- 'sub' => sub {
- if ($_[4] eq $_[0]->{nick}) {
- check_signal_message(\@_,1,$_[0],undef,$_[2],$_[3],'privnotices');
- } else {
- check_signal_message(\@_,1,$_[0],$_[4],$_[2],$_[3],'pubnotices');
- }
- }
-},
-# "message join", SERVER_REC, char *channel, char *nick, char *address
-{
- 'types' => ['joins'],
- 'signal' => 'message join',
- 'sub' => sub {check_signal_message(\@_,-1,$_[0],$_[1],$_[2],$_[3],'joins');}
-},
-# "message part", SERVER_REC, char *channel, char *nick, char *address, char *reason
-{
- 'types' => ['parts'],
- 'signal' => 'message part',
- 'sub' => sub {check_signal_message(\@_,4,$_[0],$_[1],$_[2],$_[3],'parts');}
-},
-# "message quit", SERVER_REC, char *nick, char *address, char *reason
-{
- 'types' => ['quits'],
- 'signal' => 'message quit',
- 'sub' => sub {check_signal_message(\@_,3,$_[0],undef,$_[1],$_[2],'quits');}
-},
-# "message kick", SERVER_REC, char *channel, char *nick, char *kicker, char *address, char *reason
-{
- 'types' => ['kicks'],
- 'signal' => 'message kick',
- 'sub' => sub {check_signal_message(\@_,5,$_[0],$_[1],$_[3],$_[4],'kicks',{'other'=>$_[2]});}
-},
-# "message topic", SERVER_REC, char *channel, char *topic, char *nick, char *address
-{
- 'types' => ['topics'],
- 'signal' => 'message topic',
- 'sub' => sub {check_signal_message(\@_,2,$_[0],$_[1],$_[3],$_[4],'topics');}
-},
-# "message invite", SERVER_REC, char *channel, char *nick, char *address
-{
- 'types' => ['invites'],
- 'signal' => 'message invite',
- 'sub' => sub {check_signal_message(\@_,-1,$_[0],$_[1],$_[2],$_[3],'invites');}
-},
-# "message nick", SERVER_REC, char *newnick, char *oldnick, char *address
-{
- 'types' => ['nick_changes'],
- 'signal' => 'message nick',
- 'sub' => sub {check_signal_message(\@_,-1,$_[0],undef,$_[1],$_[3],'nick_changes');}
-},
-# "message dcc", DCC_REC *dcc, char *msg
-{
- 'types' => ['dcc_msgs'],
- 'signal' => 'message dcc',
- 'sub' => sub {check_signal_message(\@_,1,$_[0]->{'server'},undef,$_[0]->{'nick'},undef,'dcc_msgs');
- }
-},
-# "message dcc action", DCC_REC *dcc, char *msg
-{
- 'types' => ['dcc_actions'],
- 'signal' => 'message dcc action',
- 'sub' => sub {check_signal_message(\@_,1,$_[0]->{'server'},undef,$_[0]->{'nick'},undef,'dcc_actions');}
-},
-# "message dcc ctcp", DCC_REC *dcc, char *cmd, char *data
-{
- 'types' => ['dcc_ctcps'],
- 'signal' => 'message dcc ctcp',
- 'sub' => sub {check_signal_message(\@_,1,$_[0]->{'server'},undef,$_[0]->{'nick'},undef,'dcc_ctcps');}
-},
-# "server incoming", SERVER_REC, char *data
-{
- 'types' => ['rawin'],
- 'signal' => 'server incoming',
- 'sub' => sub {check_signal_message(\@_,1,$_[0],undef,undef,undef,'rawin');}
-},
-# "send command", char *args, SERVER_REC, WI_ITEM_REC
-{
- 'types' => ['send_command'],
- 'signal' => 'send command',
- 'sub' => sub {
- sig_send_text_or_command(\@_,1);
- }
-},
-# "send text", char *line, SERVER_REC, WI_ITEM_REC
-{
- 'types' => ['send_text'],
- 'signal' => 'send text',
- 'sub' => sub {
- sig_send_text_or_command(\@_,0);
- }
-},
-# "beep"
-{
- 'types' => ['beep'],
- 'signal' => 'beep',
- 'sub' => sub {check_signal_message(\@_,-1,undef,undef,undef,undef,'beep');}
-},
-# "event "<cmd>, SERVER_REC, char *args, char *sender_nick, char *sender_address
-{
- 'types' => ['mode_channel', 'mode_nick'],
- 'signal' => 'event mode',
- 'sub' => sub {
- my ($server, $event_args, $nickname, $address) = @_;
- my ($target, $modes, $modeargs) = split(/ /, $event_args, 3);
- return if (!$server->ischannel($target));
- my (@modeargs) = split(/ /,$modeargs);
- my ($pos, $type, $event_type, $arg) = (0, '+');
- foreach my $char (split(//,$modes)) {
- if ($char eq "+" || $char eq "-") {
- $type = $char;
- } else {
- if ($char =~ /[Oovh]/) { # mode_nick
- $event_type = 'mode_nick';
- $arg = $modeargs[$pos++];
- } elsif ($char =~ /[beIqdk]/ || ( $char =~ /[lfJ]/ && $type eq '+')) { # chan_mode with arg
- $event_type = 'mode_channel';
- $arg = $modeargs[$pos++];
- } else { # chan_mode without arg
- $event_type = 'mode_channel';
- $arg = undef;
- }
- check_signal_message(\@_,-1,$server,$target,$nickname,$address,$event_type,{
- 'mode_type' => $type,
- 'mode_char' => $char,
- 'mode_arg' => $arg,
- 'other' => ($event_type eq 'mode_nick') ? $arg : undef
- });
- }
- }
- }
-},
-# "notifylist joined", SERVER_REC, char *nick, char *user, char *host, char *realname, char *awaymsg
-{
- 'types' => ['notify_join'],
- 'signal' => 'notifylist joined',
- 'sub' => sub {check_signal_message(\@_, 5, $_[0], undef, $_[1], $_[2].'@'.$_[3], 'notify_join', {'realname' => $_[4]});}
-},
-{
- 'types' => ['notify_part'],
- 'signal' => 'notifylist left',
- 'sub' => sub {check_signal_message(\@_, 5, $_[0], undef, $_[1], $_[2].'@'.$_[3], 'notify_left', {'realname' => $_[4]});}
-},
-{
- 'types' => ['notify_unidle'],
- 'signal' => 'notifylist unidle',
- 'sub' => sub {check_signal_message(\@_, 5, $_[0], undef, $_[1], $_[2].'@'.$_[3], 'notify_unidle', {'realname' => $_[4]});}
-},
-{
- 'types' => ['notify_away', 'notify_unaway'],
- 'signal' => 'notifylist away changed',
- 'sub' => sub {check_signal_message(\@_, 5, $_[0], undef, $_[1], $_[2].'@'.$_[3], ($_[5] ? 'notify_away' : 'notify_unaway'), {'realname' => $_[4]});}
-},
-# "ctcp msg", SERVER_REC, char *args, char *nick, char *addr, char *target
-{
- 'types' => ['pubctcps', 'privctcps'],
- 'signal' => 'ctcp msg',
- 'sub' => sub {
- my ($server, $args, $nick, $addr, $target) = @_;
- if ($target eq $server->{'nick'}) {
- check_signal_message(\@_, 1, $server, undef, $nick, $addr, 'privctcps');
- } else {
- check_signal_message(\@_, 1, $server, $target, $nick, $addr, 'pubctcps');
- }
- }
-},
-# "ctcp reply", SERVER_REC, char *args, char *nick, char *addr, char *target
-{
- 'types' => ['pubctcpreplies', 'privctcpreplies'],
- 'signal' => 'ctcp reply',
- 'sub' => sub {
- my ($server, $args, $nick, $addr, $target) = @_;
- if ($target eq $server->{'nick'}) {
- check_signal_message(\@_, 1, $server, undef, $nick, $addr, 'privctcps');
- } else {
- check_signal_message(\@_, 1, $server, $target, $nick, $addr, 'pubctcps');
- }
- }
-}
-);
-
-sub sig_send_text_or_command {
- my ($signal, $iscommand) = @_;
- my ($line, $server, $item) = @$signal;
- my ($channelname,$nickname,$address) = (undef,undef,undef);
- if ($item && (ref($item) eq 'Irssi::Irc::Channel' || ref($item) eq 'Irssi::Silc::Channel')) {
- $channelname = $item->{'name'};
- } elsif ($item && ref($item) eq 'Irssi::Irc::Query') { # TODO Silc query ?
- $nickname = $item->{'name'};
- $address = $item->{'address'}
- }
- # TODO pass context also for non-channels (queries and other stuff)
- check_signal_message($signal,0,$server,$channelname,$nickname,$address,$iscommand ? 'send_command' : 'send_text');
-
-}
-
-my %filters = (
-'tags' => {
- 'types' => \@all_server_types,
- 'sub' => sub {
- my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
-
- if (!defined($server)) {
- return 0;
- }
- my $matches = 0;
- foreach my $tag (split(/ /,$param)) {
- if (lc($server->{'tag'}) eq lc($tag)) {
- $matches = 1;
- last;
- }
- }
- return $matches;
- }
-},
-'channels' => {
- 'types' => \@allchan_types,
- 'sub' => sub {
- my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
-
- if (!defined($channelname) || !defined($server)) {
- return 0;
- }
- my $matches = 0;
- foreach my $trigger_channel (split(/ /,$param)) {
- if (lc($channelname) eq lc($trigger_channel)
- || lc($server->{'tag'}.'/'.$channelname) eq lc($trigger_channel)
- || lc($server->{'tag'}.'/') eq lc($trigger_channel)) {
- $matches = 1;
- last; # this channel matches, stop checking channels
- }
- }
- return $matches;
- }
-},
-'masks' => {
- 'types' => \@all_types,
- 'sub' => sub {
- my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
- return (defined($nickname) && defined($address) && defined($server) && $server->masks_match($param, $nickname, $address));
- }
-},
-'other_masks' => {
- 'types' => ['kicks', 'mode_nick'],
- 'sub' => sub {
- my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
- return 0 unless defined($extra->{'other'});
- my $other_address = get_address($extra->{'other'}, $server, $channelname);
- return defined($other_address) && $server->masks_match($param, $extra->{'other'}, $other_address);
- }
-},
-'hasmode' => {
- 'types' => \@all_types,
- 'sub' => sub {
- my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
- return hasmode($param, $nickname, $server, $channelname);
- }
-},
-'other_hasmode' => {
- 'types' => ['kicks', 'mode_nick'],
- 'sub' => sub {
- my ($param,$signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
- return defined($extra->{'other'}) && hasmode($param, $extra->{'other'}, $server, $channelname);
- }
-},
-'hasflag' => {
- 'types' => \@all_types,
- 'sub' => sub {
- my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
- return 0 unless defined($nickname) && defined($address) && defined($server);
- my $flags = get_flags ($server->{'chatnet'},$channelname,$nickname,$address);
- return defined($flags) && check_modes($flags,$param);
- }
-},
-'other_hasflag' => {
- 'types' => ['kicks', 'mode_nick'],
- 'sub' => sub {
- my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
- return 0 unless defined($extra->{'other'});
- my $other_address = get_address($extra->{'other'}, $server, $channelname);
- return 0 unless defined($other_address);
- my $flags = get_flags ($server->{'chatnet'},$channelname,$extra->{'other'},$other_address);
- return defined($flags) && check_modes($flags,$param);
- }
-},
-'mode_type' => {
- 'types' => ['mode_channel', 'mode_nick'],
- 'sub' => sub {
- my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
- return (($param) eq $extra->{'mode_type'});
- }
-},
-'mode_char' => {
- 'types' => ['mode_channel', 'mode_nick'],
- 'sub' => sub {
- my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
- return (($param) eq $extra->{'mode_char'});
- }
-},
-'mode_arg' => {
- 'types' => ['mode_channel', 'mode_nick'],
- 'sub' => sub {
- my ($param, $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra) = @_;
- return (($param) eq $extra->{'mode_arg'});
- }
-}
-);
-
-sub get_address {
- my ($nick, $server, $channel) = @_;
- my $nickrec = get_nickrec($nick, $server, $channel);
- return $nickrec ? $nickrec->{'host'} : undef;
-}
-sub get_nickrec {
- my ($nick, $server, $channel) = @_;
- return unless defined($server) && defined($channel) && defined($nick);
- my $chanrec = $server->channel_find($channel);
- return $chanrec ? $chanrec->nick_find($nick) : undef;
-}
-
-sub hasmode {
- my ($param, $nickname, $server, $channelname) = @_;
- my $nickrec = get_nickrec($nickname, $server, $channelname);
- return 0 unless defined $nickrec;
- my $modes =
- ($nickrec->{'op'} ? 'o' : '')
- . ($nickrec->{'voice'} ? 'v' : '')
- . ($nickrec->{'halfop'} ? 'h' : '')
- ;
- return check_modes($modes, $param);
-}
-
-# list of all switches
-my @trigger_switches = (@trigger_types, qw(all nocase stop once debug disabled));
-# parameters (with an argument)
-my @trigger_params = qw(pattern regexp command replace name);
-# list of all options (including switches) for /TRIGGER ADD
-my @trigger_add_options = (@trigger_switches, @trigger_params, keys(%filters));
-# same for /TRIGGER CHANGE, this includes the -no<option>'s
-my @trigger_options = map(($_,'no'.$_) ,@trigger_add_options);
-
-# check the triggers on $signal's $parammessage parameter, for triggers with $condition set
-# on $server in $channelname, for $nickname!$address
-# set $parammessage to -1 if the signal doesn't have a message
-# for signal without channel, nick or address, set to undef
-sub check_signal_message {
- my ($signal, $parammessage, $server, $channelname, $nickname, $address, $condition, $extra) = @_;
- my ($changed, $stopped, $context, $need_rebuild);
- my $message = ($parammessage == -1) ? '' : $signal->[$parammessage];
-
- return if (!$triggers_by_type{$condition});
-
- if ($recursion_depth > 10) {
- Irssi::print("Trigger error: Maximum recursion depth reached, aborting trigger.", MSGLEVEL_CLIENTERROR);
- return;
- }
- $recursion_depth++;
-
-TRIGGER:
- foreach my $trigger (@{$triggers_by_type{$condition}}) {
- # check filters
- foreach my $trigfilter (@{$trigger->{'filters'}}) {
- if (! ($trigfilter->[2]($trigfilter->[1], $signal,$parammessage,$server,$channelname,$nickname,$address,$condition,$extra))) {
-
- next TRIGGER;
- }
- }
-
- # check regexp (and keep matches in @- and @+, so don't make a this a {block})
- next if ($trigger->{'compregexp'} && ($parammessage == -1 || $message !~ m/$trigger->{'compregexp'}/));
-
- # if we got this far, it fully matched, and we need to do the replace/command/stop/once
- my $expands = $extra;
- $expands->{'M'} = $message,;
- $expands->{'T'} = (defined($server)) ? $server->{'tag'} : '';
- $expands->{'C'} = $channelname;
- $expands->{'N'} = $nickname;
- $expands->{'A'} = $address;
- $expands->{'I'} = ((!defined($address)) ? '' : substr($address,0,index($address,'@')));
- $expands->{'H'} = ((!defined($address)) ? '' : substr($address,index($address,'@')+1));
- $expands->{'$'} = '$';
- $expands->{';'} = ';';
-
- if (defined($trigger->{'replace'})) { # it's a -replace
- $message =~ s/$trigger->{'compregexp'}/do_expands($trigger->{'compreplace'},$expands,$message)/ge;
- $changed = 1;
- }
-
- if ($trigger->{'command'}) { # it's a (nonempty) -command
- my $command = $trigger->{'command'};
- # $1 = the stuff behind the $ we want to expand: a number, or a character from %expands
- $command = do_expands($command, $expands, $message);
-
- if (defined($server)) {
- if (defined($channelname) && $server->channel_find($channelname)) {
- $context = $server->channel_find($channelname);
- } else {
- $context = $server;
- }
- } else {
- $context = undef;
- }
-
- if (defined($context)) {
- $context->command("eval $command");
- } else {
- Irssi::command("eval $command");
- }
- }
-
- if ($trigger->{'debug'}) {
- print("DEBUG: trigger $condition pmesg=$parammessage message=$message server=$server->{tag} channel=$channelname nick=$nickname address=$address " . join(' ',map {$_ . '=' . $extra->{$_}} keys(%$extra)));
- }
-
- if ($trigger->{'stop'}) {
- $stopped = 1;
- }
-
- if ($trigger->{'once'}) {
- # find this trigger in the real trigger list, and remove it
- for (my $realindex=0; $realindex < scalar(@triggers); $realindex++) {
- if ($triggers[$realindex] == $trigger) {
- splice (@triggers,$realindex,1);
- last;
- }
- }
- $need_rebuild = 1;
- }
- }
-
- if ($need_rebuild) {
- rebuild();
- $changed_since_last_save = 1;
- }
- if ($stopped) { # stopped with -stop
- signal_stop();
- } elsif ($changed) { # changed with -replace
- $signal->[$parammessage] = $message;
- signal_continue(@$signal);
- }
- $recursion_depth--;
-}
-
-# used in check_signal_message to expand $'s
-# $inthis is a string that can contain $ stuff (like 'foo$1bar$N')
-sub do_expands {
- my ($inthis, $expands, $from) = @_;
- # @+ and @- are copied because there are two s/// nested, and the inner needs the $1 and $2,... of the outer one
- my @plus = @+;
- my @min = @-;
- my $p = \@plus; my $m = \@min;
- $inthis =~ s/\$(\\*(\d+|[^0-9x{]|x[0-9a-fA-F][0-9a-fA-F]|{.*?}))/expand_and_escape($1,$expands,$m,$p,$from)/ge;
- return $inthis;
-}
-
-# \ $ and ; need extra escaping because we use eval
-sub expand_and_escape {
- my $retval = expand(@_);
- $retval =~ s/([\\\$;])/\\\1/g;
- return $retval;
-}
-
-# used in do_expands (via expand_and_escape), to_expand is the part after the $
-sub expand {
- my ($to_expand, $expands, $min, $plus, $from) = @_;
- if ($to_expand =~ /^\d+$/) { # a number => look up in $vars
- # from man perlvar:
- # $3 is the same as "substr $var, $-[3], $+[3] - $-[3])"
- return ($to_expand > @{$min} ? '' : substr($from,$min->[$to_expand],$plus->[$to_expand]-$min->[$to_expand]));
- } elsif ($to_expand =~ s/^\\//) { # begins with \, so strip that from to_expand
- my $exp = expand($to_expand,$expands,$min,$plus,$from); # first expand without \
- $exp =~ s/([^a-zA-Z0-9])/\\\1/g; # escape non-word chars
- return $exp;
- } elsif ($to_expand =~ /^x([0-9a-fA-F]{2})/) { # $xAA
- return chr(hex($1));
- } elsif ($to_expand =~ /^{(.*?)}$/) { # ${foo}
- return expand($1, $expands, $min, $plus, $from);
- } else { # look up in $expands
- return $expands->{$to_expand};
- }
-}
-
-sub check_modes {
- my ($has_modes, $need_modes) = @_;
- my $matches;
- my $switch = 1; # if a '-' if found, will be 0 (meaning the modes should not be set)
- foreach my $need_mode (split /&/, $need_modes) {
- $matches = 0;
- foreach my $char (split //, $need_mode) {
- if ($char eq '-') {
- $switch = 0;
- } elsif ($char eq '+') {
- $switch = 1;
- } elsif ((index($has_modes, $char) != -1) == $switch) {
- $matches = 1;
- last;
- }
- }
- if (!$matches) {
- return 0;
- }
- }
- return 1;
-}
-
-# get someones flags from people.pl or friends(_shasta).pl
-sub get_flags {
- my ($chatnet, $channel, $nick, $address) = @_;
- my $flags;
- no strict 'refs';
- if (defined %{ 'Irssi::Script::people::' }) {
- if (defined ($channel)) {
- $flags = (&{ 'Irssi::Script::people::find_local_flags' }($chatnet,$channel,$nick,$address));
- } else {
- $flags = (&{ 'Irssi::Script::people::find_global_flags' }($chatnet,$nick,$address));
- }
- $flags = join('',keys(%{$flags}));
- } else {
- my $shasta;
- if (defined %{ 'Irssi::Script::friends_shasta::' }) {
- $shasta = 'friends_shasta';
- } elsif (defined &{ 'Irssi::Script::friends::get_idx' }) {
- $shasta = 'friends';
- } else {
- return undef;
- }
- my $idx = (&{ 'Irssi::Script::'.$shasta.'::get_idx' }($nick, $address));
- if ($idx == -1) {
- return '';
- }
- $flags = (&{ 'Irssi::Script::'.$shasta.'::get_friends_flags' }($idx,undef));
- if ($channel) {
- $flags .= (&{ 'Irssi::Script::'.$shasta.'::get_friends_flags' }($idx,$channel));
- }
- }
- return $flags;
-}
-
-########################################################
-### internal stuff called by manage, needed by above ###
-########################################################
-
-my %mask_to_regexp = ();
-foreach my $i (0..255) {
- my $ch = chr $i;
- $mask_to_regexp{$ch} = "\Q$ch\E";
-}
-$mask_to_regexp{'?'} = '(.)';
-$mask_to_regexp{'*'} = '(.*)';
-
-sub compile_trigger {
- my ($trigger) = @_;
- my $regexp;
-
- if ($trigger->{'regexp'}) {
- $regexp = $trigger->{'regexp'};
- } elsif ($trigger->{'pattern'}) {
- $regexp = $trigger->{'pattern'};
- $regexp =~ s/(.)/$mask_to_regexp{$1}/g;
- } else {
- delete $trigger->{'compregexp'};
- return;
- }
-
- if ($trigger->{'nocase'}) {
- $regexp = '(?i)' . $regexp;
- }
-
- $trigger->{'compregexp'} = qr/$regexp/;
-
- if(defined($trigger->{'replace'})) {
- (my $replace = $trigger->{'replace'}) =~ s/\$/\$\$/g;
- $trigger->{'compreplace'} = Irssi::parse_special($replace);
- }
-}
-
-# rebuilds triggers_by_type and updates signal binds
-sub rebuild {
- %triggers_by_type = ();
- foreach my $trigger (@triggers) {
- if (!$trigger->{'disabled'}) {
- if ($trigger->{'all'}) {
- # -all is an alias for all types in @all_types for which the filters can apply
-ALLTYPES:
- foreach my $type (@all_types) {
- # check if all filters can apply to $type
- foreach my $filter (@{$trigger->{'filters'}}) {
- if (! grep {$_ eq $type} $filters{$filter->[0]}->{'types'}) {
- next ALLTYPES;
- }
- }
- push @{$triggers_by_type{$type}}, ($trigger);
- }
- }
-
- foreach my $type ($trigger->{'all'} ? @notall_types : @trigger_types) {
- if ($trigger->{$type}) {
- push @{$triggers_by_type{$type}}, ($trigger);
- }
- }
- }
- }
-
- foreach my $signal (@signals) {
- my $should_bind = 0;
- foreach my $type (@{$signal->{'types'}}) {
- if (defined($triggers_by_type{$type})) {
- $should_bind = 1;
- }
- }
- if ($should_bind && !$signal->{'bind'}) {
- signal_add_first($signal->{'signal'}, $signal->{'sub'});
- $signal->{'bind'} = 1;
- } elsif (!$should_bind && $signal->{'bind'}) {
- signal_remove($signal->{'signal'}, $signal->{'sub'});
- $signal->{'bind'} = 0;
- }
- }
-}
-
-################################
-### manage the triggers-list ###
-################################
-
-my $trigger_file; # cached setting
-
-sub sig_setup_changed {
- $trigger_file = Irssi::settings_get_str('trigger_file');
-}
-
-sub autosave {
- cmd_save() if ($changed_since_last_save);
-}
-
-# TRIGGER SAVE
-sub cmd_save {
- my $io = new IO::File $trigger_file, "w";
- if (defined $io) {
- $io->print("#Triggers file version $VERSION\n");
- foreach my $trigger (@triggers) {
- $io->print(to_string($trigger) . "\n");
- }
- $io->close;
- }
- Irssi::printformat(MSGLEVEL_CLIENTNOTICE, 'trigger_saved', $trigger_file);
- $changed_since_last_save = 0;
-}
-
-# save on unload
-sub UNLOAD {
- cmd_save();
-}
-
-# TRIGGER LOAD
-sub cmd_load {
- sig_setup_changed(); # make sure we've read the trigger_file setting
- my $converted = 0;
- my $io = new IO::File $trigger_file, "r";
- if (not defined $io) {
- if (-e $trigger_file) {
- Irssi::print("Error opening triggers file", MSGLEVEL_CLIENTERROR);
- }
- return;
- }
- if (defined $io) {
- @triggers = ();
- my $text;
- $text = $io->getline;
- my $file_version = '';
- if ($text =~ /^#Triggers file version (.*)\n/) {
- $file_version = $1;
- }
- if ($file_version lt '0.6.1+2') {
- no strict 'vars';
- $text .= $_ foreach ($io->getlines);
- my $rep = eval "$text";
- if (! ref $rep) {
- Irssi::print("Error in triggers file");
- return;
- }
- my @old_triggers = @$rep;
-
- for (my $index=0;$index < scalar(@old_triggers);$index++) {
- my $trigger = $old_triggers[$index];
-
- if ($file_version lt '0.6.1') {
- # convert old names: notices => pubnotices, actions => pubactions
- foreach $oldname ('notices','actions') {
- if ($trigger->{$oldname}) {
- delete $trigger->{$oldname};
- $trigger->{'pub'.$oldname} = 1;
- $converted = 1;
- }
- }
- }
- if ($file_version lt '0.6.1+1' && $trigger->{'modifiers'}) {
- if ($trigger->{'modifiers'} =~ /i/) {
- $trigger->{'nocase'} = 1;
- Irssi::print("Trigger: trigger ".($index+1)." had 'i' in it's modifiers, it has been converted to -nocase");
- }
- if ($trigger->{'modifiers'} !~ /^[ig]*$/) {
- Irssi::print("Trigger: trigger ".($index+1)." had unrecognised modifier '". $trigger->{'modifiers'} ."', which couldn't be converted.");
- }
- delete $trigger->{'modifiers'};
- $converted = 1;
- }
-
- if (defined($trigger->{'replace'}) && ! $trigger->{'regexp'}) {
- Irssi::print("Trigger: trigger ".($index+1)." had -replace but no -regexp, removed it");
- splice (@old_triggers,$index,1);
- $index--; # nr of next trigger now is the same as this one was
- }
-
- # convert to text with compat, and then to new trigger hash
- $text = to_string($trigger,1);
- my @args = &shellwords($text . ' a');
- my $trigger = parse_options({},@args);
- if ($trigger) {
- push @triggers, $trigger;
- }
- }
- } else { # new format
- while ( $text = $io->getline ) {
- chop($text);
- my @args = &shellwords($text . ' a');
- my $trigger = parse_options({},@args);
- if ($trigger) {
- push @triggers, $trigger;
- }
- }
- }
- }
- Irssi::printformat(MSGLEVEL_CLIENTNOTICE, 'trigger_loaded', $trigger_file);
- if ($converted) {
- Irssi::print("Trigger: Triggers file will be in new format next time it's saved.");
- }
- rebuild();
-}
-
-# escape for printing with to_string
-# <<abcdef>> => << 'abcdef' >>
-# <<abc'def>> => << "abc'def" >>
-# <<abc'def\x02>> => << 'abc'\''def\x02' >>
-sub param_to_string {
- my ($text) = @_;
- # avoid ugly escaping if we can use "-quotes without other escaping (no " or \)
- if ($text =~ /^[^"\\]*'[^"\\]$/) {
- return ' "' . $text . '" ';
- }
- # "'" signs without a (odd number of) \ in front of them, need be to escaped as '\''
- # this is ugly :(
- $text =~ s/(^|[^\\](\\\\)*)'/$1'\\''/g;
- return " '$text' ";
-}
-
-# converts a trigger back to "-switch -options 'foo'" form
-# if $compat, $trigger is in the old format (used to convert)
-sub to_string {
- my ($trigger, $compat) = @_;
- my $string;
-
- foreach my $switch (@trigger_switches) {
- if ($trigger->{$switch}) {
- $string .= '-'.$switch.' ';
- }
- }
-
- if ($compat) {
- foreach my $filter (keys(%filters)) {
- if ($trigger->{$filter}) {
- $string .= '-' . $filter . param_to_string($trigger->{$filter});
- }
- }
- } else {
- foreach my $trigfilter (@{$trigger->{'filters'}}) {
- $string .= '-' . $trigfilter->[0] . param_to_string($trigfilter->[1]);
- }
- }
-
- foreach my $param (@trigger_params) {
- if ($trigger->{$param} || ($param eq 'replace' && defined($trigger->{'replace'}))) {
- $string .= '-' . $param . param_to_string($trigger->{$param});
- }
- }
- return $string;
-}
-
-# find a trigger (for REPLACE and DELETE), returns index of trigger, or -1 if not found
-sub find_trigger {
- my ($data) = @_;
- if ($data =~ /^[0-9]*$/ and defined($triggers[$data-1])) {
- return $data-1;
- } else {
- for (my $i=0; $i < scalar(@triggers); $i++) {
- if ($triggers[$i]->{'name'} eq $data) {
- return $i;
- }
- }
- }
- Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trigger_not_found', $data);
- return -1; # not found
-}
-
-
-# TRIGGER ADD <options>
-sub cmd_add {
- my ($data, $server, $item) = @_;
- my @args = shellwords($data . ' a');
-
- my $trigger = parse_options({}, @args);
- if ($trigger) {
- push @triggers, $trigger;
- Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trigger_added', scalar(@triggers), to_string($trigger));
- rebuild();
- $changed_since_last_save = 1;
- }
-}
-
-# TRIGGER CHANGE <nr> <options>
-sub cmd_change {
- my ($data, $server, $item) = @_;
- my @args = shellwords($data . ' a');
- my $index = find_trigger(shift @args);
- if ($index != -1) {
- if(parse_options($triggers[$index], @args)) {
- Irssi::print("Trigger " . ($index+1) ." changed to: ". to_string($triggers[$index]));
- }
- rebuild();
- $changed_since_last_save = 1;
- }
-}
-
-# parses options for TRIGGER ADD and TRIGGER CHANGE
-# if invalid args returns undef, else changes $thetrigger and returns it
-sub parse_options {
- my ($thetrigger,@args) = @_;
- my ($trigger, $option);
-
- if (pop(@args) ne 'a') {
- Irssi::print("Syntax error, probably missing a closing quote", MSGLEVEL_CLIENTERROR);
- return undef;
- }
-
- %$trigger = %$thetrigger; # make a copy to prevent changing the given trigger if args doesn't parse
-ARGS: for (my $arg = shift @args; $arg; $arg = shift @args) {
- # expand abbreviated options, put in $option
- $arg =~ s/^-//;
- $option = undef;
- foreach my $ioption (@trigger_options) {
- if (index($ioption, $arg) == 0) { # -$opt starts with $arg
- if ($option) { # another already matched
- Irssi::print("Ambiguous option: $arg", MSGLEVEL_CLIENTERROR);
- return undef;
- }
- $option = $ioption;
- last if ($arg eq $ioption); # exact match is unambiguous
- }
- }
- if (!$option) {
- Irssi::print("Unknown option: $arg", MSGLEVEL_CLIENTERROR);
- return undef;
- }
-
- # -<param> <value> or -no<param>
- foreach my $param (@trigger_params) {
- if ($option eq $param) {
- $trigger->{$param} = shift @args;
- next ARGS;
- }
- if ($option eq 'no'.$param) {
- $trigger->{$param} = undef;
- next ARGS;
- }
- }
-
- # -[no]<switch>
- foreach my $switch (@trigger_switches) {
- # -<switch>
- if ($option eq $switch) {
- $trigger->{$switch} = 1;
- next ARGS;
- }
- # -no<switch>
- elsif ($option eq 'no'.$switch) {
- $trigger->{$switch} = undef;
- next ARGS;
- }
- }
-
- # -<filter> <value>
- if ($filters{$option}) {
- push @{$trigger->{'filters'}}, [$option, shift @args, $filters{$option}->{'sub'}];
- next ARGS;
- }
-
- # -<nofilter>
- if ($option =~ /^no(.*)$/ && $filters{$1}) {
- my $filter = $1;
- # the new filters are the old grepped for everything except ones with name $filter
- @{$trigger->{'filters'}} = grep( $_->[0] ne $filter, @{$trigger->{'filters'}} );
- }
- }
-
- if (defined($trigger->{'replace'}) && ! $trigger->{'regexp'} && !$trigger->{'pattern'}) {
- Irssi::print("Trigger error: Can't have -replace without -regexp", MSGLEVEL_CLIENTERROR);
- return undef;
- }
-
- if ($trigger->{'pattern'} && $trigger->{'regexp'}) {
- Irssi::print("Trigger error: Can't have -pattern and -regexp in same trigger", MSGLEVEL_CLIENTERROR);
- return undef;
- }
-
- # remove types that are implied by -all
- if ($trigger->{'all'}) {
- foreach my $type (@all_types) {
- delete $trigger->{$type};
- }
- }
-
- # remove types for which the filters don't apply
- foreach my $type (@trigger_types) {
- if ($trigger->{$type}) {
- foreach my $filter (@{$trigger->{'filters'}}) {
- if (!grep {$_ eq $type} @{$filters{$filter->[0]}->{'types'}}) {
- Irssi::print("Warning: the filter -" . $filter->[0] . " can't apply to an event of type -$type, so I'm removing that type from this trigger.");
- delete $trigger->{$type};
- }
- }
- }
- }
-
- # check if it has at least one type
- my $has_a_type;
- foreach my $type (@trigger_types) {
- if ($trigger->{$type}) {
- $has_a_type = 1;
- last;
- }
- }
- if (!$has_a_type && !$trigger->{'all'}) {
- Irssi::print("Warning: this trigger doesn't trigger on any type of message. you probably want to add -publics or -all");
- }
-
- compile_trigger($trigger);
- %$thetrigger = %$trigger; # copy changes to real trigger
- return $thetrigger;
-}
-
-# TRIGGER DELETE <num>
-sub cmd_del {
- my ($data, $server, $item) = @_;
- my @args = shellwords($data);
- my $index = find_trigger(shift @args);
- if ($index != -1) {
- Irssi::print("Deleted ". ($index+1) .": ". to_string($triggers[$index]));
- splice (@triggers,$index,1);
- rebuild();
- $changed_since_last_save = 1;
- }
-}
-
-# TRIGGER MOVE <num> <num>
-sub cmd_move {
- my ($data, $server, $item) = @_;
- my @args = &shellwords($data);
- my $index = find_trigger(shift @args);
- if ($index != -1) {
- my $newindex = shift @args;
- if ($newindex < 1 || $newindex > scalar(@triggers)) {
- Irssi::print("$newindex is not a valid trigger number");
- return;
- }
- Irssi::print("Moved from ". ($index+1) ." to $newindex: ". to_string($triggers[$index]));
- $newindex -= 1; # array starts counting from 0
- my $trigger = splice (@triggers,$index,1); # remove from old place
- splice (@triggers,$newindex,0,($trigger)); # insert at new place
- rebuild();
- $changed_since_last_save = 1;
- }
-}
-
-# TRIGGER LIST
-sub cmd_list {
- Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trigger_header');
- my $i=1;
- foreach my $trigger (@triggers) {
- Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trigger_line', $i++, to_string($trigger));
- }
-}
-
-######################
-### initialisation ###
-######################
-
-command_bind('trigger help',\&cmd_help);
-command_bind('help trigger',\&cmd_help);
-command_bind('trigger add',\&cmd_add);
-command_bind('trigger change',\&cmd_change);
-command_bind('trigger move',\&cmd_move);
-command_bind('trigger list',\&cmd_list);
-command_bind('trigger delete',\&cmd_del);
-command_bind('trigger save',\&cmd_save);
-command_bind('trigger reload',\&cmd_load);
-command_bind 'trigger' => sub {
- my ( $data, $server, $item ) = @_;
- $data =~ s/\s+$//g;
- command_runsub('trigger', $data, $server, $item);
-};
-
-Irssi::signal_add('setup saved', \&autosave);
-Irssi::signal_add('setup changed', \&sig_setup_changed);
-
-# This makes tab completion work
-Irssi::command_set_options('trigger add',join(' ',@trigger_add_options));
-Irssi::command_set_options('trigger change',join(' ',@trigger_options));
-
-Irssi::settings_add_str($IRSSI{'name'}, 'trigger_file', Irssi::get_irssi_dir()."/triggers");
-
-cmd_load();
diff --git a/protocols/skype/t/livetest-bitlbee.sh b/protocols/skype/t/livetest-bitlbee.sh
deleted file mode 100755
index 7cbfbf6e..00000000
--- a/protocols/skype/t/livetest-bitlbee.sh
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/env bash
-
-start_skyped()
-{
- python ../skyped.py "$@" > skypedtest.pid
- while true
- do
- [ -e skypedtest.pid ] || break
- pid=$(sed 's/.*: //' skypedtest.pid)
- if [ -n "$(ps -p $pid -o pid=)" ]; then
- sleep 5
- else
- start_skyped "$@"
- break
- fi
- done
-}
-
-BITLBEE=$1
-typeset -ix PORT=`echo $2 | egrep '^[0-9]{1,5}$'`
-SCRIPT=$3
-shift 3
-
-[ -n "$SCRIPT" -a -n "$BITLBEE" -a -e "$SCRIPT" -a "$PORT" -ne 0 ] || { echo Syntax: `basename "$0"` bitlbee-executable listening-port test-script test-script-args; exit 1; }
-
-# Create or empty test dir
-mkdir livetest 2>/dev/null || rm livetest/bitlbeetest*.xml bitlbeetest.pid 2>/dev/null
-
-# Run the bee
-echo Running bitlbee...
-$VALGRIND $BITLBEE -n -c bitlbee.conf -d livetest/ -D -P bitlbeetest.pid -p $PORT 2>bitlbee.log &
-sleep 2
-
-# Check if it's really running
-kill -0 `cat bitlbeetest.pid 2>/dev/null ` 2>/dev/null || { echo Failed to run bitlbee daemon on port $PORT; exit 1; }
-
-if [ -z "$TUNNELED_MODE" ]; then
- # Set up skyped
-
- rm -rf etc
- mkdir etc
- cd etc
- cp ../../skyped.cnf .
- cp ~/.skyped/skyped.cert.pem .
- cp ~/.skyped/skyped.key.pem .
- cd ..
- echo "[skyped]" > skyped.conf
- echo "username = $TEST_SKYPE_ID" >> skyped.conf
- SHA1=`which sha1sum`
- if [ -z "$SHA1" ]; then
- SHA1=`which sha1`
- fi
- if [ -z "$SHA1" ]; then
- echo Test failed
- echo "(Can't compute password for skyped.conf)"
- exit 77
- fi
- echo "password = $(echo -n $TEST_SKYPE_PASSWORD|$SHA1|sed 's/ *-$//')" >> skyped.conf
- # we use ~ here to test that resolve that syntax works
- echo "cert = $(pwd|sed "s|$HOME|~|")/etc/skyped.cert.pem" >> skyped.conf
- echo "key = $(pwd|sed "s|$HOME|~|")/etc/skyped.key.pem" >> skyped.conf
- echo "port = 2727" >> skyped.conf
-
- # Run skyped
- start_skyped -c skyped.conf -l skypedtest.log &
- sleep 2
-fi
-
-if [ "$TUNNELED_MODE" = "yes" ]; then
- rm -f tunnel.pid
- if [ -n "$TUNNEL_SCRIPT" ]; then
- $TUNNEL_SCRIPT &
- echo $! > tunnel.pid
- sleep 5
- fi
-fi
-
-# Run the test
-echo Running test script...
-"$SCRIPT" $*
-RET=$?
-
-if [ -z "$TUNNELED_MODE" ]; then
- # skyped runs on another host: no means to kill it
- # Kill skyped
- killall -TERM skype
- if [ -f skypedtest.pid ]; then
- pid=$(sed 's/.*: //' skypedtest.pid)
- rm skypedtest.pid
- [ -n "$(ps -p $pid -o pid=)" ] && kill -TERM $pid
- fi
-fi
-
-if [ "$TUNNELED_MODE" = "yes" ]; then
- if [ -n "$TUNNEL_SCRIPT" ]; then
- cat tunnel.pid >> /tmp/tunnel.pid
- kill `cat tunnel.pid`
- rm -f tunnel.pid
- fi
-fi
-
-# Kill bee
-echo Killing bitlbee...
-kill `cat bitlbeetest.pid`
-
-if [ "$TUNNELED_MODE" = "yes" ]; then
- # give the skyped a chance to timeout
- sleep 30
-fi
-
-# Return test result
-[ $RET -eq 0 ] && echo Test passed
-[ $RET -ne 0 ] && echo Test failed
-[ $RET -eq 22 ] && echo '(timed out)'
-[ $RET -eq 66 ] && echo '(environment variables missing)'
-exit $RET
diff --git a/protocols/skype/t/login-bitlbee.mock b/protocols/skype/t/login-bitlbee.mock
new file mode 100644
index 00000000..41273a83
--- /dev/null
+++ b/protocols/skype/t/login-bitlbee.mock
@@ -0,0 +1,7 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> PRIVMSG &bitlbee :skype - Logging in: Logged in
diff --git a/protocols/skype/t/login-skyped.mock b/protocols/skype/t/login-skyped.mock
new file mode 100644
index 00000000..eacff2e6
--- /dev/null
+++ b/protocols/skype/t/login-skyped.mock
@@ -0,0 +1,16 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS ONLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
diff --git a/protocols/skype/t/msg-bitlbee.mock b/protocols/skype/t/msg-bitlbee.mock
new file mode 100644
index 00000000..42cc163d
--- /dev/null
+++ b/protocols/skype/t/msg-bitlbee.mock
@@ -0,0 +1,9 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype on
+>> :bob!bob@skype.com JOIN :&bitlbee
+<< PRIVMSG &bitlbee :bob: foo
+>> :bob!bob@skype.com PRIVMSG &bitlbee :alice: bar
diff --git a/protocols/skype/t/msg-skyped.mock b/protocols/skype/t/msg-skyped.mock
new file mode 100644
index 00000000..03efb6bc
--- /dev/null
+++ b/protocols/skype/t/msg-skyped.mock
@@ -0,0 +1,49 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123, bob
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> GET USER bob ONLINESTATUS
+<< USER bob ONLINESTATUS ONLINE
+>> GET USER bob FULLNAME
+<< USER bob FULLNAME Bob
+>> MESSAGE bob foo
+<< CHATMESSAGE 290 STATUS SENDING
+<< CHAT #alice/$bob;ea753190f0a3e49b NAME #alice/$bob;ea753190f0a3e49b
+<< CHAT #alice/$bob;ea753190f0a3e49b STATUS DIALOG
+<< CHATMEMBER 287 ROLE USER
+<< CHAT #alice/$bob;ea753190f0a3e49b MYROLE USER
+<< CHAT #alice/$bob;ea753190f0a3e49b MEMBERS alice bob
+<< CHAT #alice/$bob;ea753190f0a3e49b ACTIVEMEMBERS alice
+<< CHAT #alice/$bob;ea753190f0a3e49b STATUS DIALOG
+<< CHAT #alice/$bob;ea753190f0a3e49b TIMESTAMP 1357987847
+<< CHAT #alice/$bob;ea753190f0a3e49b DIALOG_PARTNER bob
+<< CHAT #alice/$bob;ea753190f0a3e49b MEMBERS alice bob
+<< CHAT #alice/$bob;ea753190f0a3e49b FRIENDLYNAME bob | foo
+<< CHAT #alice/$bob;ea753190f0a3e49b POSTERS alice
+<< CHAT #alice/$bob;ea753190f0a3e49b ACTIVITY_TIMESTAMP 1357987847
+<< CHAT #alice/$bob;ea753190f0a3e49b FRIENDLYNAME bob | foo
+<< CHATMESSAGE 289 STATUS SENDING
+<< CHATMESSAGE 290 STATUS SENDING
+<< CHATMESSAGE 289 STATUS SENT
+<< CHATMESSAGE 290 STATUS SENT
+<< CHATMEMBER 288 IS_ACTIVE TRUE
+<< CHAT #alice/$bob;ea753190f0a3e49b ACTIVEMEMBERS alice bob
+<< CHAT #alice/$bob;ea753190f0a3e49b POSTERS alice bob
+<< CHAT #alice/$bob;ea753190f0a3e49b ACTIVITY_TIMESTAMP 1357987875
+<< CHATMESSAGE 293 STATUS RECEIVED
+>> GET CHATMESSAGE 293 FROM_HANDLE
+<< CHATMESSAGE 293 FROM_HANDLE bob
+>> GET CHATMESSAGE 293 BODY
+<< CHATMESSAGE 293 BODY bar
+>> GET CHATMESSAGE 293 TYPE
+<< CHATMESSAGE 293 TYPE SAID
+>> GET CHATMESSAGE 293 CHATNAME
+<< CHATMESSAGE 293 CHATNAME #alice/$bob;ea753190f0a3e49b
diff --git a/protocols/skype/t/set-mood-text-bitlbee.mock b/protocols/skype/t/set-mood-text-bitlbee.mock
new file mode 100644
index 00000000..f017f8bd
--- /dev/null
+++ b/protocols/skype/t/set-mood-text-bitlbee.mock
@@ -0,0 +1,9 @@
+>> NOTICE AUTH
+<< NICK alice
+<< USER alice alice localhost :Alice
+>> PRIVMSG &bitlbee
+<< PRIVMSG &bitlbee :account add skype alice foo
+<< PRIVMSG &bitlbee :account skype set skypeconsole_receive true
+<< PRIVMSG &bitlbee :account skype on
+<< PRIVMSG &bitlbee :account skype set mood_text "foo bar"
+>> PRIVMSG &bitlbee :alice: PROFILE MOOD_TEXT foo bar
diff --git a/protocols/skype/t/set-mood-text-skyped.mock b/protocols/skype/t/set-mood-text-skyped.mock
new file mode 100644
index 00000000..566f4234
--- /dev/null
+++ b/protocols/skype/t/set-mood-text-skyped.mock
@@ -0,0 +1,14 @@
+>> SEARCH GROUPS CUSTOM
+<< GROUPS 48, 49
+>> SEARCH FRIENDS
+<< USERS echo123
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> SET USERSTATUS ONLINE
+<< USERSTATUS ONLINE
+>> GET USER echo123 ONLINESTATUS
+<< USER echo123 ONLINESTATUS ONLINE
+>> GET USER echo123 FULLNAME
+<< USER echo123 FULLNAME Echo / Sound Test Service
+>> SET PROFILE MOOD_TEXT foo bar
+<< PROFILE MOOD_TEXT foo bar
diff --git a/protocols/skype/test.py b/protocols/skype/test.py
new file mode 100755
index 00000000..63652f76
--- /dev/null
+++ b/protocols/skype/test.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python2.7
+
+import subprocess
+import sys
+import pexpect
+import unittest
+import shutil
+import os
+import hashlib
+
+def openssl(args):
+ with open(os.devnull, "w") as devnull:
+ proc = subprocess.Popen(['openssl'] + args, stdin=subprocess.PIPE, stderr=devnull)
+ for i in range(6):
+ proc.stdin.write("\n")
+ proc.stdin.close()
+ proc.communicate()
+def setupSkyped():
+ try:
+ shutil.rmtree("t/skyped")
+ except OSError:
+ pass
+ os.makedirs("t/skyped")
+ cwd = os.getcwd()
+ os.chdir("t/skyped")
+ try:
+ shutil.copyfile("../../skyped.cnf", "skyped.cnf")
+ openssl(['req', '-new', '-x509', '-days', '365', '-nodes', '-config', 'skyped.cnf', '-out', 'skyped.cert.pem', '-keyout', 'skyped.key.pem'])
+ with open("skyped.conf", "w") as sock:
+ sock.write("[skyped]\n")
+ sock.write("username = alice\n")
+ sock.write("password = %s\n" % hashlib.sha1("foo").hexdigest())
+ sock.write("cert = %s/skyped.cert.pem\n" % os.getcwd())
+ sock.write("key = %s/skyped.key.pem\n" % os.getcwd())
+ sock.write("port = 2727\n")
+ finally:
+ os.chdir(cwd)
+
+class Test(unittest.TestCase):
+ def mock(self, name):
+ with open("t/skyped.log", "w") as skyped_log,\
+ open("t/pexpect.log", "w") as pexpect_log:
+ skyped = subprocess.Popen([sys.executable, "skyped.py",
+ "-c", "t/skyped/skyped.conf", "-n", "-d", "-m", "t/%s-skyped.mock" % name],
+ stdout=skyped_log, stderr=subprocess.STDOUT)
+ try:
+ bitlbee = pexpect.spawn('../../bitlbee', ['-d', 't/bitlbee'], logfile=pexpect_log)
+ if os.environ.get('ATTACH_GDB'):
+ subprocess.Popen(['gdb', '-batch-silent',
+ '-ex', 'set logging overwrite on',
+ '-ex', 'set logging file t/gdb-%s.log' % bitlbee.pid,
+ '-ex', 'set logging on',
+ '-ex', 'handle all pass nostop noprint',
+ '-ex', 'handle SIGSEGV pass stop print',
+ '-ex', 'set pagination 0',
+ '-ex', 'continue',
+ '-ex', 'backtrace full',
+ '-ex', 'info registers',
+ '-ex', 'thread apply all backtrace',
+ '-ex', 'quit',
+ '../../bitlbee', str(bitlbee.pid) ])
+ bitlbee_mock = open("t/%s-bitlbee.mock" % name)
+ for i in bitlbee_mock.readlines():
+ line = i.strip()
+ if line.startswith(">> "):
+ bitlbee.expect_exact(line[3:], timeout=10)
+ elif line.startswith("<< "):
+ bitlbee.sendline(line[3:])
+ bitlbee_mock.close()
+ bitlbee.close()
+ finally:
+ skyped.terminate()
+ skyped.communicate()
+
+ def setUp(self):
+ try:
+ shutil.rmtree("t/bitlbee")
+ except OSError:
+ pass
+ os.makedirs("t/bitlbee")
+
+ def testMsg(self):
+ self.mock("msg")
+
+ def testLogin(self):
+ self.mock("login")
+
+ def testInfo(self):
+ self.mock("info")
+
+ def testCall(self):
+ self.mock("call")
+
+ def testCallFailed(self):
+ self.mock("call-failed")
+
+ def testAddYes(self):
+ self.mock("add-yes")
+
+ def testAddedYes(self):
+ self.mock("added-yes")
+
+ def testAddedNo(self):
+ self.mock("added-no")
+
+ def testGroupchatInvited(self):
+ self.mock("groupchat-invited")
+
+ def testGroupchatInvite(self):
+ self.mock("groupchat-invite")
+
+ def testGroupchatLeave(self):
+ self.mock("groupchat-leave")
+
+ def testCalledYes(self):
+ self.mock("called-yes")
+
+ def testCalledNo(self):
+ self.mock("called-no")
+
+ def testFiletransfer(self):
+ self.mock("filetransfer")
+
+ def testGroupRead(self):
+ self.mock("group-read")
+
+ def testCtcpHelp(self):
+ self.mock("ctcp-help")
+
+ def testSetMoodText(self):
+ self.mock("set-mood-text")
+
+if __name__ == '__main__':
+ setupSkyped()
+ unittest.main()