summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.am18
-rw-r--r--scripts/Makefile.in741
-rw-r--r--scripts/autoop.pl156
-rw-r--r--scripts/autorejoin.pl72
-rw-r--r--scripts/buf.pl132
-rw-r--r--scripts/dns.pl236
-rw-r--r--scripts/examples/Makefile.am8
-rw-r--r--scripts/examples/Makefile.in552
-rw-r--r--scripts/examples/command.pl23
-rw-r--r--scripts/examples/msg-event.pl41
-rw-r--r--scripts/examples/redirect.pl40
-rw-r--r--scripts/kills.pl103
-rw-r--r--scripts/mail.pl416
-rw-r--r--scripts/meson.build14
-rw-r--r--scripts/mlock.pl135
-rw-r--r--scripts/quitmsg.pl36
-rw-r--r--scripts/scriptassist.pl1265
-rw-r--r--scripts/usercount.pl184
18 files changed, 4172 insertions, 0 deletions
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
new file mode 100644
index 0000000..42b3ea7
--- /dev/null
+++ b/scripts/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = examples
+
+scriptdir = $(datadir)/irssi/scripts
+
+script_DATA = \
+ autoop.pl \
+ autorejoin.pl \
+ buf.pl \
+ dns.pl \
+ kills.pl \
+ mail.pl \
+ mlock.pl \
+ quitmsg.pl \
+ scriptassist.pl \
+ usercount.pl
+
+EXTRA_DIST = $(script_DATA) \
+ meson.build
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
new file mode 100644
index 0000000..eaacc6c
--- /dev/null
+++ b/scripts/Makefile.in
@@ -0,0 +1,741 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = scripts
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
+ $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/libgcrypt.m4 \
+ $(top_srcdir)/m4/libotr.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/irssi-config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(scriptdir)"
+DATA = $(script_DATA)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir distdir-am
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHAT_MODULES = @CHAT_MODULES@
+COMMON_LIBS = @COMMON_LIBS@
+COMMON_NOUI_LIBS = @COMMON_NOUI_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FUZZER_LIBS = @FUZZER_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBOTR_CFLAGS = @LIBOTR_CFLAGS@
+LIBOTR_LIBS = @LIBOTR_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+OTR_CFLAGS = @OTR_CFLAGS@
+OTR_LDFLAGS = @OTR_LDFLAGS@
+OTR_LINK_FLAGS = @OTR_LINK_FLAGS@
+OTR_LINK_LIBS = @OTR_LINK_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL_CFLAGS = @PERL_CFLAGS@
+PERL_EXTRA_OPTS = @PERL_EXTRA_OPTS@
+PERL_FE_LINK_LIBS = @PERL_FE_LINK_LIBS@
+PERL_LDFLAGS = @PERL_LDFLAGS@
+PERL_LINK_FLAGS = @PERL_LINK_FLAGS@
+PERL_LINK_LIBS = @PERL_LINK_LIBS@
+PERL_MM_OPT = @PERL_MM_OPT@
+PERL_MM_PARAMS = @PERL_MM_PARAMS@
+PERL_STATIC_LIBS = @PERL_STATIC_LIBS@
+PERL_USE_LIB = @PERL_USE_LIB@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROG_LIBS = @PROG_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TEXTUI_LIBS = @TEXTUI_LIBS@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+installed_test_metadir = @installed_test_metadir@
+installed_testdir = @installed_testdir@
+irc_MODULES = @irc_MODULES@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+otr_module_lib = @otr_module_lib@
+otr_static_lib = @otr_static_lib@
+pdfdir = @pdfdir@
+perl_module_fe_lib = @perl_module_fe_lib@
+perl_module_lib = @perl_module_lib@
+perl_static_fe_lib = @perl_static_fe_lib@
+perl_static_lib = @perl_static_lib@
+perlpath = @perlpath@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sedpath = @sedpath@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = examples
+scriptdir = $(datadir)/irssi/scripts
+script_DATA = \
+ autoop.pl \
+ autorejoin.pl \
+ buf.pl \
+ dns.pl \
+ kills.pl \
+ mail.pl \
+ mlock.pl \
+ quitmsg.pl \
+ scriptassist.pl \
+ usercount.pl
+
+EXTRA_DIST = $(script_DATA) \
+ meson.build
+
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign scripts/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign scripts/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-scriptDATA: $(script_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(script_DATA)'; test -n "$(scriptdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(scriptdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(scriptdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(scriptdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(scriptdir)" || exit $$?; \
+ done
+
+uninstall-scriptDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(script_DATA)'; test -n "$(scriptdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(scriptdir)'; $(am__uninstall_files_from_dir)
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(DATA)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(scriptdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-scriptDATA
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-scriptDATA
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+ check-am clean clean-generic clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-scriptDATA install-strip installcheck installcheck-am \
+ installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-scriptDATA
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/scripts/autoop.pl b/scripts/autoop.pl
new file mode 100644
index 0000000..b72def1
--- /dev/null
+++ b/scripts/autoop.pl
@@ -0,0 +1,156 @@
+# /AUTOOP <*|#channel> [<nickmasks>]
+# use friends.pl if you need more features
+
+use Irssi;
+use strict;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = "1.10";
+%IRSSI = (
+ authors => 'Timo Sirainen & Jostein Kjønigsen',
+ name => 'autoop',
+ description => 'Simple auto-op script',
+ license => 'Public Domain',
+ changed => 'Fri Nov 24 12:55 GMT+1 2014'
+);
+
+my (%opnicks, %temp_opped);
+
+sub cmd_autoop {
+ my ($data) = @_;
+ my ($channel, $masks) = split(" ", $data, 2);
+
+ if ($channel eq "") {
+ if (!%opnicks) {
+ Irssi::print("Usage: /AUTOOP <*|#channel> [<nickmasks>]");
+ Irssi::print("No-one's being auto-opped currently.");
+ return;
+ }
+
+ Irssi::print("Currently auto-opping in channels:");
+ foreach $channel (keys %opnicks) {
+ $masks = $opnicks{$channel};
+
+ if ($channel eq "*") {
+ Irssi::print("All channels: $masks");
+ } else {
+ Irssi::print("$channel: $masks");
+ }
+ }
+ return;
+ }
+
+ if ($masks eq "") {
+ $masks = "<no-one>";
+ delete $opnicks{$channel};
+ } else {
+ $opnicks{$channel} = $masks;
+ }
+ if ($channel eq "*") {
+ Irssi::print("Now auto-opping in all channels: $masks");
+ } else {
+ Irssi::print("$channel: Now auto-opping: $masks");
+ }
+}
+
+sub autoop {
+ my ($channel, $masks, @nicks) = @_;
+ my ($server, $nickrec);
+
+ $server = $channel->{server};
+ foreach $nickrec (@nicks) {
+ my $nick = $nickrec->{nick};
+ my $host = $nickrec->{host};
+
+ if (!$temp_opped{$nick} &&
+ $server->masks_match($masks, $nick, $host)) {
+ $channel->command("/op $nick");
+ $temp_opped{$nick} = 1;
+ }
+ }
+}
+
+sub event_massjoin {
+ my ($channel, $nicks_list) = @_;
+ my @nicks = @{$nicks_list};
+
+ return if (!$channel->{chanop});
+
+ undef %temp_opped;
+
+ # channel specific
+ my $masks = $opnicks{$channel->{name}};
+ autoop($channel, $masks, @nicks) if ($masks);
+
+ # for all channels
+ $masks = $opnicks{"*"};
+ autoop($channel, $masks, @nicks) if ($masks);
+}
+
+Irssi::command_bind('autoop', 'cmd_autoop');
+Irssi::signal_add_last('massjoin', 'event_massjoin');
+
+sub load_autoops {
+ my($file) = Irssi::get_irssi_dir."/autoop";
+ my($count) = 0;
+ local(*CONF);
+
+ %opnicks = ();
+ open(CONF, "<", "$file") or return;
+ while (my $line = <CONF>) {
+ if ($line !=~ /^\s*$/) {
+ cmd_autoop($line);
+ $count++;
+ }
+ }
+ close(CONF);
+
+ Irssi::print("Loaded $count channels from $file");
+}
+
+# --------[ save_autoops ]------------------------------------------------
+
+sub save_autoops {
+ my($auto) = @_;
+ my($file) = Irssi::get_irssi_dir."/autoop";
+ my($count) = 0;
+ my($channel) = "";
+ local(*CONF);
+
+ return if $auto;
+
+ open(CONF, ">", "$file");
+ foreach $channel (keys %opnicks) {
+ my $masks = $opnicks{$channel};
+ print CONF "$channel\t$masks\n";
+ $count++;
+ }
+ close(CONF);
+
+ Irssi::print("Saved $count channels to $file")
+ unless $auto;
+}
+
+
+# --------[ sig_setup_reread ]------------------------------------------
+
+# main setup is reread, so let us do it too
+sub sig_setup_reread {
+ load_autoops;
+}
+
+# --------[ sig_setup_save ]--------------------------------------------
+
+# main config is saved, and so we should save too
+sub sig_setup_save {
+ my($mainconf,$auto) = @_;
+ save_autoops($auto);
+}
+
+# persistance
+
+Irssi::signal_add('setup saved', 'sig_setup_save');
+Irssi::signal_add('setup reread', 'sig_setup_reread');
+
+# ensure we load persisted values on start
+load_autoops;
diff --git a/scripts/autorejoin.pl b/scripts/autorejoin.pl
new file mode 100644
index 0000000..e5be21b
--- /dev/null
+++ b/scripts/autorejoin.pl
@@ -0,0 +1,72 @@
+# automatically rejoin to channel after kicked
+# delayed rejoin: Lam 28.10.2001 (lam@lac.pl)
+
+# /SET autorejoin_channels #channel1 #channel2 ...
+# /SET autorejoin_delay 5
+
+# NOTE: I personally don't like this feature, in most channels I'm in it
+# will just result as ban. You've probably misunderstood the idea of /KICK
+# if you kick/get kicked all the time "just for fun" ...
+
+use Irssi;
+use Irssi::Irc;
+use strict;
+use vars qw($VERSION %IRSSI);
+$VERSION = "1.1.0";
+%IRSSI = (
+ authors => "Timo 'cras' Sirainen, Leszek Matok",
+ contact => "lam\@lac.pl",
+ name => "autorejoin",
+ description => "Automatically rejoin to channel after being kicked, after a (short) user-defined delay",
+ license => "GPLv2",
+ changed => "10.3.2002 14:00"
+);
+
+sub rejoin {
+ my ( $data ) = @_;
+ my ( $servtag, $channel, $pass ) = @{$data};
+
+ my $server = Irssi::server_find_tag( $servtag );
+ $server->send_raw( "JOIN $channel $pass" ) if ( $server );
+}
+
+sub event_rejoin_kick {
+ my ( $server, $data ) = @_;
+ my ( $channel, $nick ) = split( / +/, $data );
+
+ return if ( $server->{ nick } ne $nick );
+
+ # check if channel has password
+ my $chanrec = $server->channel_find( $channel );
+ my $password = $chanrec->{ key } if ( $chanrec );
+ my $rejoinchan = $chanrec->{ name } if ( $chanrec );
+ my $servtag = $server->{ tag };
+
+ # check if we want to autorejoin this channel
+ my $chans = Irssi::settings_get_str( 'autorejoin_channels' );
+
+ if ( $chans ) {
+ my $found = 0;
+ foreach my $chan ( split( /[ ,]/, $chans ) ) {
+ if ( lc( $chan ) eq lc( $channel ) ) {
+ $found = 1;
+ last;
+ }
+ }
+ return unless $found;
+ }
+
+ my @args = ($servtag, $rejoinchan, $password);
+ my $delay = Irssi::settings_get_int( "autorejoin_delay" );
+
+ if ($delay) {
+ Irssi::print "Rejoining $rejoinchan in $delay seconds.";
+ Irssi::timeout_add_once( $delay * 1000, "rejoin", \@args );
+ } else {
+ rejoin( \@args );
+ }
+}
+
+Irssi::settings_add_int('misc', 'autorejoin_delay', 5);
+Irssi::settings_add_str('misc', 'autorejoin_channels', '');
+Irssi::signal_add( 'event kick', 'event_rejoin_kick' );
diff --git a/scripts/buf.pl b/scripts/buf.pl
new file mode 100644
index 0000000..0b37e9d
--- /dev/null
+++ b/scripts/buf.pl
@@ -0,0 +1,132 @@
+use strict;
+use vars qw($VERSION %IRSSI);
+use Storable;
+use 5.014000;
+
+use Irssi qw(command signal_add signal_add_first active_win
+ settings_get_str settings_get_bool channels windows
+ settings_add_str settings_add_bool get_irssi_dir
+ window_find_refnum signal_stop);
+$VERSION = '3.00';
+%IRSSI = (
+ authors => 'Juerd',
+ contact => 'juerd@juerd.nl',
+ name => 'Scroll buffer restorer',
+ description => 'Saves the buffer for /upgrade, so that no information is lost',
+ license => 'Public Domain',
+ url => 'http://juerd.nl/irssi/',
+ changed => 'Thu Mar 29 10:00 CEST 2018',
+ changes => 'Fixed file permissions (leaked everything via filesystem), rewritten to use Storable and print to correct levels',
+ note1 => 'This script HAS TO BE in your scripts/autorun!',
+ note2 => 'Perl support must be static or in startup',
+);
+
+# Q: How can I get a very smooth and clean upgrade?
+#
+# A: /set -clear upgrade_separator
+# /set upgrade_suppress_join ON (default)
+# /set channel_sync OFF
+
+# Q: Can I use color in the upgrade_separator?
+# Q: Is it possible to save my command history?
+# Q: Can I prevent the screen from blinking?
+# Q: Can you make it faster?
+#
+# A: Probably not, but if you can do it, tell me how.
+
+use Irssi::TextUI;
+use Data::Dumper;
+
+my %suppress;
+
+sub _filename { sprintf '%s/scrollbuffer', get_irssi_dir }
+
+sub upgrade {
+ my $out = { suppress => [ map $_->{server}->{address} . $_->{name}, channels ] };
+ for my $window (windows) {
+ next unless defined $window;
+ next if $window->{name} eq 'status';
+ my $view = $window->view;
+ my $line = $view->get_lines;
+ my $lines = 0;
+ my $buf = '';
+ my $output;
+ if (defined $line) {
+ {
+ push @$output, { level => $line->{info}{level}, data => $line->get_text(1) };
+ $line = $line->next;
+ redo if defined $line;
+ }
+ }
+ push @{$out->{windows}}, { refnum => $window->{refnum}, lines => $output };
+ }
+ my $old_umask = umask 0077;
+ my $fn = _filename;
+ store($out, $fn) or die "Could not store data to $fn";
+ umask $old_umask;
+ unlink sprintf("%s/sessionconfig", get_irssi_dir);
+ command 'layout save';
+ command 'save';
+}
+
+sub restore {
+ my $fn = _filename;
+ my $in = retrieve($fn) or die "Could not retrieve data from $fn";
+ unlink $fn or warn "unlink $fn: $!";
+
+ my @suppress = @{$in->{suppress}};
+ @suppress{@suppress} = (2) x @suppress if (settings_get_bool 'upgrade_suppress_join');
+
+ active_win->command('^window scroll off');
+ for my $win (@{$in->{windows}}) {
+ my $window = window_find_refnum $win->{refnum};
+ next unless $window;
+ my @lines = @{ $win->{lines} || [] };
+ next unless @lines;
+
+ my $view = $window->view;
+ $view->remove_all_lines();
+ $view->redraw();
+ for my $line (@lines) {
+ my $level = $line->{level};
+ my $data = $line->{data};
+ $window->gui_printtext_after($window->last_line_insert, $level, "$data\n");
+ }
+ my $sep = settings_get_str 'upgrade_separator';
+ $window->gui_printtext_after($window->last_line_insert, MSGLEVEL_CLIENTNOTICE, "\cO$sep\n") if $sep ne '';
+ $view->redraw();
+ }
+ active_win->command('^window scroll on');
+ active_win->command('^scrollback end');
+}
+
+sub suppress {
+ my ($first, $second) = @_;
+ return unless scalar keys %suppress and settings_get_bool 'upgrade_suppress_join';
+ my $key_part = (grep { /^:?[#!+&]/ } split ' ', $second)[0];
+ $key_part =~ s/^://;
+ my $key = $first->{address} . $key_part;
+ if (exists $suppress{$key} and $suppress{$key}--) {
+ signal_stop();
+ delete $suppress{$key} unless $suppress{$key};
+ }
+}
+
+settings_add_str 'buffer', 'upgrade_separator' => '=Upgrade=';
+settings_add_bool 'buffer', 'upgrade_suppress_join' => 1;
+
+signal_add_first 'session save' => 'upgrade';
+signal_add_first 'session restore' => 'restore';
+signal_add 'event 366' => 'suppress';
+signal_add 'event join' => 'suppress';
+
+unless (-f sprintf('%s/scripts/autorun/buf.pl', get_irssi_dir)) {
+ Irssi::print('PUT THIS SCRIPT IN ~/.irssi/scripts/autorun/ BEFORE /UPGRADING!!');
+}
+
+# Remove any left-over file. If 'session' doesn't exist (created by irssi
+# during /UPGRADE), neither should our file.
+unless (-e sprintf('%s/session', get_irssi_dir)) {
+ my $fn = _filename;
+ unlink $fn or warn "unlink $fn: $!" if -e $fn;
+}
diff --git a/scripts/dns.pl b/scripts/dns.pl
new file mode 100644
index 0000000..9e9f478
--- /dev/null
+++ b/scripts/dns.pl
@@ -0,0 +1,236 @@
+# /DNS <nick>|<host>|<ip> ...
+#
+# v2.2
+# add ipv6 support
+# v2.1.1
+# updated the script to fix a bug where the script would let
+# a trailing whitespace go through (ex: tab completion)
+# - inch <inch@stmpd.net>
+
+use strict;
+use Socket;
+use POSIX;
+
+use vars qw($VERSION %IRSSI);
+$VERSION = "2.2";
+%IRSSI = (
+ authors => "Timo \'cras\' Sirainen",
+ contact => "tss\@iki.fi",
+ name => "dns",
+ description => "/DNS <nick>|<host>|<ip> ...",
+ license => "Public Domain",
+ url => "http://irssi.org/",
+ changed => "2019-01-24"
+);
+
+my (%resolve_hosts, %resolve_nicks, %resolve_print); # resolve queues
+my $userhosts; # number of USERHOSTs currently waiting for reply
+my $lookup_waiting; # 1 if we're waiting a reply for host lookup
+
+# for the current host lookup
+my ($print_server, $print_host, $print_name, @print_ips);
+my ($input_skip_next, $input_query);
+
+my $pipe_tag;
+
+sub cmd_dns {
+ my ($nicks, $server) = @_;
+ return if !$nicks;
+ $nicks =~ s/\s+$//;
+ # get list of nicks/hosts we want to know
+ my $tag = !$server ? undef : $server->{tag};
+ my $ask_nicks = "";
+ my $print_error = 0;
+ foreach my $nick (split(" ", $nicks)) {
+ $nick = lc($nick);
+ if ($nick =~ /[\.:]/) {
+ # it's an IP or hostname
+ $resolve_hosts{$nick} = $tag;
+ } else {
+ # it's nick
+ if (!$print_error && (!$server || !$server->{connected})) {
+ $print_error = 1;
+ Irssi::print("Not connected to server");
+ } else {
+ $resolve_nicks{$nick} = 1;
+ $ask_nicks .= "$nick ";
+ }
+ }
+ }
+
+ if ($ask_nicks ne "") {
+ # send the USERHOST query
+ $userhosts++;
+ $server->redirect_event('userhost', 1, $ask_nicks, 0, 'redir dns failure', {
+ 'event 302' => 'redir dns host',
+ '' => 'event empty' } );
+ $server->send_raw("USERHOST :$nicks");
+ }
+
+ # ask the IPs/hostnames immediately
+ host_lookup() if (!$lookup_waiting);
+}
+
+sub sig_failure {
+ Irssi::print("Error getting hostname for nick");
+ %resolve_nicks = () if (--$userhosts == 0);
+}
+
+sub sig_userhost {
+ my ($server, $data) = @_;
+ $data =~ s/^[^ ]* :?//;
+ my @hosts = split(/ +/, $data);
+
+ # move resolve_nicks -> resolve_hosts
+ foreach my $host (@hosts) {
+ if ($host =~ /^([^=\*]*)\*?=.(.*)@(.*)/) {
+ my $nick = lc($1);
+ my $user = $2;
+ $host = lc($3);
+
+ $resolve_hosts{$host} = $resolve_nicks{$nick};
+ delete $resolve_nicks{$nick};
+ $resolve_print{$host} = "[$nick!$user"."@"."$host]";
+ }
+ }
+
+ if (--$userhosts == 0 && %resolve_nicks) {
+ # unknown nicks - they didn't contain . or : so it can't be
+ # IP or hostname.
+ Irssi::print("Unknown nicks: ".join(' ', keys %resolve_nicks));
+ %resolve_nicks = ();
+ }
+
+ host_lookup() if (!$lookup_waiting);
+}
+
+sub dns {
+ my ($host) =@_;
+ my %hints = (socktype => SOCK_STREAM);
+ my ($err, @res) = Socket::getaddrinfo($host, "http", \%hints);
+ my @res1;
+ if ($err ==0 ) {
+ foreach(@res) {
+ if ($_->{family}==AF_INET) {
+ my ($proto,$ip)=unpack_sockaddr_in($_->{addr});
+ push @res1, Socket::inet_ntop(AF_INET,$ip);
+ }
+ if ($_->{family}==AF_INET6) {
+ my ($proto,$ip)=unpack_sockaddr_in6($_->{addr});
+ push @res1, Socket::inet_ntop(AF_INET6,$ip);
+ }
+ }
+ return join(' ',@res1);
+ }
+}
+
+sub rdns {
+ my ($host) =@_;
+ my %hints = (socktype => SOCK_STREAM);
+ my ($err, @res) = Socket::getaddrinfo($host, "http", \%hints);
+ my @res1;
+ if ($err ==0 ) {
+ foreach(@res) {
+ my ($err, $hostname, $servicename) = Socket::getnameinfo $_->{addr};
+ if ($err ==0) {
+ push @res1, $hostname;
+ }
+ }
+ return join(' ',@res1);
+ }
+}
+
+sub host_lookup {
+ return if (!%resolve_hosts);
+
+ my ($host) = keys %resolve_hosts;
+ $print_server = $resolve_hosts{$host};
+
+ $print_host = undef;
+ $print_name = $resolve_print{$host};
+ @print_ips = ();
+
+ delete $resolve_hosts{$host};
+ delete $resolve_print{$host};
+
+ $input_query = $host;
+ $input_skip_next = 0;
+
+ # pipe is used to get the reply from child
+ my ($rh, $wh);
+ pipe($rh, $wh);
+
+ # non-blocking host lookups with fork()ing
+ my $pid = fork();
+ if (!defined($pid)) {
+ %resolve_hosts = ();
+ %resolve_print = ();
+ Irssi::print("Can't fork() - aborting");
+ close($rh); close($wh);
+ return;
+ }
+ $lookup_waiting++;
+
+ if ($pid > 0) {
+ # parent, wait for reply
+ close($wh);
+ Irssi::pidwait_add($pid);
+ $pipe_tag = Irssi::input_add(fileno($rh), INPUT_READ, \&pipe_input, $rh);
+ return;
+ }
+
+ my $text;
+ eval {
+ # child, do the lookup
+ my $name = "";
+ if ($host =~ /^[0-9\.]*$/ || $host =~ m/^[0-9a-f:]*$/) {
+ # ip -> host
+ #$name = gethostbyaddr(inet_aton($host), AF_INET);
+ $name = rdns($host);
+ } else {
+ # host -> ip
+ $name = dns($host);
+ }
+
+ $print_name = $input_query if !$print_name;
+ if (!$name) {
+ $text = "No information for $print_name";
+ } else {
+ $text = "$print_name: $name";
+ }
+ };
+ $text = $! if (!$text);
+
+ eval {
+ # write the reply
+ print($wh $text);
+ close($wh);
+ };
+ POSIX::_exit(1);
+}
+
+sub pipe_input {
+ my $rh = shift;
+ my $text = <$rh>;
+ close($rh);
+
+ Irssi::input_remove($pipe_tag);
+ $pipe_tag = -1;
+
+ my $server = Irssi::server_find_tag($print_server);
+ if ($server) {
+ $server->print('', $text);
+ } else {
+ Irssi::print($text);
+ }
+
+ $lookup_waiting--;
+ host_lookup();
+}
+
+Irssi::command_bind('dns', 'cmd_dns');
+Irssi::signal_add( {
+ 'redir dns failure' => \&sig_failure,
+ 'redir dns host' => \&sig_userhost } );
+
+# vim:set sw=2 ts=8:
diff --git a/scripts/examples/Makefile.am b/scripts/examples/Makefile.am
new file mode 100644
index 0000000..c8d8c8e
--- /dev/null
+++ b/scripts/examples/Makefile.am
@@ -0,0 +1,8 @@
+scriptdir = $(datadir)/irssi/scripts
+
+script_DATA = \
+ command.pl \
+ msg-event.pl \
+ redirect.pl
+
+EXTRA_DIST = $(script_DATA)
diff --git a/scripts/examples/Makefile.in b/scripts/examples/Makefile.in
new file mode 100644
index 0000000..c6c6789
--- /dev/null
+++ b/scripts/examples/Makefile.in
@@ -0,0 +1,552 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = scripts/examples
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
+ $(top_srcdir)/m4/glibtests.m4 $(top_srcdir)/m4/libgcrypt.m4 \
+ $(top_srcdir)/m4/libotr.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/irssi-config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(scriptdir)"
+DATA = $(script_DATA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHAT_MODULES = @CHAT_MODULES@
+COMMON_LIBS = @COMMON_LIBS@
+COMMON_NOUI_LIBS = @COMMON_NOUI_LIBS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+FUZZER_LIBS = @FUZZER_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBOTR_CFLAGS = @LIBOTR_CFLAGS@
+LIBOTR_LIBS = @LIBOTR_LIBS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+OTR_CFLAGS = @OTR_CFLAGS@
+OTR_LDFLAGS = @OTR_LDFLAGS@
+OTR_LINK_FLAGS = @OTR_LINK_FLAGS@
+OTR_LINK_LIBS = @OTR_LINK_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL_CFLAGS = @PERL_CFLAGS@
+PERL_EXTRA_OPTS = @PERL_EXTRA_OPTS@
+PERL_FE_LINK_LIBS = @PERL_FE_LINK_LIBS@
+PERL_LDFLAGS = @PERL_LDFLAGS@
+PERL_LINK_FLAGS = @PERL_LINK_FLAGS@
+PERL_LINK_LIBS = @PERL_LINK_LIBS@
+PERL_MM_OPT = @PERL_MM_OPT@
+PERL_MM_PARAMS = @PERL_MM_PARAMS@
+PERL_STATIC_LIBS = @PERL_STATIC_LIBS@
+PERL_USE_LIB = @PERL_USE_LIB@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROG_LIBS = @PROG_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TEXTUI_LIBS = @TEXTUI_LIBS@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+installed_test_metadir = @installed_test_metadir@
+installed_testdir = @installed_testdir@
+irc_MODULES = @irc_MODULES@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+otr_module_lib = @otr_module_lib@
+otr_static_lib = @otr_static_lib@
+pdfdir = @pdfdir@
+perl_module_fe_lib = @perl_module_fe_lib@
+perl_module_lib = @perl_module_lib@
+perl_static_fe_lib = @perl_static_fe_lib@
+perl_static_lib = @perl_static_lib@
+perlpath = @perlpath@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sedpath = @sedpath@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+scriptdir = $(datadir)/irssi/scripts
+script_DATA = \
+ command.pl \
+ msg-event.pl \
+ redirect.pl
+
+EXTRA_DIST = $(script_DATA)
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign scripts/examples/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign scripts/examples/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-scriptDATA: $(script_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(script_DATA)'; test -n "$(scriptdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(scriptdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(scriptdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(scriptdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(scriptdir)" || exit $$?; \
+ done
+
+uninstall-scriptDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(script_DATA)'; test -n "$(scriptdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(scriptdir)'; $(am__uninstall_files_from_dir)
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(DATA)
+installdirs:
+ for dir in "$(DESTDIR)$(scriptdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-scriptDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-scriptDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ cscopelist-am ctags-am distclean distclean-generic \
+ distclean-libtool distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-scriptDATA install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+ ps ps-am tags-am uninstall uninstall-am uninstall-scriptDATA
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/scripts/examples/command.pl b/scripts/examples/command.pl
new file mode 100644
index 0000000..77a9d7f
--- /dev/null
+++ b/scripts/examples/command.pl
@@ -0,0 +1,23 @@
+# Example how to create your own /commands:
+
+# /HELLO <nick> - sends a "Hello, world!" to given nick.
+
+use Irssi;
+use strict;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = "1.00";
+%IRSSI = (
+ authors => 'Timo Sirainen',
+ name => 'command',
+ description => 'Command example',
+ license => 'Public Domain'
+);
+
+sub cmd_hello {
+ my ($data, $server, $channel) = @_;
+
+ $server->command("/msg $data Hello, world!");
+}
+
+Irssi::command_bind('hello', 'cmd_hello');
diff --git a/scripts/examples/msg-event.pl b/scripts/examples/msg-event.pl
new file mode 100644
index 0000000..53174e2
--- /dev/null
+++ b/scripts/examples/msg-event.pl
@@ -0,0 +1,41 @@
+# Example how to react on specific messages:
+
+# !reverse <text> sends back the text reversed.
+
+use Irssi;
+use strict;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = "1.00";
+%IRSSI = (
+ authors => 'Timo Sirainen',
+ name => 'msg-event',
+ description => 'Event example',
+ license => 'Public Domain'
+);
+
+sub event_privmsg {
+ # $server = server record where the message came
+ # $data = the raw data received from server, with PRIVMSGs it is:
+ # "target :text" where target is either your nick or #channel
+ # $nick = the nick who sent the message
+ # $host = host of the nick who sent the message
+ my ($server, $data, $nick, $host) = @_;
+
+ # split data to target/text
+ my ($target, $text) = $data =~ /^(\S*)\s:(.*)/;
+
+ # skip lines not beginning with !reverse
+ return if ($text !~ /!reverse (.*)/);
+ $text = $1;
+
+ if (!$server->ischannel($target)) {
+ # private message, $target contains our nick, so we'll need
+ # to change it to $nick
+ $target = $nick;
+ }
+
+ $server->command("notice $target reversed $text = ".reverse($text));
+}
+
+Irssi::signal_add('event privmsg', 'event_privmsg');
diff --git a/scripts/examples/redirect.pl b/scripts/examples/redirect.pl
new file mode 100644
index 0000000..6a7e94c
--- /dev/null
+++ b/scripts/examples/redirect.pl
@@ -0,0 +1,40 @@
+# Example how to do redirections, we'll grab the output of /WHOIS:
+
+# /RN - display real name of nick
+
+use Irssi;
+use Irssi::Irc;
+use strict;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = "1.00";
+%IRSSI = (
+ authors => 'Timo Sirainen',
+ name => 'redirect',
+ description => 'Redirection example',
+ license => 'Public Domain'
+);
+
+sub cmd_realname {
+ my ($data, $server, $channel) = @_;
+
+ # ignore all whois replies except "No such nick" or the
+ # first line of the WHOIS reply
+ $server->redirect_event('whois', 1, $data, -1, '', {
+ 'event 402' => 'event 402',
+ 'event 401' => 'event 401',
+ 'event 311' => 'redir whois',
+ '' => 'event empty' });
+
+ $server->send_raw("WHOIS :$data");
+}
+
+sub event_rn_whois {
+ my ($num, $nick, $user, $host, $empty, $realname) = split(/ +/, $_[1], 6);
+ $realname =~ s/^://;
+
+ Irssi::print("%_$nick%_ is $realname");
+}
+
+Irssi::command_bind('rn', 'cmd_realname');
+Irssi::signal_add('redir whois', 'event_rn_whois');
diff --git a/scripts/kills.pl b/scripts/kills.pl
new file mode 100644
index 0000000..50d9383
--- /dev/null
+++ b/scripts/kills.pl
@@ -0,0 +1,103 @@
+# Display kills with more understandable messages.
+# for irssi 0.7.98 by Timo Sirainen
+
+# There's one kind of nick collision this script doesn't handle - if the
+# collision is detected by the server you're connected to, it won't use
+# kill as quit reason, but "Nick collision(new)" or "..(old)". This is pretty
+# easy to understand already, happens hardly ever(?) and it can be faked
+# so I thought better not change it to kill message.
+
+# There's a pretty good explanation of (ircnet) ircd's server kills in
+# http://www.irc.org/tech_docs/ircnet/kills.html
+
+use strict;
+use Irssi;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = "1.00";
+%IRSSI = (
+ authors => 'Timo Sirainen',
+ name => 'kills',
+ description => 'Displays kills with more understandable messages',
+ license => 'Public Domain',
+ changed => 'Sun Mar 10 23:18 EET 2002'
+);
+
+Irssi::theme_register([
+ 'kill_public', '{channick $0} {chanhost $1} killed by {nick $2}$3 {reason $4}'
+]);
+
+sub msg_quit {
+ my ($server, $nick, $addr, $data) = @_;
+
+ my $localkill;
+ if ($data =~ /^Killed \(([^ ]*) \((.*)\)\)$/) {
+ # remote kill
+ $localkill = 0;
+ } elsif ($data =~ /^Local Kill by ([^ ]*) \((.*)\)/) {
+ # local kill
+ $localkill = 1;
+ } else {
+ return;
+ }
+
+ my $killer = $1;
+ my $killmsg = $2;
+ my $msg = "\002Nick collision\002: ";
+
+ my @printargs = ();
+ if ($killmsg =~ /([^ ]*) != (.*)/) {
+ # 1 != 2
+ my $server1 = $1, my $server2 = $2;
+
+ $server1 =~ s/([^\[]*)\[([^\]]*)\]/\1/;
+ $msg .= "$2 != $server2";
+ } elsif ($killmsg =~ /([^ ]*) <- (.*)/) {
+ # 1 <- 2
+ my $server1 = $1, my $server2 = $2;
+
+ if ($server1 =~ /^\(/) {
+ # (addr1)server1 <- (add2)server2
+ $server1 =~ s/^\(([^\)]*)\)//;
+ my $nick1 = $1;
+ $server2 =~ s/^\(([^\)]*)\)//;
+ my $nick2 = $1;
+
+ $msg .= "server $server1";
+ $msg .= " (nick from $nick1)" if $nick1;
+ $msg .= " <- ";
+ $msg .= "\002$server2\002";
+ $msg .= " (nick from \002$nick2\002)" if $nick2;
+ } elsif ($server1 =~ /\)$/ || $server2 =~ /\)$/) {
+ # server1(nick) <- server2
+ # server1 <- server2(nick)
+ $server1 =~ s/\(([^\)]*)\)$//;
+ my $oldnick = $1;
+ $server2 =~ s/\(([^\)]*)\)$//;
+ $oldnick = $1 if $1;
+ $msg = "\002Nick change collision\002: $server1 <- \002$server2\002 (old nick \002$oldnick\002)";
+ } else {
+ # server1 <- server2
+ $msg = "\002Nick/server collision\002: $server1 <- \002$server2\002";
+ }
+ } else {
+ # something else, just show it as-is
+ $msg = $killmsg;
+ }
+
+ my @list = $server->nicks_get_same($nick);
+ while (@list) {
+ my $channel = $list[0];
+ shift @list;
+ # skip nick record
+ shift @list;
+
+ $channel->printformat(MSGLEVEL_QUITS, 'kill_public',
+ $nick, $addr, $killer,
+ $localkill ? " (local)" : "", $msg);
+ }
+
+ Irssi::signal_stop();
+}
+
+Irssi::signal_add('message quit', 'msg_quit');
diff --git a/scripts/mail.pl b/scripts/mail.pl
new file mode 100644
index 0000000..23f99c0
--- /dev/null
+++ b/scripts/mail.pl
@@ -0,0 +1,416 @@
+use strict;
+use vars qw($VERSION %IRSSI);
+$VERSION = "2.92";
+%IRSSI = (
+ authors => "Timo Sirainen, Matti Hiljanen, Joost Vunderink, Bart Matthaei",
+ contact => "tss\@iki.fi, matti\@hiljanen.com, joost\@carnique.nl, bart\@dreamflow.nl",
+ name => "mail",
+ description => "Fully customizable mail counter statusbar item with multiple mailbox and multiple Maildir support",
+ sbitems => "mail",
+ license => "Public Domain",
+ url => "http://irssi.org, http://scripts.irssi.de",
+);
+
+# Mail counter statusbar item
+# for irssi 0.8.1 by Timo Sirainen
+#
+# Maildir support added by Matti Hiljanen
+# Multiple Maildir/mbox and customization support added by Joost Vunderink
+# OLD mailtreatment switch added by Bart Matthaei.
+# Improved some regexps in maildirmode by Bart Matthaei.
+# Maildirmode regexps (hopefully) fixed for good by Matti Hiljanen.
+#
+# You can add any number of mailboxes or Maildirs to watch for new mail in.
+# Give them any name and <name>:<count> will appear in your mail
+# statusbar item, where <count> is the number of unread messages.
+# If only 1 mailbox/Maildir is defined, the statusbar item will have the
+# familiar form [Mail: <count>].
+# If you set mail_show_message to ON, irssi will print a message in the
+# active window whenever new mail arrives.
+#
+# Check /mailbox help for help.
+
+use Irssi::TextUI;
+use Irssi;
+
+my $maildirmode = 0; # maildir=1, file(spools)=0
+my $old_is_not_new = 0;
+my $extprog;
+my ($last_refresh_time, $refresh_tag);
+
+# for mbox caching
+my ($last_size, $last_mtime, $last_mailcount, $last_mode);
+
+# list of mailboxes
+my %mailboxes = ();
+my %new_mails_in_box = ();
+my $nummailboxes = 0;
+
+# the string to be stored in Irssi's mail_mailboxes setting
+my $mailboxsetting = "";
+
+sub cmd_print_help {
+ Irssi::print(
+ "MAILBOX ADD <num> <file|dir>\n".
+ "MAILBOX DEL <num>\n".
+ "MAILBOX SHOW\n\n".
+ "Statusbar item to keep track of how many (new) emails there are in ".
+ "each of your mailboxes/Maildirs.\n\n".
+ "/MAILBOX ADD <name> <file|dir>\n".
+ " - Adds a mailbox or a Maildir to the list.\n".
+ "/MAILBOX DEL <name>\n".
+ " - Removes mailbox or Maildir named <name> from the list.\n".
+ "/MAILBOX SHOW\n".
+ " - Shows a list of the defined mailboxes.\n\n".
+ "Use the following commands to change the behaviour:\n\n".
+ "/SET MAILDIRMODE on|off\n".
+ " - If maildirmode is on, the mailboxes in the list are assumed to be ".
+ "directories. Otherwise they are assumed to be spool files.\n".
+ " Default: off.\n".
+ "/SET MAIL_OLDNOTNEW on|off\n".
+ " - If switched on, mail marked als \"OLD\" will not be treated as new.\n".
+ " Default: off.\n".
+ "/SET MAIL_EXT_PROGRAM <prog>\n".
+ " - <prog> will be used to check for mail.\n".
+ "/SET MAIL_REFRESH_TIME <num>\n".
+ " - Sets the time between checks to <num> seconds.\n Default: 60.\n".
+ "/SET MAIL_SHOW_MESSAGE on|off\n".
+ " - If this is on, a message will be printed in the active window ".
+ "whenever new email is received.\n Default: off.\n".
+ "/SET MAIL_SHOW_ONLY_UNREAD on|off\n".
+ " - If you don't want to see a mailbox if it does not contain any new ".
+ "mail, set this to on.\n Default: on.\n" .
+ "/SET MAIL_SEPARATOR <char>\n".
+ " - Sets the character to be printed between each mailbox.\n".
+ " The default is a comma.\n".
+ "/SET MAIL_FORMAT <format>\n".
+ " - Sets the format of each mailbox.\n".
+ " Allowed variables:\n".
+ " %%n = mailbox name\n".
+ " %%u = number of unread mail\n".
+ " %%r = number of read mail\n".
+ " %%t = total amount of mail\n".
+ " The default format is %%n:%%u/%%t.\n".
+ "\nSee also: STATUSBAR"
+ ,MSGLEVEL_CRAP);
+}
+
+sub mbox_count {
+ my $mailfile = shift;
+ my $unread = 0;
+ my $read = 0;
+ my $maildirmode=Irssi::settings_get_bool('maildir_mode');
+ my $old_is_not_new=Irssi::settings_get_bool('mail_oldnotnew');
+
+ if ($extprog ne "") {
+ my $total = `$extprog`;
+ chomp $total;
+ ($read, $unread) = split ' ', $total, 2;
+ } else {
+ if (!$maildirmode) {
+ if (-f $mailfile) {
+ my @stat = stat($mailfile);
+ my $size = $stat[7];
+ my $mtime = $stat[9];
+
+ # if the file hasn't changed, get the count from cache
+ return $last_mailcount if ($last_size == $size && $last_mtime == $mtime);
+ $last_size = $size;
+ $last_mtime = $mtime;
+
+ return 0 if (!open(my $f, "<", $mailfile));
+
+ # count new mails only
+ my $internal_removed = 0;
+ while (<$f>) {
+ $unread++ if (/^From /);
+
+ if(!$old_is_not_new) {
+ $unread-- if (/^Status: R/);
+ } else {
+ $unread-- if (/^Status: [OR]/);
+ }
+
+ $read++ if (/^From /);
+
+ # Remove folder internal data, but only once
+ if (/^Subject: .*FOLDER INTERNAL DATA/) {
+ if ($internal_removed == 0) {
+ $internal_removed = 1;
+ $read--;
+ $unread--;
+ }
+ }
+ }
+ close($f);
+ }
+ } else {
+ opendir(DIR, "$mailfile/cur") or return 0;
+ while (defined(my $file = readdir(DIR))) {
+ next if $file =~ /^(.|..)$/;
+ # Maildir flags: http://cr.yp.to/proto/maildir.html
+ # My old regexps were useless if the MUA added any
+ # non-default flags -qvr
+ #
+ # deleted mail
+ next if $file =~ /\:.*?T.*?$/;
+ if($old_is_not_new) {
+ # when mail gets moved from new to cur it's name _always_
+ # changes from uniq to uniq:info, even when it's still not
+ # read. I assume "old mail" means mail which hasn't been read
+ # yet but it has been "acknowledged" by the user. (it's been
+ # moved to cur) -qvr
+ if ($file =~ /\:.*?$/) {
+ $read++;
+ next;
+ }
+ } else {
+ if ($file =~ /\:.*?S.*?$/) {
+ $read++;
+ next;
+ }
+ }
+ $unread++;
+ }
+ closedir(DIR);
+
+ opendir(DIR, "$mailfile/new") or return 0;
+ while (defined(my $file = readdir(DIR))) {
+ next if $file =~ /^(.|..)$/;
+ $unread++;
+ }
+ closedir(DIR);
+ }
+ }
+
+ if ($unread eq "" || $unread < 0) {
+ $unread = 0;
+ }
+ if ($read eq "" || $read < 0) {
+ $read = 0;
+ }
+
+ $last_mailcount = $unread;
+
+ return ($unread, $read);
+}
+
+# Checks for mail and sets the statusbar item to the right string.
+# Also shows a message in the active window if that setting is set.
+sub mail {
+ my ($item, $get_size_only) = @_;
+
+ my $result;
+ my $format = Irssi::settings_get_str('mail_format');
+ my $unread = 0;
+ my $read = 0;
+ my $total = 0;
+
+ # check all mailboxes for new email
+ foreach my $name (keys(%mailboxes)) {
+ my $box = $mailboxes{$name};
+ # replace "~/" at the beginning by the user's home dir
+ $box =~ s/^~\//$ENV{'HOME'}\//;
+
+ ($unread, $read) = mbox_count($box);
+ $unread = "0" if ($unread eq "");
+ $read = "0" if ($read eq "");
+ $total = $unread + $read;
+ $total = "0" if ($total eq "");
+
+ next if (Irssi::settings_get_bool('mail_show_only_unread') && $unread == 0);
+
+ if ($total eq "") { $total = 0; }
+ if (length($result) > 0) {
+ $result .= Irssi::settings_get_str('mail_separator');
+ }
+ my $string = $format;
+ $string =~ s/%n/$name/;
+ $string =~ s/%u/$unread/;
+ $string =~ s/%r/$read/;
+ $string =~ s/%t/$total/;
+ $result .= $string;
+
+ # Show -!- You have <num> new messages in <name>.
+ # Show this only if there are any new, unread messages.
+ if (Irssi::settings_get_bool('mail_show_message') &&
+ $unread > $new_mails_in_box{$name}) {
+ my $new_mails = $unread - $new_mails_in_box{$name};
+ if ($nummailboxes == 1) {
+ Irssi::print("You have $new_mails new message" . ($new_mails != 1 ? "s." : "."), MSGLEVEL_CRAP);
+ } else {
+ Irssi::print("You have $new_mails new message" . ($new_mails != 1 ? "s " : " ") . "in $name.", MSGLEVEL_CRAP);
+ }
+ }
+
+ $new_mails_in_box{$name} = $unread;
+ }
+
+ if (length($result) == 0) {
+ # no mail - don't print the [Mail: ] at all
+ if ($get_size_only) {
+ $item->{min_size} = $item->{max_size} = 0;
+ }
+ } else {
+ $item->default_handler($get_size_only, undef, $result, 1);
+ }
+}
+
+sub refresh_mail {
+ Irssi::statusbar_items_redraw('mail');
+}
+
+# Adds the mailboxes from a string. Only to be used during startup.
+sub add_mailboxes {
+ my $boxstring = $_[0];
+ my @boxes = split(/,/, $boxstring);
+
+ foreach my $dbox(@boxes) {
+ my $name = substr($dbox, 0, index($dbox, '='));
+ my $box = substr($dbox, index($dbox, '=') + 1, length($dbox));
+ addmailbox($name, $box);
+ }
+}
+
+sub addmailbox {
+ my ($name, $box) = @_;
+
+ if (exists($mailboxes{$name})) {
+ if ($box eq $mailboxes{$name}) {
+ Irssi::print("Mailbox $name already set to $box", MSGLEVEL_CRAP);
+ } else {
+ Irssi::print("Mailbox $name changed to $box", MSGLEVEL_CRAP);
+ $new_mails_in_box{$name} = 0;
+ }
+ } else {
+ Irssi::print("Mailbox $name added: " . $box, MSGLEVEL_CRAP);
+ $new_mails_in_box{$name} = 0;
+ $nummailboxes++;
+ }
+ $mailboxes{$name} = $box;
+}
+
+sub delmailbox {
+ my $name = $_[0];
+
+ if (exists($mailboxes{$name})) {
+ Irssi::print("Mailbox $name removed", MSGLEVEL_CRAP);
+ delete($mailboxes{$name});
+ delete($new_mails_in_box{$name});
+ $nummailboxes--;
+ } else {
+ Irssi::print("No such mailbox $name. Use /mailbox show to see a list.", MSGLEVEL_CRAP);
+ }
+}
+
+sub update_settings_string {
+ my $setting;
+
+ foreach my $name (keys(%mailboxes)) {
+ $setting .= $name . "=" . $mailboxes{$name} . ",";
+ }
+
+ Irssi::settings_set_str("mail_mailboxes", $setting);
+}
+
+sub cmd_addmailbox {
+ my ($name, $box) = split(/ +/, $_[0]);
+
+ if ($name eq "" || $box eq "") {
+ Irssi::print("Use /mailbox add <name> <mailbox> to add a mailbox.", MSGLEVEL_CRAP);
+ return;
+ }
+
+ addmailbox($name, $box);
+ update_settings_string();
+ refresh_mail();
+}
+
+sub cmd_delmailbox {
+ my $name = $_[0];
+
+ if ($name eq "") {
+ Irssi::print("Use /mailbox del <name> to delete a mailbox.", MSGLEVEL_CRAP);
+ return;
+ }
+
+ delmailbox($name);
+ update_settings_string();
+ refresh_mail();
+}
+
+sub cmd_showmailboxes {
+ if ($nummailboxes == 0) {
+ Irssi::print("No mailboxes defined.", MSGLEVEL_CRAP);
+ return;
+ }
+ Irssi::print("Mailboxes:", MSGLEVEL_CRAP);
+ foreach my $box (keys(%mailboxes)) {
+ Irssi::print("$box: " . $mailboxes{$box}, MSGLEVEL_CRAP);
+ }
+}
+
+sub cmd_mailboxes {
+ my ($data, $server, $item) = @_;
+ if ($data =~ m/^[(show)|(add)|(del)]/i ) {
+ Irssi::command_runsub ('mailbox', $data, $server, $item);
+ }
+ else {
+ Irssi::print("Use /mailbox (show|add|del).")
+ }
+}
+
+sub init_mailboxes {
+ # Add the mailboxes at startup of the script
+ my $boxes = Irssi::settings_get_str('mail_mailboxes');
+ if (length($boxes) > 0) {
+ add_mailboxes($boxes);
+ }
+}
+
+sub read_settings {
+ $extprog = Irssi::settings_get_str('mail_ext_program');
+ my $time = Irssi::settings_get_int('mail_refresh_time');
+ my $mode = Irssi::settings_get_bool('maildir_mode');
+ unless ($time == $last_refresh_time) {
+ $last_refresh_time = $time;
+ Irssi::timeout_remove($refresh_tag) if ($refresh_tag);
+ $refresh_tag = Irssi::timeout_add($time*1000, 'refresh_mail', undef);
+ }
+ return if ($mode == $last_mode);
+ $last_mode = $mode;
+ refresh_mail;
+}
+
+
+if (!$maildirmode) {
+ my $default = "1=" . $ENV{'MAIL'} . ",";
+ Irssi::settings_add_str('misc', 'mail_mailboxes', $default);
+} else {
+ my $default = "1=~/Maildir/,";
+ Irssi::settings_add_str('misc', 'mail_mailboxes', $default);
+}
+
+Irssi::command_bind('mailbox show', 'cmd_showmailboxes');
+Irssi::command_bind('mailbox add', 'cmd_addmailbox');
+Irssi::command_bind('mailbox del', 'cmd_delmailbox');
+Irssi::command_bind('mailbox help', 'cmd_print_help');
+Irssi::command_bind('mailbox', 'cmd_mailboxes');
+
+Irssi::settings_add_str('misc', 'mail_ext_program', '');
+Irssi::settings_add_int('misc', 'mail_refresh_time', 60);
+Irssi::settings_add_bool('misc', 'maildir_mode', "$maildirmode");
+Irssi::settings_add_bool('misc', 'mail_oldnotnew', "$old_is_not_new");
+Irssi::settings_add_str('misc', 'mail_separator', ",");
+Irssi::settings_add_bool('misc', 'mail_show_message', "0");
+Irssi::settings_add_str('misc', 'mail_format', '%n:%u/%t');
+Irssi::settings_add_bool('misc', 'mail_show_only_unread', "1");
+
+Irssi::statusbar_item_register('mail', '{sb Mail: $0-}', 'mail');
+
+read_settings();
+init_mailboxes();
+Irssi::signal_add('setup changed', 'read_settings');
+refresh_mail();
+
+# EOF
diff --git a/scripts/meson.build b/scripts/meson.build
new file mode 100644
index 0000000..072ac3e
--- /dev/null
+++ b/scripts/meson.build
@@ -0,0 +1,14 @@
+install_data(
+ files(
+ 'autoop.pl',
+ 'autorejoin.pl',
+ 'buf.pl',
+ 'dns.pl',
+ 'kills.pl',
+ 'mail.pl',
+ 'mlock.pl',
+ 'quitmsg.pl',
+ 'scriptassist.pl',
+ 'usercount.pl',
+ ),
+ install_dir : scriptdir)
diff --git a/scripts/mlock.pl b/scripts/mlock.pl
new file mode 100644
index 0000000..bf2fd00
--- /dev/null
+++ b/scripts/mlock.pl
@@ -0,0 +1,135 @@
+# /MLOCK <channel> <mode>
+#
+# Locks the channel mode to <mode>, if someone else tries to change the mode
+# Irssi will automatically change it back. +k and +l are a bit special since
+# they require the parameter. If you omit the parameter, like setting the
+# mode to "+ntlk", Irssi will allow all +k and +l (or -lk) mode changes.
+# You can remove the lock with /MODE #channel -
+
+use Irssi;
+use Irssi::Irc;
+use strict;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = "1.00";
+%IRSSI = (
+ authors => 'Timo Sirainen',
+ name => 'mlock',
+ description => 'Channel mode locking',
+ license => 'Public Domain',
+ changed => 'Sun Mar 10 23:18 EET 2002'
+);
+
+my %keep_channels;
+
+sub cmd_mlock {
+ my ($data, $server) = @_;
+ my ($channel, $mode) = split(/ /, $data, 2);
+
+ if ($mode eq "-") {
+ # remove checking
+ delete $keep_channels{$channel};
+ } else {
+ $keep_channels{$channel} = $mode;
+ mlock_check_mode($server, $channel);
+ }
+}
+
+sub mlock_check_mode {
+ my ($server, $channame) = @_;
+
+ my $channel = $server->channel_find($channame);
+ return if (!$channel || !$channel->{chanop});
+
+ my $keep_mode = $keep_channels{$channame};
+ return if (!$keep_mode);
+
+ # old channel mode
+ my ($oldmode, $oldkey, $oldlimit);
+ $oldmode = $channel->{mode};
+ $oldmode =~ s/^([^ ]*).*/\1/;
+ $oldkey = $channel->{key};
+ $oldlimit = $channel->{limit};
+
+ # get the new channel key/limit
+ my (@newmodes, $newkey, $limit);
+ @newmodes = split(/ /, $keep_mode); $keep_mode = $newmodes[0];
+ if ($keep_mode =~ /k/) {
+ if ($keep_mode =~ /k.*l/) {
+ $newkey = $newmodes[1];
+ $limit = $newmodes[2];
+ } elsif ($keep_mode =~ /l.*k/) {
+ $limit = $newmodes[1];
+ $newkey = $newmodes[2];
+ } else {
+ $newkey = $newmodes[1];
+ }
+ } elsif ($keep_mode =~ /l/) {
+ $limit = $newmodes[1];
+ }
+
+ # check the differences
+ my %allmodes;
+ $keep_mode =~ s/^\+//;
+ for (my $n = 0; $n < length($keep_mode); $n++) {
+ my $modechar = substr($keep_mode, $n, 1);
+ $allmodes{$modechar} = '+';
+ }
+
+ for (my $n = 0; $n < length($oldmode); $n++) {
+ my $modechar = substr($oldmode, $n, 1);
+
+ if ($allmodes{$modechar} eq '+') {
+ next if (($modechar eq "k" && $newkey ne $oldkey) ||
+ ($modechar eq "l" && $limit != $oldlimit));
+ delete $allmodes{$modechar};
+ } else {
+ $allmodes{$modechar} = '-';
+ }
+ }
+
+ # create the mode change string
+ my ($modecmd, $extracmd);
+ foreach my $mode (keys %allmodes) {
+ Irssi::print("key = '$mode':".$allmodes{$mode});
+ if ($mode eq "k") {
+ if ($allmodes{$mode} eq '+') {
+ next if ($newkey eq "");
+ if ($oldkey ne "") {
+ # we need to get rid of old key too
+ $modecmd .= "-k";
+ $extracmd .= " $oldkey";
+ }
+ $extracmd .= " $newkey";
+ } else {
+ $extracmd .= " $oldkey";
+ }
+ }
+ if ($mode eq "l" && $allmodes{$mode} eq '+') {
+ next if ($limit <= 0);
+ $extracmd .= " $limit";
+ }
+ $modecmd .= $allmodes{$mode}.$mode;
+ }
+
+ if ($modecmd ne "") {
+ $channel->{server}->command("/mode $channame $modecmd$extracmd");
+ }
+}
+
+sub mlock_mode_changed {
+ my ($server, $data) = @_;
+ my ($channel, $mode) = split(/ /, $data, 2);
+
+ mlock_check_mode($server, $channel);
+}
+
+sub mlock_synced {
+ my $channel = $_[0];
+
+ mlock_check_mode($channel->{server}, $channel->{name});
+}
+
+Irssi::command_bind('mlock', 'cmd_mlock');
+Irssi::signal_add_last("event mode", "mlock_mode_changed");
+Irssi::signal_add("channel synced", "mlock_synced");
diff --git a/scripts/quitmsg.pl b/scripts/quitmsg.pl
new file mode 100644
index 0000000..102d9aa
--- /dev/null
+++ b/scripts/quitmsg.pl
@@ -0,0 +1,36 @@
+# If quit message isn't given, quit with a random message
+# read from ~/.irssi/irssi.quit
+
+use Irssi;
+use Irssi::Irc;
+use strict;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = "1.01";
+%IRSSI = (
+ authors => 'Timo Sirainen',
+ name => 'quitmsg',
+ description => 'Random quit messages',
+ license => 'Public Domain',
+ changed => 'Mon Jul 22 20:00 EET 2020'
+);
+
+my $quitfile = Irssi::get_irssi_dir() . "/irssi.quit";
+
+sub cmd_quit {
+ my ($data, $server, $channel) = @_;
+ return if ($data ne "");
+
+ open (my $fh, "<", $quitfile) || return;
+ my @lines = <$fh>;
+
+ my $quitmsg = $lines[int(rand(@lines))];
+ chomp($quitmsg);
+ close($fh);
+
+ foreach my $server (Irssi::servers) {
+ $server->command("/disconnect ".$server->{tag}." $quitmsg");
+ }
+}
+
+Irssi::command_bind('quit', 'cmd_quit');
diff --git a/scripts/scriptassist.pl b/scripts/scriptassist.pl
new file mode 100644
index 0000000..5cad383
--- /dev/null
+++ b/scripts/scriptassist.pl
@@ -0,0 +1,1265 @@
+# by Stefan "tommie" Tomanek
+#
+# scriptassist.pl
+
+
+use strict;
+
+our $VERSION = '2022053100';
+our %IRSSI = (
+ authors => 'Stefan \'tommie\' Tomanek',
+ contact => 'stefan@pico.ruhr.de',
+ name => 'scriptassist',
+ description => 'keeps your scripts on the cutting edge',
+ license => 'GPLv2',
+ url => 'https://scripts.irssi.org/',
+ modules => 'CPAN::Meta::YAML LWP::Protocol::https (GnuPG)',
+ commands => "scriptassist"
+);
+
+our ($forked, %remote_db, $have_gpg, @complist);
+
+use Irssi 20020324;
+use CPAN::Meta::YAML;
+use LWP::UserAgent;
+use POSIX;
+use version;
+
+# GnuPG is not always needed
+$have_gpg = 0;
+eval "use GnuPG qw(:algo :trust);";
+$have_gpg = 1 if not ($@);
+
+my $irssi_version = qv('v'.Irssi::parse_special('$J') =~ s/[^.\d].*//r);
+
+sub show_help {
+ my $help = "scriptassist $VERSION
+/scriptassist check
+ Check all loaded scripts for new available versions
+/scriptassist update <script|all>
+ Update the selected or all script to the newest version
+/scriptassist search <query>
+ Search the script database
+/scriptassist info <scripts>
+ Display information about <scripts>
+/scriptassist ratings <scripts|all>
+ Retrieve the average ratings of the the scripts
+/scriptassist top <num>
+ Retrieve the first <num> top rated scripts
+/scriptassist new <num>
+ Display the newest <num> scripts
+/scriptassist rate <script>
+ Rate the script if you like it
+/scriptassist contact <script>
+ Write an email to the author of the script
+ (Requires OpenURL)
+/scriptassist cpan <module>
+ Visit CPAN to look for missing Perl modules
+ (Requires OpenURL)
+/scriptassist install <script>
+ Retrieve and load the script
+/scriptassist autorun <script>
+ Toggles automatic loading of <script>
+";
+ my $text='';
+ foreach (split(/\n/, $help)) {
+ $_ =~ s/^\/(.*)$/%9\/$1%9/;
+ $text .= $_."\n";
+ }
+ print CLIENTCRAP &draw_box("ScriptAssist", $text, "scriptassist help", 1);
+ #theme_box("ScriptAssist", $text, "scriptassist help", 1);
+}
+
+sub theme_box {
+ my ($title, $text, $footer, $colour) = @_;
+ Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'box_header', $title);
+ foreach (split(/\n/, $text)) {
+ Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'box_inside', $_);
+ }
+ Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'box_footer', $footer);
+}
+
+sub draw_box {
+ my ($title, $text, $footer, $colour) = @_;
+ my $box = '';
+ $box .= '%R,--[%n%9%U'.$title.'%U%9%R]%n'."\n";
+ foreach (split(/\n/, $text)) {
+ $box .= '%R|%n '.$_."\n";
+ }
+ $box .= '%R`--<%n'.$footer.'%R>->%n';
+ $box =~ s/%.//g unless $colour;
+ return $box;
+}
+
+sub call_openurl {
+ my ($url) = @_;
+ # check for a loaded openurl
+ if (my $code = Irssi::Script::openurl::->can('launch_url')) {
+ $code->($url);
+ } else {
+ print CLIENTCRAP "%R>>%n Please install openurl.pl";
+ print CLIENTCRAP "%R>>%n or open < $url > manually";
+ }
+}
+
+sub bg_do {
+ my ($func) = @_;
+ my ($rh, $wh);
+ pipe($rh, $wh);
+ if ($forked) {
+ print CLIENTCRAP "%R>>%n Please wait until your earlier request has been finished.";
+ return;
+ }
+ my $pid = fork();
+ $forked = 1;
+ if ($pid > 0) {
+ print CLIENTCRAP "%R>>%n Please wait...";
+ close $wh;
+ Irssi::pidwait_add($pid);
+ my $pipetag;
+ my @args = ($rh, \$pipetag, $func);
+ $pipetag = Irssi::input_add(fileno($rh), INPUT_READ, \&pipe_input, \@args);
+ } else {
+ eval {
+ my @items = split(/ /, $func);
+ my %result;
+ my $ts1 = $remote_db{timestamp};
+ my $xml = get_scripts();
+ my $ts2 = $remote_db{timestamp};
+ if (not($ts1 eq $ts2) && Irssi::settings_get_bool('scriptassist_cache_sources')) {
+ $result{db} = $remote_db{db};
+ $result{timestamp} = $remote_db{timestamp};
+ }
+ if ($items[0] eq 'check') {
+ $result{data}{check} = check_scripts($xml);
+ } elsif ($items[0] eq 'update') {
+ shift(@items);
+ $result{data}{update} = update_scripts(\@items, $xml);
+ } elsif ($items[0] eq 'search') {
+ shift(@items);
+ foreach (@items) {
+ $result{data}{search}{$_} = search_scripts($_, $xml);
+ }
+ } elsif ($items[0] eq 'install') {
+ shift(@items);
+ $result{data}{install} = install_scripts(\@items, $xml);
+ } elsif ($items[0] eq 'debug') {
+ shift(@items);
+ $result{data}{debug} = debug_scripts(\@items);
+ } elsif ($items[0] eq 'ratings') {
+ shift(@items);
+ @items = @{ loaded_scripts() } if $items[0] eq "all";
+ my %ratings = %{ get_ratings(\@items, '') };
+ foreach (keys %ratings) {
+ $result{data}{rating}{$_}{rating} = $ratings{$_}->[0];
+ $result{data}{rating}{$_}{votes} = $ratings{$_}->[1];
+ }
+ } elsif ($items[0] eq 'rate') {
+ $result{data}{rate}{$items[1]} = rate_script($items[1], $items[2]);
+ } elsif ($items[0] eq 'info') {
+ shift(@items);
+ $result{data}{info} = script_info(\@items);
+ } elsif ($items[0] eq 'echo') {
+ $result{data}{echo} = 1;
+ } elsif ($items[0] eq 'top') {
+ my %ratings = %{ get_ratings([], $items[1]) };
+ foreach (keys %ratings) {
+ $result{data}{rating}{$_}{rating} = $ratings{$_}->[0];
+ $result{data}{rating}{$_}{votes} = $ratings{$_}->[1];
+ }
+ } elsif ($items[0] eq 'new') {
+ my $new = get_new($items[1]);
+ $result{data}{new} = $new;
+ } elsif ($items[0] eq 'unknown') {
+ my $cmd = $items[1];
+ $result{data}{unknown}{$cmd} = get_unknown($cmd, $xml);
+ }
+ my $yaml = CPAN::Meta::YAML->new(\%result);
+ my $data = $yaml->write_string();
+ print($wh $data);
+ };
+ if ($@) {
+ print($wh CPAN::Meta::YAML->new(+{data=>+{error=>$@}})
+ ->write_string());
+ }
+ close($wh);
+ POSIX::_exit(1);
+ }
+}
+
+sub get_unknown {
+ my ($cmd, $db) = @_;
+ foreach (keys %$db) {
+ next unless defined $db->{$_}{commands};
+ foreach my $item (split / /, $db->{$_}{commands}) {
+ return { $_ => +{%{$db->{$_}}} } if ($item =~ /^$cmd$/i);
+ }
+ }
+ return undef;
+}
+
+sub get_names {
+ my ($sname, $db) = shift;
+ $sname =~ s/\s+$//;
+ $sname =~ s/\.pl$//;
+ my $plname = "$sname.pl";
+ $sname =~ s/^.*\///;
+ my $xname = $sname;
+ $xname =~ s/\W/_/g;
+ my $pname = "${xname}::";
+ if ($xname ne $sname || $sname =~ /_/) {
+ my $dir = Irssi::get_irssi_dir()."/scripts/";
+ if ($db && exists $db->{"$sname.pl"}) {
+ # $found = 1;
+ } elsif (-e $dir.$plname || -e $dir."$sname.pl" || -e $dir."autorun/$sname.pl") {
+ # $found = 1;
+ } else {
+ # not found
+ my $pat = $xname; $pat =~ y/_/?/;
+ my $re = "\Q$xname"; $re =~ s/\Q_/./g;
+ if ($db) {
+ my ($cand) = grep /^$re\.pl$/, sort keys %$db;
+ if ($cand) {
+ return get_names($cand, $db);
+ }
+ }
+ my ($cand) = glob "'$dir$pat.pl' '${dir}autorun/$pat.pl'";
+ if ($cand) {
+ $cand =~ s/^.*\///;
+ return get_names($cand, $db);
+ }
+ }
+ }
+ ($sname, $plname, $pname, $xname)
+}
+
+sub script_info {
+ my ($scripts) = @_;
+ my %result;
+ my $xml = get_scripts();
+ foreach (@{$scripts}) {
+ my ($sname, $plname, $pname) = get_names($_, $xml);
+ next unless (defined $xml->{$plname} || ( exists $Irssi::Script::{$pname} && exists $Irssi::Script::{$pname}{IRSSI} ));
+ $result{$sname}{version} = get_remote_version($sname, $xml);
+ my @headers = ('authors', 'contact', 'description', 'license', 'source');
+ foreach my $entry (@headers) {
+ $result{$sname}{$entry} = $Irssi::Script::{$pname}{IRSSI}{$entry};
+ if (defined $xml->{$plname}{$entry}) {
+ $result{$sname}{$entry} = $xml->{$plname}{$entry};
+ }
+ }
+ if ($xml->{$plname}{signature_available}) {
+ $result{$sname}{signature_available} = 1;
+ }
+ if (defined $xml->{$plname}{modules}) {
+ my $modules = $xml->{$plname}{modules};
+ foreach my $mod (split(/ /, $modules)) {
+ my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
+ $mod = $1 if $1;
+ $result{$sname}{modules}{$mod}{optional} = $opt;
+ $result{$sname}{modules}{$mod}{installed} = module_exist($mod);
+ }
+ } elsif (defined $Irssi::Script::{$pname}{IRSSI}{modules}) {
+ my $modules = $Irssi::Script::{$pname}{IRSSI}{modules};
+ foreach my $mod (split(/ /, $modules)) {
+ my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
+ $mod = $1 if $1;
+ $result{$sname}{modules}{$mod}{optional} = $opt;
+ $result{$sname}{modules}{$mod}{installed} = module_exist($mod);
+ }
+ }
+ # if (defined $xml->{$plname}{depends}) {
+ # my $depends = $xml->{$plname}{depends};
+ # foreach my $dep (split(/ /, $depends)) {
+ # $result{$sname}{depends}{$dep}{installed} = 1; #(defined ${ 'Irssi::Script::'.$dep });
+ # }
+ # }
+ }
+ return \%result;
+}
+
+sub get_rate_url {
+ my ($src) = @_;
+ my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30);
+ $ua->agent('ScriptAssist/'.$VERSION);
+ my $request = HTTP::Request->new('GET', $src);
+ my $response = $ua->request($request);
+ unless ($response->is_success) {
+ my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
+ die("Fetching ratings location failed: $error");
+ }
+ my $votes_url;
+ for my $tag ($response->content() =~ /<script([^>]*)>/g) {
+ my $attr = " $tag ";
+ ($votes_url = $1) =~ s/\.\w+$/.yml/
+ if $attr =~ /\sasync\s/ && $attr =~ m{\ssrc="(https?://.*?/votes\.\w+)"\s};
+ }
+ unless ($votes_url) {
+ die("Fetching ratings failed: Could not find votes script\n");
+ }
+ $request = HTTP::Request->new('GET', $votes_url);
+ $response = $ua->request($request);
+ if (!$response->is_success) {
+ my $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
+ die("Fetching ratings failed: $error");
+ }
+ my $data = $response->content();
+ utf8::decode($data);
+ CPAN::Meta::YAML->read_string($data)->[0];
+}
+
+sub rate_script {
+ my ($script, $stars) = @_;
+ my $xml = get_scripts();
+ my $votes = get_rate_url(map { $_->{source} } values %$xml);
+ my ($sname, $plname, $pname) = get_names($script, $xml);
+ die "Script $script not found\n" unless $votes->{$plname};
+ return $votes->{$plname}{u}
+}
+
+sub get_ratings {
+ my ($scripts, $limit) = @_;
+ my $xml = get_scripts();
+ my $votes = get_rate_url(map { $_->{source} } values %$xml);
+ foreach (keys %{$votes}) {
+ if ($xml->{$_}) {
+ $xml->{$_}{votes} = $votes->{$_}{v};
+ }
+ }
+ my %result;
+ if (@{$scripts}) {
+ foreach (@{$scripts}) {
+ my ($sname, $plname, $pname) = get_names($_, $xml);
+ next unless (defined $xml->{$plname} || ( exists $Irssi::Script::{$pname} && exists $Irssi::Script::{$pname}{IRSSI} ));
+ $result{$plname} = [$xml->{$plname}{votes}];
+ }
+ } else {
+ my @keys = sort { $xml->{$b}{votes} <=> $xml->{$a}{votes}
+ || $xml->{$b}{modified} cmp $xml->{$a}{modified} }
+ grep { !$xml->{$_}{HIDDEN} && $xml->{$_}{votes} ne '' } keys %$xml;
+ foreach (splice @keys, 0, $limit) {
+ $result{$_} = [$xml->{$_}{votes}];
+ }
+ }
+ die "No such script found\n" unless keys %result;
+ return \%result;
+}
+
+sub get_new {
+ my ($num) = @_;
+ my $result;
+ my $xml = get_scripts();
+ foreach (sort {$xml->{$b}{modified} cmp $xml->{$a}{modified}} keys %$xml) {
+ my %entry = %{ $xml->{$_} };
+ next if $entry{HIDDEN};
+ $result->{$_} = \%entry;
+ $num--;
+ last unless $num;
+ }
+ return $result;
+}
+sub module_exist {
+ my ($module) = @_;
+ $module =~ s/::/\//g;
+ foreach (@INC) {
+ return 1 if (-e $_."/".$module.".pm");
+ }
+ return 0;
+}
+
+sub debug_scripts {
+ my ($scripts) = @_;
+ my %result;
+ my $xml = get_scripts();
+ foreach (@{$scripts}) {
+ my ($sname, $plname) = get_names($_, $xml);
+ if (defined $xml->{$plname}{modules}) {
+ my $modules = $xml->{$plname}{modules};
+ foreach my $mod (split(/ /, $modules)) {
+ my $opt = ($mod =~ /\((.*)\)/)? 1 : 0;
+ $mod = $1 if $1;
+ $result{$sname}{$mod}{optional} = $opt;
+ $result{$sname}{$mod}{installed} = module_exist($mod);
+ }
+ }
+ }
+ return(\%result);
+}
+
+sub install_scripts {
+ my ($scripts, $xml) = @_;
+ my %success;
+ my $dir = Irssi::get_irssi_dir()."/scripts/";
+ foreach (@{$scripts}) {
+ my ($sname, $plname, $pname) = get_names($_, $xml);
+ if (get_local_version($sname) && (-e $dir.$plname)) {
+ $success{$sname}{installed} = -2;
+ } else {
+ $success{$sname} = download_script($sname, $xml);
+ }
+ }
+ return \%success;
+}
+
+sub update_scripts {
+ my ($list, $database) = @_;
+ $list = loaded_scripts() if ($list->[0] eq "all" || scalar(@$list) == 0);
+ my %status;
+ foreach (@{$list}) {
+ my ($sname) = get_names($_, $database);
+ my $local = get_local_version($sname);
+ my $remote = get_remote_version($sname, $database);
+ next if $local eq '' || $remote eq '';
+ if (compare_versions($local, $remote) eq "older") {
+ $status{$sname} = download_script($sname, $database);
+ } else {
+ $status{$sname}{installed} = -2;
+ }
+ $status{$sname}{remote} = $remote;
+ $status{$sname}{local} = $local;
+ }
+ return \%status;
+}
+
+sub search_scripts {
+ my ($query, $database) = @_;
+ $query =~ s/\.pl\Z//;
+ my %result;
+ foreach (sort keys %{$database}) {
+ my %entry = %{$database->{$_}};
+ next if $entry{HIDDEN};
+ my $string = $_." ";
+ $string .= $entry{description} if defined $entry{description};
+ if ($string =~ /$query/i) {
+ my $name = $_;
+ $name =~ s/\.pl$//;
+ if (defined $entry{description}) {
+ $result{$name}{desc} = $entry{description};
+ } else {
+ $result{$name}{desc} = "";
+ }
+ if (defined $entry{authors}) {
+ $result{$name}{authors} = $entry{authors};
+ } else {
+ $result{$name}{authors} = "";
+ }
+ if (get_local_version($name)) {
+ $result{$name}{installed} = 1;
+ } else {
+ $result{$name}{installed} = 0;
+ }
+ }
+ }
+ return \%result;
+}
+
+sub pipe_input {
+ my ($rh, $pipetag) = @{$_[0]};
+ my $text = do { local $/; <$rh>; };
+ close($rh);
+ Irssi::input_remove($$pipetag);
+ $forked = 0;
+ unless ($text) {
+ print CLIENTCRAP "%R<<%n Something weird happend (no text)";
+ return();
+ }
+ utf8::decode($text);
+ my $incoming = CPAN::Meta::YAML->read_string($text)->[0];
+ if ($incoming->{db} && $incoming->{timestamp}) {
+ $remote_db{db} = $incoming->{db};
+ $remote_db{timestamp} = $incoming->{timestamp};
+ }
+ unless (defined $incoming->{data}) {
+ print CLIENTCRAP "%R<<%n Something weird happend (no data)";
+ return;
+ }
+ my %result = %{ $incoming->{data} };
+ @complist = ();
+ if (defined $result{new}) {
+ print_new($result{new});
+ push @complist, $_ foreach keys %{ $result{new} };
+ }
+ if (defined $result{check}) {
+ print_check(%{$result{check}});
+ push @complist, $_ foreach keys %{ $result{check} };
+ }
+ if (defined $result{update}) {
+ print_update(%{ $result{update} });
+ push @complist, $_ foreach keys %{ $result{update} };
+ }
+ if (defined $result{search}) {
+ foreach (keys %{$result{search}}) {
+ print_search($_, %{$result{search}{$_}});
+ push @complist, keys(%{$result{search}{$_}});
+ }
+ }
+ if (defined $result{install}) {
+ print_install(%{ $result{install} });
+ push @complist, $_ foreach keys %{ $result{install} };
+ }
+ if (defined $result{debug}) {
+ print_debug(%{ $result{debug} });
+ }
+ if (defined $result{rating}) {
+ print_ratings(%{ $result{rating} });
+ push @complist, $_ foreach keys %{ $result{rating} };
+ }
+ if (defined $result{rate}) {
+ print_rate(%{ $result{rate} });
+ }
+ if (defined $result{info}) {
+ print_info(%{ $result{info} });
+ }
+ if (defined $result{echo}) {
+ Irssi::print "ECHO";
+ }
+ if ($result{unknown}) {
+ print_unknown($result{unknown});
+ }
+ if (defined $result{error}) {
+ print CLIENTCRAP "%R<<%n There was an error in background processing:"; chomp($result{error});
+ print CLIENTERROR $result{error};
+ }
+
+}
+
+sub print_unknown {
+ my ($data) = @_;
+ foreach my $cmd (keys %$data) {
+ print CLIENTCRAP "%R<<%n No script provides '/$cmd'" unless $data->{$cmd};
+ foreach (keys %{ $data->{$cmd} }) {
+ my $text .= "The command '/".$cmd."' is provided by the script '".$data->{$cmd}{$_}{name}."'.\n";
+ $text .= "This script is currently not installed on your system.\n";
+ $text .= "If you want to install the script, enter\n";
+ my ($name) = get_names($_);
+ $text .= " %U/script install ".$name."%U ";
+ my $output = draw_box("ScriptAssist", $text, "'".$_."' missing", 1);
+ print CLIENTCRAP $output;
+ }
+ }
+}
+
+sub check_autorun {
+ my ($script) = @_;
+ my (undef, $plname) = get_names($script);
+ my $dir = Irssi::get_irssi_dir()."/scripts/";
+ if (-e $dir."/autorun/".$plname) {
+ if (readlink($dir."/autorun/".$plname) eq "../".$plname) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub array2table {
+ my (@array) = @_;
+ my @width;
+ foreach my $line (@array) {
+ for (0..scalar(@$line)-1) {
+ my $l = $line->[$_];
+ $l =~ s/%[^%]//g;
+ $l =~ s/%%/%/g;
+ $width[$_] = length($l) if $width[$_]<length($l);
+ }
+ }
+ my $text;
+ foreach my $line (@array) {
+ for (0..scalar(@$line)-1) {
+ my $l = $line->[$_];
+ $text .= $line->[$_];
+ $l =~ s/%[^%]//g;
+ $l =~ s/%%/%/g;
+ $text .= " "x($width[$_]-length($l)+1) unless ($_ == scalar(@$line)-1);
+ }
+ $text .= "\n";
+ }
+ return $text;
+}
+
+
+sub print_info {
+ my (%data) = @_;
+ my $line;
+ foreach my $script (sort keys(%data)) {
+ my ($local, $autorun);
+ if (get_local_version($script)) {
+ $line .= "%go%n ";
+ $local = get_local_version($script);
+ } else {
+ $line .= "%ro%n ";
+ $local = undef;
+ }
+ if (defined $local || check_autorun($script)) {
+ $autorun = "no";
+ $autorun = "yes" if check_autorun($script);
+ } else {
+ $autorun = undef;
+ }
+ $line .= "%9".$script."%9\n";
+ $line .= " Version : ".$data{$script}{version}."\n";
+ $line .= " Source : ".$data{$script}{source}."\n";
+ $line .= " Installed : ".$local."\n" if defined $local;
+ $line .= " Autorun : ".$autorun."\n" if defined $autorun;
+ $line .= " Authors : ".$data{$script}{authors};
+ $line .= " %Go-m signed%n" if $data{$script}{signature_available};
+ $line .= "\n";
+ $line .= " Contact : ".$data{$script}{contact}."\n";
+ $line .= " Description: ".$data{$script}{description}."\n";
+ $line .= "\n" if $data{$script}{modules};
+ $line .= " Needed Perl modules:\n" if $data{$script}{modules};
+
+ foreach (sort keys %{$data{$script}{modules}}) {
+ if ( $data{$script}{modules}{$_}{installed} == 1 ) {
+ $line .= " %g->%n ".$_." (found)";
+ } else {
+ $line .= " %r->%n ".$_." (not found)";
+ }
+ $line .= " <optional>" if $data{$script}{modules}{$_}{optional};
+ $line .= "\n";
+ }
+ $line .= " Needed Irssi Scripts:\n" if $data{$script}{depends};
+ foreach (sort keys %{$data{$script}{depends}}) {
+ if ( $data{$script}{depends}{$_}{installed} == 1 ) {
+ $line .= " %g->%n ".$_." (loaded)";
+ } else {
+ $line .= " %r->%n ".$_." (not loaded)";
+ }
+ $line .= "\n";
+ }
+ }
+ print CLIENTCRAP draw_box('ScriptAssist', $line, 'info', 1) ;
+}
+
+sub print_rate {
+ my (%data) = @_;
+ my $line;
+ foreach my $script (sort keys(%data)) {
+ call_openurl($data{$script});
+ }
+}
+
+sub print_ratings {
+ my (%data) = @_;
+ my @table;
+ foreach my $script (sort {$data{$b}{rating}<=>$data{$a}{rating}} keys(%data)) {
+ my @line;
+ if (get_local_version($script)) {
+ push @line, "%go%n";
+ } else {
+ push @line, "%yo%n";
+ }
+ push @line, "%9".$script."%9";
+ push @line, "[".(length $data{$script}{rating} ? $data{$script}{rating} : 'no')." votes]";
+ push @table, \@line;
+ }
+ print CLIENTCRAP draw_box('ScriptAssist', array2table(@table), 'ratings', 1) ;
+}
+
+sub print_new {
+ my ($list) = @_;
+ my @table;
+ foreach (sort {$list->{$b}{modified} cmp $list->{$a}{modified}} keys %$list) {
+ my @line;
+ my ($name) = get_names($_);
+ if (get_local_version($name)) {
+ push @line, "%go%n";
+ } else {
+ push @line, "%yo%n";
+ }
+ push @line, "%9".$name."%9";
+ push @line, $list->{$_}{modified};
+ push @table, \@line;
+ }
+ print CLIENTCRAP draw_box('ScriptAssist', array2table(@table), 'new scripts', 1) ;
+}
+
+sub print_debug {
+ my (%data) = @_;
+ my $line;
+ foreach my $script (sort keys %data) {
+ $line .= "%ro%n %9".$script."%9 failed to load\n";
+ $line .= " Make sure you have the following perl modules installed:\n";
+ foreach (sort keys %{$data{$script}}) {
+ if ( $data{$script}{$_}{installed} == 1 ) {
+ $line .= " %g->%n ".$_." (found)";
+ } else {
+ $line .= " %r->%n ".$_." (not found)\n";
+ $line .= " [This module is optional]\n" if $data{$script}{$_}{optional};
+ $line .= " [Try /scriptassist cpan ".$_."]";
+ }
+ $line .= "\n";
+ }
+ print CLIENTCRAP draw_box('ScriptAssist', $line, 'debug', 1) ;
+ }
+}
+
+sub load_script {
+ my ($script) = @_;
+ Irssi::command('script load '.$script);
+}
+
+sub print_install {
+ my (%data) = @_;
+ my $text;
+ my ($crashed, @installed);
+ foreach my $script (sort keys %data) {
+ my $line;
+ if ($data{$script}{installed} == 1) {
+ my $hacked;
+ if ($have_gpg && Irssi::settings_get_bool('scriptassist_use_gpg')) {
+ if ($data{$script}{signed} >= 0) {
+ load_script($script) unless (lc($script) eq lc($IRSSI{name}));
+ } else {
+ $hacked = 1;
+ }
+ } else {
+ load_script($script) unless (lc($script) eq lc($IRSSI{name}));
+ }
+ if (get_local_version($script) && not lc($script) eq lc($IRSSI{name})) {
+ $line .= "%go%n %9".$script."%9 installed\n";
+ push @installed, $script;
+ } elsif (lc($script) eq lc($IRSSI{name})) {
+ $line .= "%yo%n %9".$script."%9 installed, please reload manually\n";
+ } else {
+ $line .= "%Ro%n %9".$script."%9 fetched, but unable to load\n";
+ $crashed .= $script." " unless $hacked;
+ }
+ if ($have_gpg && Irssi::settings_get_bool('scriptassist_use_gpg')) {
+ foreach (split /\n/, check_sig($data{$script})) {
+ $line .= " ".$_."\n";
+ }
+ }
+ } elsif ($data{$script}{installed} == -2) {
+ $line .= "%ro%n %9".$script."%9 already loaded, please try \"update\"\n";
+ } elsif ($data{$script}{installed} <= 0) {
+ $line .= "%ro%n %9".$script."%9 not installed\n";
+ foreach (split /\n/, check_sig($data{$script})) {
+ $line .= " ".$_."\n";
+ }
+ } else {
+ $line .= "%Ro%n %9".$script."%9 not found on server\n";
+ }
+ $text .= $line;
+ }
+ # Inspect crashed scripts
+ bg_do("debug ".$crashed) if $crashed;
+ print CLIENTCRAP draw_box('ScriptAssist', $text, 'install', 1);
+ list_sbitems(\@installed);
+}
+
+sub list_sbitems {
+ my ($scripts) = @_;
+ my $text;
+ foreach (@$scripts) {
+ next unless exists $Irssi::Script::{"${_}::"};
+ next unless exists $Irssi::Script::{"${_}::"}{IRSSI};
+ my $header = $Irssi::Script::{"${_}::"}{IRSSI};
+ next unless $header->{sbitems};
+ $text .= '%9"'.$_.'"%9 provides the following statusbar item(s):'."\n";
+ $text .= ' ->'.$_."\n" foreach (split / /, $header->{sbitems});
+ }
+ return unless $text;
+ $text .= "\n";
+ $text .= "Enter '/statusbar window add <item>' to add an item.";
+ print CLIENTCRAP draw_box('ScriptAssist', $text, 'sbitems', 1);
+}
+
+sub check_sig {
+ my ($sig) = @_;
+ my $line;
+ my %trust = ( -1 => 'undefined',
+ 0 => 'never',
+ 1 => 'marginal',
+ 2 => 'fully',
+ 3 => 'ultimate'
+ );
+ if ($sig->{signed} == 1) {
+ $line .= "Signature found from ".$sig->{sig}{user}."\n";
+ $line .= "Timestamp : ".$sig->{sig}{date}."\n";
+ $line .= "Fingerprint: ".$sig->{sig}{fingerprint}."\n";
+ $line .= "KeyID : ".$sig->{sig}{keyid}."\n";
+ $line .= "Trust : ".$trust{$sig->{sig}{trust}}."\n";
+ } elsif ($sig->{signed} == -1) {
+ $line .= "%1Warning, unable to verify signature%n\n";
+ } elsif ($sig->{signed} == 0) {
+ $line .= "%1No signature found%n\n" unless Irssi::settings_get_bool('scriptassist_install_unsigned_scripts');
+ }
+ return $line;
+}
+
+sub print_search {
+ my ($query, %data) = @_;
+ my $text;
+ foreach (sort keys %data) {
+ my $line;
+ $line .= "%go%n" if $data{$_}{installed};
+ $line .= "%yo%n" if not $data{$_}{installed};
+ $line .= " %9".$_."%9 ";
+ $line .= $data{$_}{desc};
+ $line =~ s/($query)/%U$1%U/gi;
+ $line .= ' ('.$data{$_}{authors}.')';
+ $text .= $line." \n";
+ }
+ print CLIENTCRAP draw_box('ScriptAssist', $text, 'search: '.$query, 1) ;
+}
+
+sub print_update {
+ my (%data) = @_;
+ my $text;
+ my @table;
+ my $verbose = Irssi::settings_get_bool('scriptassist_update_verbose');
+ foreach (sort keys %data) {
+ my $signed = 0;
+ if ($data{$_}{installed} == 1) {
+ my $local = $data{$_}{local};
+ my $remote = $data{$_}{remote};
+ push @table, ['%yo%n', '%9'.$_.'%9', 'upgraded ('.$local.'->'.$remote.')'];
+ foreach (split /\n/, check_sig($data{$_})) {
+ push @table, ['', '', $_];
+ }
+ if (lc($_) eq lc($IRSSI{name})) {
+ push @table, ['', '', "%R%9Please reload manually%9%n"];
+ } else {
+ load_script($_);
+ }
+ } elsif ($data{$_}{installed} == 0 || $data{$_}{installed} == -1) {
+ push @table, ['%yo%n', '%9'.$_.'%9', 'not upgraded'];
+ foreach (split /\n/, check_sig($data{$_})) {
+ push @table, ['', '', $_];
+ }
+ } elsif ($data{$_}{installed} == -2 && $verbose) {
+ my $local = $data{$_}{local};
+ push @table, ['%go%n', '%9'.$_.'%9', 'already at the latest version ('.$local.')'];
+ }
+ }
+ $text = array2table(@table);
+ print CLIENTCRAP draw_box('ScriptAssist', $text, 'update', 1) ;
+}
+
+sub contact_author {
+ my ($script) = @_;
+ my ($sname, $plname, $pname) = get_names($script);
+ return unless exists $Irssi::Script::{$pname};
+ my $header = $Irssi::Script::{$pname}{IRSSI};
+ if ($header && defined $header->{contact}) {
+ my @ads = split(/ |,/, $header->{contact});
+ my $address = $ads[0];
+ $address .= '?subject='.$script;
+ $address .= '_'.get_local_version($script) if defined get_local_version($script);
+ call_openurl($address) if $address =~ /[\@:]/;
+ }
+}
+
+sub get_scripts {
+ my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30);
+ $ua->agent('ScriptAssist/'.$VERSION);
+ $ua->env_proxy();
+ my @mirrors = split(/ /, Irssi::settings_get_str('scriptassist_script_sources'));
+ my %sites_db;
+ my $not_modified = 0;
+ my $fetched = 0;
+ my @sources;
+ my $error;
+ foreach my $site (@mirrors) {
+ my $request = HTTP::Request->new('GET', $site);
+ if ($remote_db{timestamp}) {
+ $request->if_modified_since($remote_db{timestamp});
+ }
+ my $response = $ua->request($request);
+ if ($response->code == 304) { # HTTP_NOT_MODIFIED
+ $not_modified = 1;
+ next;
+ }
+ unless ($response->is_success) {
+ $error = join "\n", $response->status_line(), (grep / at .* line \d+/, split "\n", $response->content()), '';
+ next;
+ }
+ $fetched = 1;
+ my $data = $response->content();
+ my $src = $site;
+ my $type = '';
+ if ($site =~ /(.*\/).+\.(.+)/) {
+ $src = $1;
+ $type = $2;
+ }
+ push @sources, $src;
+ #my @header = ('name', 'contact', 'authors', 'description', 'version', 'modules', 'modified');
+ if ($type eq 'dmp') {
+ die("Support for $type script database has been removed. Please /set scriptassist_script_sources and change $type -> yml.\n");
+ } elsif ($type eq 'yml') {
+ utf8::decode($data);
+ my $new_db = CPAN::Meta::YAML->read_string($data);
+ foreach (@{$new_db->[0]}) {
+ my $K = $_->{filename};
+ if (defined $sites_db{script}{$K}) {
+ my $old = $sites_db{$K}{version};
+ my $new = $_->{version};
+ next if (compare_versions($old, $new) eq 'newer');
+ }
+ #foreach my $key (@header) {
+ foreach my $key (keys %$_) {
+ next unless defined $_->{$key};
+ $sites_db{$K}{$key} = $_->{$key};
+ }
+ $sites_db{$K}{source} = $src;
+ }
+ } else {
+ die("Unknown script database type ($type).\n");
+ }
+ }
+ if ($fetched) {
+ # Clean database
+ foreach (keys %{$remote_db{db}}) {
+ foreach my $site (@sources) {
+ if ($remote_db{db}{$_}{source} eq $site) {
+ delete $remote_db{db}{$_};
+ last;
+ }
+ }
+ }
+ $remote_db{db}{$_} = $sites_db{$_} foreach (keys %sites_db);
+ $remote_db{timestamp} = time();
+ } elsif ($not_modified) {
+ # nothing to do
+ } else {
+ die("No script database sources defined in /set scriptassist_script_sources\n") unless @mirrors;
+ die("Fetching script database failed: $error") if $error;
+ die("Unknown error while fetching script database\n");
+ }
+ return $remote_db{db};
+}
+
+sub get_remote_version {
+ my ($script, $database) = @_;
+ my $plname = (get_names($script, $database))[1];
+ return $database->{$plname}{version};
+}
+
+sub get_local_version {
+ my ($script) = @_;
+ my $pname = (get_names($script))[2];
+ return unless exists $Irssi::Script::{$pname};
+ my $vref = $Irssi::Script::{$pname}{VERSION};
+ return $vref ? $$vref : undef;
+}
+
+sub compare_versions {
+ my ($ver1, $ver2) = @_;
+ for ($ver1, $ver2) {
+ $_ = "0:$_" unless /:/;
+ }
+ my @ver1 = split /[.:]/, $ver1;
+ my @ver2 = split /[.:]/, $ver2;
+ my $cmp = 0;
+ ### Special thanks to Clemens Heidinger
+ no warnings 'uninitialized';
+ $cmp ||= $ver1[$_] <=> $ver2[$_] || $ver1[$_] cmp $ver2[$_] for 0..scalar(@ver2);
+ return 'newer' if $cmp == 1;
+ return 'older' if $cmp == -1;
+ return 'equal';
+}
+
+sub loaded_scripts {
+ my @modules;
+ foreach (sort grep(s/::$//, keys %Irssi::Script::)) {
+ push @modules, $_;
+ }
+ return \@modules;
+}
+
+sub check_scripts {
+ my ($data) = @_;
+ my %versions;
+ foreach (@{loaded_scripts()}) {
+ my ($sname) = get_names($_, $data);
+ my $remote = get_remote_version($sname, $data);
+ my $local = get_local_version($sname);
+ my $state;
+ if ($local && $remote) {
+ $state = compare_versions($local, $remote);
+ } elsif ($local) {
+ $state = 'noversion';
+ $remote = '/';
+ } else {
+ $state = 'noheader';
+ $local = '/';
+ $remote = '/';
+ }
+ if ($state) {
+ $versions{$sname}{state} = $state;
+ $versions{$sname}{remote} = $remote;
+ $versions{$sname}{local} = $local;
+ }
+ }
+ return \%versions;
+}
+
+sub download_script {
+ my ($script, $xml) = @_;
+ my ($sname, $plname) = get_names($script, $xml);
+ my %result;
+ my $site = $xml->{$plname}{source};
+ $result{installed} = 0;
+ $result{signed} = 0;
+ my $dir = Irssi::get_irssi_dir();
+ my $ua = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30);
+ $ua->agent('ScriptAssist/'.2003020803);
+ my $request = HTTP::Request->new('GET', $site.'/scripts/'.$script.'.pl');
+ my $response = $ua->request($request);
+ if ($response->is_success()) {
+ my $file = $response->content();
+ mkdir $dir.'/scripts/' unless (-e $dir.'/scripts/');
+ open(my $F, '>', $dir.'/scripts/'.$plname.'.new');
+ print $F $file;
+ close($F);
+ if ($have_gpg && Irssi::settings_get_bool('scriptassist_use_gpg')) {
+ my $ua2 = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30);
+ $ua->agent('ScriptAssist/'.2003020803);
+ my $request2 = HTTP::Request->new('GET', $site.'/signatures/'.$plname.'.asc');
+ my $response2 = $ua->request($request2);
+ if ($response2->is_success()) {
+ my $sig_dir = $dir.'/scripts/signatures/';
+ mkdir $sig_dir unless (-e $sig_dir);
+ open(my $S, '>', $sig_dir.$plname.'.asc');
+ my $file2 = $response2->content();
+ print $S $file2;
+ close($S);
+ my $sig;
+ foreach (1..2) {
+ # FIXME gpg needs two rounds to load the key
+ my $gpg = new GnuPG();
+ eval {
+ $sig = $gpg->verify( file => $dir.'/scripts/'.$plname.'.new', signature => $sig_dir.$plname.'.asc' );
+ };
+ }
+ if (defined $sig->{user}) {
+ $result{installed} = 1;
+ $result{signed} = 1;
+ $result{sig}{$_} = $sig->{$_} foreach (keys %{$sig});
+ } else {
+ # Signature broken?
+ $result{installed} = 0;
+ $result{signed} = -1;
+ }
+ } else {
+ $result{signed} = 0;
+ $result{installed} = -1;
+ $result{installed} = 1 if Irssi::settings_get_bool('scriptassist_install_unsigned_scripts');
+ }
+ } else {
+ $result{signed} = 0;
+ $result{installed} = -1;
+ $result{installed} = 1 if Irssi::settings_get_bool('scriptassist_install_unsigned_scripts');
+ }
+ }
+ if ($result{installed}) {
+ my $old_dir = "$dir/scripts/old/";
+ mkdir $old_dir unless (-e $old_dir);
+ rename "$dir/scripts/$plname", "$old_dir/$plname.old" if -e "$dir/scripts/$plname";
+ rename "$dir/scripts/$plname.new", "$dir/scripts/$plname";
+ }
+ return \%result;
+}
+
+sub print_check {
+ my (%data) = @_;
+ my $text;
+ my @table;
+ foreach (sort keys %data) {
+ my $state = $data{$_}{state};
+ my $remote = $data{$_}{remote};
+ my $local = $data{$_}{local};
+ if (Irssi::settings_get_bool('scriptassist_check_verbose')) {
+ push @table, ['%go%n', '%9'.$_.'%9', 'Up to date. ('.$local.')'] if $state eq 'equal';
+ }
+ push @table, ['%mo%n', '%9'.$_.'%9', "No version information available on network."] if $state eq "noversion";
+ push @table, ['%mo%n', '%9'.$_.'%9', 'No header in script.'] if $state eq "noheader";
+ push @table, ['%bo%n', '%9'.$_.'%9', "Your version is newer (".$local."->".$remote.")"] if $state eq "newer";
+ push @table, ['%ro%n', '%9'.$_.'%9', "A new version is available (".$local."->".$remote.")"] if $state eq "older";;
+ }
+ $text = array2table(@table);
+ print CLIENTCRAP draw_box('ScriptAssist', $text, 'check', 1) ;
+}
+
+sub toggle_autorun {
+ my ($script) = @_;
+ my ($sname, $plname) = get_names($script);
+ my $dir = Irssi::get_irssi_dir()."/scripts/";
+ mkdir $dir."autorun/" unless (-e $dir."autorun/");
+ return unless (-e $dir.$plname);
+ if (-e $dir."/autorun/".$plname) {
+ if (readlink($dir."/autorun/".$plname) eq "../".$plname) {
+ if (unlink($dir."/autorun/".$plname)) {
+ print CLIENTCRAP "%R>>%n Autorun of ".$sname." disabled";
+ } else {
+ print CLIENTCRAP "%R>>%n Unable to delete link";
+ }
+ } else {
+ print CLIENTCRAP "%R>>%n ".$dir."/autorun/".$plname." is not a correct link";
+ }
+ } else {
+ if (symlink("../".$plname, $dir."/autorun/".$plname)) {
+ print CLIENTCRAP "%R>>%n Autorun of ".$sname." enabled";
+ } else {
+ print CLIENTCRAP "%R>>%n Unable to create autorun link";
+ }
+ }
+}
+
+sub sig_script_error {
+ my ($script, $msg) = @_;
+ return unless Irssi::settings_get_bool('scriptassist_catch_script_errors');
+ if ($msg =~ /Can't locate (.*?)\.pm in \@INC \(\@INC contains:(.*?) at/) {
+ my $module = $1;
+ $module =~ s/\//::/g;
+ missing_module($module);
+ }
+}
+
+sub missing_module {
+ my ($module) = @_;
+ my $text;
+ $text .= "The perl module %9".$module."%9 is missing on your system.\n";
+ $text .= "Please ask your administrator about it.\n";
+ $text .= "You can also check CPAN via '/scriptassist cpan ".$module."'.\n";
+ print CLIENTCRAP &draw_box('ScriptAssist', $text, $module, 1);
+}
+
+sub cmd_scripassist {
+ my ($arg, $server, $witem) = @_;
+ utf8::decode($arg);
+ my @args = split(/ /, $arg);
+ if ($args[0] eq 'help' || $args[0] eq '-h') {
+ show_help();
+ } elsif ($args[0] eq 'check') {
+ bg_do("check");
+ } elsif ($args[0] eq 'update') {
+ shift @args;
+ bg_do("update ".join(' ', @args));
+ } elsif ($args[0] eq 'search' && defined $args[1]) {
+ shift @args;
+ bg_do("search ".join(" ", @args));
+ } elsif ($args[0] eq 'install' && defined $args[1]) {
+ shift @args;
+ bg_do("install ".join(' ', @args));
+ } elsif ($args[0] eq 'contact' && defined $args[1]) {
+ contact_author($args[1]);
+ } elsif ($args[0] eq 'ratings' && defined $args[1]) {
+ shift @args;
+ bg_do("ratings ".join(' ', @args));
+ } elsif ($args[0] eq 'rate' && defined $args[1]) {
+ shift @args;
+ bg_do("rate ".join(' ', @args));
+ } elsif ($args[0] eq 'info' && defined $args[1]) {
+ shift @args;
+ bg_do("info ".join(' ', @args));
+ } elsif ($args[0] eq 'echo') {
+ bg_do("echo");
+ } elsif ($args[0] eq 'top') {
+ my $number = defined $args[1] ? $args[1] : 10;
+ bg_do("top ".$number);
+ } elsif ($args[0] eq 'cpan' && defined $args[1]) {
+ call_openurl('http://search.cpan.org/search?mode=module&query='.$args[1]);
+ } elsif ($args[0] eq 'autorun' && defined $args[1]) {
+ toggle_autorun($args[1]);
+ } elsif ($args[0] eq 'new') {
+ my $number = defined $args[1] ? $args[1] : 5;
+ bg_do("new ".$number);
+ }
+}
+
+sub cmd_help {
+ my ($arg, $server, $witem) = @_;
+ $arg =~ s/\s+$//;
+ if ($arg =~ /^scriptassist/i) {
+ show_help();
+ }
+}
+
+sub sig_command_script_load {
+ my ($script, $server, $witem) = @_;
+ my ($sname, $plname, $pname, $xname) = get_names($script);
+ if ( exists $Irssi::Script::{$pname} ) {
+ if (my $code = "Irssi::Script::${pname}"->can('pre_unload')) {
+ print CLIENTCRAP "%R>>%n Triggering pre_unload function of $script...";
+ $code->();
+ }
+ }
+}
+
+sub sig_default_command {
+ my ($cmd, $server) = @_;
+ return unless Irssi::settings_get_bool("scriptassist_check_unknown_commands");
+ return if ($cmd =~ /^\d+$/ && $irssi_version >= v1.2.0 && Irssi::settings_get_bool("window_number_commands"));
+ bg_do('unknown '.$cmd);
+}
+
+sub sig_complete {
+ my ($list, $window, $word, $linestart, $want_space) = @_;
+ return unless $linestart =~ /^.script(assist)? (install|rate|ratings|update|check|contact|info|autorun)/i;
+ my @newlist;
+ my $str = $word;
+ foreach (@complist) {
+ if ($_ =~ /^(\Q$str\E.*)?$/) {
+ push @newlist, $_;
+ }
+ }
+ foreach (@{loaded_scripts()}) {
+ push @newlist, $_ if /^(\Q$str\E.*)?$/;
+ }
+ push @$list, $_ foreach @newlist;
+ Irssi::signal_stop();
+}
+
+
+Irssi::settings_add_str($IRSSI{name}, 'scriptassist_script_sources', 'https://scripts.irssi.org/scripts.yml');
+Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_cache_sources', 1);
+Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_update_verbose', 1);
+Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_check_verbose', 1);
+Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_catch_script_errors', 1);
+
+Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_install_unsigned_scripts', 1);
+Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_use_gpg', 1);
+Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_integrate', 1);
+Irssi::settings_add_bool($IRSSI{name}, 'scriptassist_check_unknown_commands', 1);
+
+Irssi::signal_add_first("default command", 'sig_default_command');
+Irssi::signal_add_first('complete word', 'sig_complete');
+Irssi::signal_add_first('command script load', 'sig_command_script_load');
+Irssi::signal_add_first('command script unload', 'sig_command_script_load');
+
+Irssi::signal_register({ 'script error' => [ 'Irssi::Script', 'string' ] });
+Irssi::signal_add_last('script error', 'sig_script_error');
+
+Irssi::command_bind('scriptassist', 'cmd_scripassist');
+Irssi::command_bind('help', 'cmd_help');
+
+Irssi::theme_register(['box_header', '%R,--[%n$*%R]%n',
+'box_inside', '%R|%n $*',
+'box_footer', '%R`--<%n$*%R>->%n',
+]);
+
+foreach my $cmd ( ( 'check',
+ 'install',
+ 'update',
+ 'contact',
+ 'search',
+# '-h',
+ 'help',
+ 'ratings',
+ 'rate',
+ 'info',
+# 'echo',
+ 'top',
+ 'cpan',
+ 'autorun',
+ 'new' ) ) {
+ Irssi::command_bind('scriptassist '.$cmd => sub {
+ cmd_scripassist("$cmd ".$_[0], $_[1], $_[2]); });
+ if (Irssi::settings_get_bool('scriptassist_integrate')) {
+ Irssi::command_bind('script '.$cmd => sub {
+ cmd_scripassist("$cmd ".$_[0], $_[1], $_[2]); });
+ }
+}
+
+print CLIENTCRAP '%B>>%n '.$IRSSI{name}.' '.$VERSION.' loaded: /scriptassist help for help';
diff --git a/scripts/usercount.pl b/scripts/usercount.pl
new file mode 100644
index 0000000..7e765c9
--- /dev/null
+++ b/scripts/usercount.pl
@@ -0,0 +1,184 @@
+use strict;
+use Irssi 20040119.2359 ();
+use vars qw($VERSION %IRSSI);
+$VERSION = "1.20";
+%IRSSI = (
+ authors => 'David Leadbeater, Timo Sirainen, Georg Lukas',
+ contact => 'dgl@dgl.cx, tss@iki.fi, georg@boerde.de',
+ name => 'usercount',
+ description => 'Adds a usercount for a channel as a statusbar item',
+ sbitems => 'usercount',
+ license => 'GNU GPLv2 or later',
+ url => 'http://irssi.dgl.cx/',
+ changes => 'Only show halfops if server supports them',
+);
+
+# Once you have loaded this script run the following command:
+# /statusbar window add usercount
+# You can also add -alignment left|right option
+
+# Settings:
+# /toggle usercount_show_zero to show item even when there are no users
+# /toggle usercount_show_ircops (default off)
+# /toggle usercount_show_halfops (default on)
+
+# you can customize the look of this item from theme file:
+# sb_usercount = "{sb %_$0%_ nicks ($1-)}";
+# sb_uc_ircops = "%_*%_$*";
+# sb_uc_ops = "%_@%_$*";
+# sb_uc_halfops = "%_%%%_$*";
+# sb_uc_voices = "%_+%_$*";
+# sb_uc_normal = "$*";
+# sb_uc_space = " ";
+
+
+use Irssi::TextUI;
+
+my ($ircops, $ops, $halfops, $voices, $normal, $total);
+my ($timeout_tag, $recalc);
+
+# Called to make the status bar item
+sub usercount {
+ my ($item, $get_size_only) = @_;
+ my $wi = !Irssi::active_win() ? undef : Irssi::active_win()->{active};
+
+ if(!ref $wi || $wi->{type} ne "CHANNEL") { # only works on channels
+ return unless ref $item;
+ $item->{min_size} = $item->{max_size} = 0;
+ return;
+ }
+
+ if ($recalc) {
+ $recalc = 0;
+ calc_users($wi);
+ }
+
+ my $theme = Irssi::current_theme();
+ my $format = $theme->format_expand("{sb_usercount}");
+ if ($format) {
+ # use theme-specific look
+ my $ircopstr = $theme->format_expand("{sb_uc_ircops $ircops}",
+ Irssi::EXPAND_FLAG_IGNORE_EMPTY);
+ my $opstr = $theme->format_expand("{sb_uc_ops $ops}",
+ Irssi::EXPAND_FLAG_IGNORE_EMPTY);
+ my $halfopstr = $theme->format_expand("{sb_uc_halfops $halfops}",
+ Irssi::EXPAND_FLAG_IGNORE_EMPTY);
+ my $voicestr = $theme->format_expand("{sb_uc_voices $voices}",
+ Irssi::EXPAND_FLAG_IGNORE_EMPTY);
+ my $normalstr = $theme->format_expand("{sb_uc_normal $normal}",
+ Irssi::EXPAND_FLAG_IGNORE_EMPTY);
+ my $space = $theme->format_expand('{sb_uc_space}',
+ Irssi::EXPAND_FLAG_IGNORE_EMPTY);
+ $space = " " unless $space;
+
+ my $str = "";
+ $str .= $ircopstr.$space if defined $ircops;
+ $str .= $opstr.$space if defined $ops;
+ $str .= $halfopstr.$space if defined $halfops;
+ $str .= $voicestr.$space if defined $voices;
+ $str .= $normalstr.$space if defined $normal;
+ $str =~ s/\Q$space\E$//;
+
+ $format = $theme->format_expand("{sb_usercount $total $str}",
+ Irssi::EXPAND_FLAG_IGNORE_REPLACES);
+ } else {
+ # use the default look
+ $format = "{sb \%_$total\%_ nicks \%c(\%n";
+ $format .= '*'.$ircops.' ' if (defined $ircops);
+ $format .= '@'.$ops.' ' if (defined $ops);
+ $format .= '%%'.$halfops.' ' if (defined $halfops);
+ $format .= "+$voices " if (defined $voices);
+ $format .= "$normal " if (defined $normal);
+ $format =~ s/ $//;
+ $format .= "\%c)}";
+ }
+
+ $item->default_handler($get_size_only, $format, undef, 1);
+}
+
+sub calc_users() {
+ my $channel = shift;
+ my $server = $channel->{server};
+
+ $ircops = $ops = $halfops = $voices = $normal = 0;
+ for ($channel->nicks()) {
+ if ($_->{serverop}) {
+ $ircops++;
+ }
+
+ if ($_->{op}) {
+ $ops++;
+ } elsif ($_->{halfop}) {
+ $halfops++;
+ } elsif ($_->{voice}) {
+ $voices++;
+ } else {
+ $normal++;
+ }
+ }
+
+ $total = $ops+$halfops+$voices+$normal;
+
+ if (!Irssi::settings_get_bool('usercount_show_zero')) {
+ $ircops = undef if ($ircops == 0);
+ $ops = undef if ($ops == 0);
+ $halfops = undef if ($halfops == 0);
+ $voices = undef if ($voices == 0);
+ $normal = undef if ($normal == 0);
+ }
+
+ # Server doesn't support halfops?
+ if($server->can('isupport') && $server->isupport("PREFIX") !~ /\%/) {
+ $halfops = undef;
+ } else {
+ $halfops = undef unless Irssi::settings_get_bool('usercount_show_halfops');
+ }
+
+ $ircops = undef unless Irssi::settings_get_bool('usercount_show_ircops');
+}
+
+sub refresh {
+ if ($timeout_tag > 0) {
+ Irssi::timeout_remove($timeout_tag);
+ $timeout_tag = 0;
+ }
+ Irssi::statusbar_items_redraw('usercount');
+}
+
+sub refresh_check {
+ my $channel = shift;
+ my $wi = ref Irssi::active_win() ? Irssi::active_win()->{active} : 0;
+
+ return unless ref $wi && ref $channel;
+ return if $wi->{name} ne $channel->{name};
+ return if $wi->{server}->{tag} ne $channel->{server}->{tag};
+
+ # don't refresh immediately, or we'll end up refreshing
+ # a lot around netsplits
+ $recalc = 1;
+ Irssi::timeout_remove($timeout_tag) if ($timeout_tag > 0);
+ $timeout_tag = Irssi::timeout_add(500, 'refresh', undef);
+}
+
+sub refresh_recalc {
+ $recalc = 1;
+ refresh();
+}
+
+$recalc = 1;
+$timeout_tag = 0;
+
+Irssi::settings_add_bool('usercount', 'usercount_show_zero', 1);
+Irssi::settings_add_bool('usercount', 'usercount_show_ircops', 0);
+Irssi::settings_add_bool('usercount', 'usercount_show_halfops', 1);
+
+Irssi::statusbar_item_register('usercount', undef, 'usercount');
+Irssi::statusbars_recreate_items();
+
+Irssi::signal_add_last('nicklist new', 'refresh_check');
+Irssi::signal_add_last('nicklist remove', 'refresh_check');
+Irssi::signal_add_last('nick mode changed', 'refresh_check');
+Irssi::signal_add_last('setup changed', 'refresh_recalc');
+Irssi::signal_add_last('window changed', 'refresh_recalc');
+Irssi::signal_add_last('window item changed', 'refresh_recalc');
+