Set away status when detaching and attaching from screen or tmux.
Author: xt
— Version: 0.16
— License: GPL-3.0-or-later
For WeeChat ≥ 0.3.0.
Tags: away, screen, tmux, py2, py3
Added: 2009-11-29
— Updated: 2019-03-17
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 | # -*- coding: utf-8 -*- # # Copyright (c) 2009 by xt <xt@bash.no> # Copyright (c) 2009 by penryu <penryu@gmail.com> # Copyright (c) 2010 by Blake Winton <bwinton@latte.ca> # Copyright (c) 2010 by Aron Griffis <agriffis@n01se.net> # Copyright (c) 2010 by Jani Kesänen <jani.kesanen@gmail.com> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # # (this script requires WeeChat 0.3.0 or newer) # # History: # 2019-03-04, Germain Z. <germanosz@gmail.com> # version 0.16: add option "socket_file", for use with e.g. dtach # : code reformatting for consistency/PEP8 # 2017-11-20, Nils Görs <weechatter@arcor.de> # version 0.15: make script python3 compatible # : fix problem with empty "command_on_*" options # : add option "no_output" # 2014-08-02, Nils Görs <weechatter@arcor.de> # version 0.14: add time to detach message. (idea by Mikaela) # 2014-06-19, Anders Bergh <anders1@gmail.com> # version 0.13: Fix a simple typo in an option description. # 2014-01-12, Phyks (Lucas Verney) <phyks@phyks.me> # version 0.12: Added an option to check status of relays to set unaway in # case of a connected relay. # 2013-08-30, Anders Einar Hilden <hildenae@gmail.com> # version: 0.11: Fix reading of set_away # 2013-06-16, Renato Botelho <rbgarga@gmail.com> # version 0.10: add option to don't set away, only change nick # allow multiple commands on attach/dettach # do not add suffix if nick already have it # 2012-12-29, David Flatz <david@upcs.at> # version 0.9: add option to ignore servers and don't set away status for them # add descriptions to config options # 2010-08-07, Filip H.F. "FiXato" Slagter <fixato@gmail.com> # version 0.8: add command on attach feature # 2010-05-07, Jani Kesänen <jani.kesanen@gmail.com> # version 0.7: add command on detach feature # 2010-03-07, Aron Griffis <agriffis@n01se.net> # version 0.6: move socket check to register, # add hook_config for interval, # reduce default interval from 60 to 5 # 2010-02-19, Blake Winton <bwinton@latte.ca> # version 0.5: add option to change nick when away # 2010-01-18, xt # version 0.4: only update servers that are connected # 2009-11-30, xt <xt@bash.no> # version 0.3: do not touch servers that are manually set away # 2009-11-27, xt <xt@bash.no> # version 0.2: code for TMUX from penryu # 2009-11-27, xt <xt@bash.no> # version 0.1: initial release import os import re import time import weechat as w SCRIPT_NAME = 'screen_away' SCRIPT_AUTHOR = 'xt <xt@bash.no>' SCRIPT_VERSION = '0.16' SCRIPT_LICENSE = 'GPL3' SCRIPT_DESC = 'Set away status on screen detach' SETTINGS = { 'message': ('Detached from screen', 'Away message'), 'time_format': ('since %Y-%m-%d %H:%M:%S%z', 'time format append to away message'), 'interval': ('5', 'How often in seconds to check screen status'), 'away_suffix': ('', 'What to append to your nick when you\'re away.'), 'command_on_attach': ('', ('Commands to execute on attach, separated by ' 'semicolon')), 'command_on_detach': ('', ('Commands to execute on detach, separated by ' 'semicolon')), 'ignore': ('', 'Comma-separated list of servers to ignore.'), 'set_away': ('on', 'Set user as away.'), 'ignore_relays': ('off', 'Only check screen status and ignore relay interfaces'), 'no_output': ('off', 'no detach/attach information will be displayed in buffer'), 'socket_file': ('', 'Socket file to use (leave blank to auto-detect)'), } TIMER = None SOCK = None AWAY = False CONNECTED_RELAY = False def set_timer(): '''Update timer hook with new interval.''' global TIMER if TIMER: w.unhook(TIMER) TIMER = w.hook_timer(int(w.config_get_plugin('interval')) * 1000, 0, 0, 'screen_away_timer_cb', '') def screen_away_config_cb(data, option, value): '''Update timer / sock file on config changes.''' global SOCK if SOCK and option.endswith('.interval'): set_timer() elif option.endswith('.socket_file'): SOCK = value if not SOCK: SOCK = get_sock() if SOCK: set_timer() elif TIMER: w.unhook(TIMER) return w.WEECHAT_RC_OK def get_servers(): '''Get the servers that are not away, or were set away by this script.''' ignores = w.config_get_plugin('ignore').split(',') infolist = w.infolist_get('irc_server', '', '') buffers = [] while w.infolist_next(infolist): if (not w.infolist_integer(infolist, 'is_connected') == 1 or w.infolist_string(infolist, 'name') in ignores): continue if (not w.config_string_to_boolean(w.config_get_plugin('set_away')) or not w.infolist_integer(infolist, 'is_away') or w.config_get_plugin('message') in w.infolist_string( infolist, 'away_message')): buffers.append((w.infolist_pointer(infolist, 'buffer'), w.infolist_string(infolist, 'nick'))) w.infolist_free(infolist) return buffers def screen_away_timer_cb(buffer, args): '''Check if screen is attached and update awayness.''' global AWAY, SOCK, CONNECTED_RELAY set_away = w.config_string_to_boolean(w.config_get_plugin('set_away')) check_relays = not w.config_string_to_boolean( w.config_get_plugin('ignore_relays')) suffix = w.config_get_plugin('away_suffix') attached = os.access(SOCK, os.X_OK) # X bit indicates attached. # Check wether a client is connected on relay or not. CONNECTED_RELAY = False if check_relays: infolist = w.infolist_get('relay', '', '') if infolist: while w.infolist_next(infolist): status = w.infolist_string(infolist, 'status_string') if status == 'connected': CONNECTED_RELAY = True break w.infolist_free(infolist) if ((attached and AWAY) or (check_relays and CONNECTED_RELAY and not attached and AWAY)): if not w.config_string_to_boolean(w.config_get_plugin('no_output')): w.prnt('', '{}: Screen attached. Clearing away status'.format( SCRIPT_NAME)) for server, nick in get_servers(): if set_away: w.command(server, '/away') if suffix and nick.endswith(suffix): nick = nick[:-len(suffix)] w.command(server, '/nick {}'.format(nick)) AWAY = False if w.config_get_plugin('command_on_attach'): for cmd in w.config_get_plugin('command_on_attach').split(';'): w.command('', cmd) elif not attached and not AWAY: if not CONNECTED_RELAY: if (not w.config_string_to_boolean( w.config_get_plugin('no_output'))): w.prnt('', '{}: Screen detached. Setting away status'.format( SCRIPT_NAME)) for server, nick in get_servers(): if suffix and not nick.endswith(suffix): w.command(server, '/nick {}{}'.format(nick, suffix)) if set_away: w.command(server, '/away {} {}'.format( w.config_get_plugin('message'), time.strftime(w.config_get_plugin('time_format')))) AWAY = True if w.config_get_plugin('command_on_detach'): for cmd in w.config_get_plugin('command_on_detach').split(';'): w.command('', cmd) return w.WEECHAT_RC_OK def get_sock(): '''Try to get the appropriate sock file for screen/tmux.''' sock = None if 'STY' in os.environ.keys(): # We are running under screen. cmd_output = os.popen('env LC_ALL=C screen -ls').read() match = re.search(r'Sockets? in (/.+)\.', cmd_output) if match: sock = os.path.join(match.group(1), os.environ['STY']) if not sock and 'TMUX' in os.environ.keys(): # We are running under tmux. socket_data = os.environ['TMUX'] sock = socket_data.rsplit(',', 2)[0] return sock if w.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, '', ''): version = w.info_get('version_number', '') or 0 for option, default_desc in SETTINGS.items(): if not w.config_is_set_plugin(option): w.config_set_plugin(option, default_desc[0]) if int(version) >= 0x00030500: w.config_set_desc_plugin(option, default_desc[1]) SOCK = w.config_get_plugin('socket_file') if not SOCK: SOCK = get_sock() if SOCK: set_timer() w.hook_config('plugins.var.python.{}.*'.format(SCRIPT_NAME), 'screen_away_config_cb', '') |