diff options
Diffstat (limited to '')
-rw-r--r-- | scripts/Makefile.am | 18 | ||||
-rw-r--r-- | scripts/Makefile.in | 741 | ||||
-rw-r--r-- | scripts/autoop.pl | 156 | ||||
-rw-r--r-- | scripts/autorejoin.pl | 72 | ||||
-rw-r--r-- | scripts/buf.pl | 132 | ||||
-rw-r--r-- | scripts/dns.pl | 236 | ||||
-rw-r--r-- | scripts/examples/Makefile.am | 8 | ||||
-rw-r--r-- | scripts/examples/Makefile.in | 552 | ||||
-rw-r--r-- | scripts/examples/command.pl | 23 | ||||
-rw-r--r-- | scripts/examples/msg-event.pl | 41 | ||||
-rw-r--r-- | scripts/examples/redirect.pl | 40 | ||||
-rw-r--r-- | scripts/kills.pl | 103 | ||||
-rw-r--r-- | scripts/mail.pl | 416 | ||||
-rw-r--r-- | scripts/meson.build | 14 | ||||
-rw-r--r-- | scripts/mlock.pl | 135 | ||||
-rw-r--r-- | scripts/quitmsg.pl | 36 | ||||
-rw-r--r-- | scripts/scriptassist.pl | 1265 | ||||
-rw-r--r-- | scripts/usercount.pl | 184 |
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'); + |