def doInfo(self, cmdString, argList, kwargs): result = 0 top_context = hexchat.find_context() channel_list = hexchat.get_list('channels') front_tab = [c for c in hexchat.get_list('channels') if c.context == top_context][0] type = front_tab.type if type == 1: # server tab print("server tab, server is", front_tab.server) elif type == 2: # channel tab print("channel tab, channel is %s, modes are %s" % (front_tab.channel, front_tab.chanmodes)) users = top_context.get_list("users") elif type == 3: # dialog/query tab print("query tab, nick is", front_tab.channel) elif type == 4: # notices tab print("notices tab") elif type == 5: # SNotices tab print("SNotices tab") return result
def end_of_names_callback(word, word_eol, userdata): server = hexchat.get_info('server') if not server == TWITCH_IRC_SERVER or len(hexchat.get_list('users')) > 1: return current_channel = hexchat.get_info('channel') url = CHATTERS_URL_TEMPLATE % current_channel[1:] channel_key = server + current_channel hexchat.hook_timer(RETRIEVE_USERLIST_TIMEOUT, retrieve_userlist_update_callback, (url, channel_key)) start_new_thread(retrieve_userlist_update_thread, url, channel_key) channel = None for channel in hexchat.get_list('channels'): if channel.server == server and channel.channel == current_channel: break # This should never happen... assert channel # Initial userlist update, approximately 3 seconds after starting retrieve_userlist_update_thread. hexchat.hook_timer(INITIAL_UPDATE_USERLIST_TIMEOUT, initial_update_userlist_callback, channel) hexchat.hook_timer(UPDATE_USERLIST_TIMEOUT, update_userlist_callback, channel) return hexchat.EAT_NONE
def keypress(w, we, u): if re.search(affected_networks, hexchat.get_info("network")): key, state, key_str, str_len = w if int(key) == 65289: # <Tab> inputbox = hexchat.get_info("inputbox") pos = hexchat.get_prefs("state_cursor") text, suffix = inputbox[:pos], inputbox[pos:] prefix, space, word = text.rpartition(" ") if len(word): prefix += space if word[0] == '#': return hexchat.EAT_NONE # let the built-in completion handle channels if word[0] == '@': word = word[1:] users = [] for u in hexchat.get_list("users"): if not hexchat.nickcmp(u.nick[:len(word)], word): users.append((u.nick, u.lasttalk)) for c in hexchat.get_list("channels"): if c.context == hexchat.get_context(): if c.type == 3: if not hexchat.nickcmp(c.channel[:len(word)], word): users.append((c.channel, 0)) # if we're in a dialog, include the targer user if len(users): if len(users) == 1: completion = "@" + users[0][0] + " " else: if hexchat.get_prefs("completion_sort") == 1: users = sorted(users, key = lambda x: -x[1]) else: users = sorted(users, key = lambda x: x[0].lower()) nicks = [u[0] for u in users] print(" ".join(nicks)) common = None # longest common prefix for nick in nicks: if common == None: common = word + nick[len(word):] # copy the case of characters entered by the user else: while hexchat.nickcmp(nick[:len(common)], common): common = common[:-1] for nick in nicks: if not hexchat.nickcmp(nick, word): common = nick # if we have an exact match, ignore the case of user's characters completion = "@" + common hexchat.command("settext " + prefix + completion + suffix) hexchat.command("setcursor " + str(len(prefix) + len(completion))) return hexchat.EAT_ALL else: prevword = prefix.rpartition(" ")[2] if len(prevword) and prevword[0] == '@': return hexchat.EAT_ALL # don't let the built-in completion kick in if we just completed a nick else: return hexchat.EAT_NONE else: return hexchat.EAT_NONE
def checkStreams(): global firstRun if(firstRun): hexchat.unhook(timerHook) hexchat.hook_timer(300000, checkStreams_cb) firstRun = False channels = hexchat.get_list("channels") realChannels = [] channelObjects = {} for channel in channels: if(channel.server == "tmi.twitch.tv" and channel.channel[0] == '#'): realChannels.append(channel.channel.strip('#')) channelObjects[channel.channel.strip('#')] = channel if len(realChannels) > 0: streams = ",".join(realChannels) obj = loadJSON('https://api.twitch.tv/kraken/streams?channel=' + streams) # Returns only streams that are currently live, but returns them all in one go. if (obj is not None): streamData = {} for stream in obj["streams"]: streamData[stream["channel"]["name"]] = stream for channel in realChannels: newTopic = "\00318{0}\00399 - \00320\002OFFLINE\002\00399 | \035Stream is offline\017".format(channel) if (channel in streamData): newTopic = "\00318{0}\00399 - \00319\002LIVE\002\00399 for {1} viewers | Now playing: \00318{2}\00399 | {3}".format(streamData[channel]["channel"]["display_name"], streamData[channel]["viewers"], streamData[channel]["channel"]["game"], streamData[channel]["channel"]["status"]) if (get_topic(channelObjects[channel]) is not None): if (hexchat.strip(newTopic) != hexchat.strip(get_topic(channelObjects[channel]))): set_topic(channelObjects[channel], newTopic) else: set_topic(channelObjects[channel], newTopic)
def is_op(): for user in hexchat.get_list("users"): if user.nick == hexchat.get_info("nick"): if user.prefix == "@": return True else: return False
def get_Host (user): list = hexchat.get_list('users') for object in list: if user.lower() == object.nick.lower(): host = "*!*@" + object.host.split("@")[1] return host return user
def WhoScanStart(userdata): #print('timer started') global AllUsers global AllChannels for network in list(ScanProgress.keys()): if len(ScanProgress[network]) != 0: # hexchat.find_context().prnt('scan is in progress') return 1 # To keep the timer running AllChannels = {} allchannels = hexchat.get_list('channels') for channel in allchannels: if channel.type == 2: if channel.network not in list(AllChannels.keys()): AllChannels[channel.network] = [channel.channel] else: if channel.channel not in AllChannels[channel.network]: AllChannels[channel.network].append(channel.channel) for network in list(AllUsers.keys()): if network not in list(AllChannels.keys()): del AllUsers[network] for network in list(AllChannels.keys()): #hexchat.find_context().prnt('scanning ' + AllChannels[network][0] + ' at ' + network) hexchat.find_context(server=network).command('WHO ' + AllChannels[network][0]) ScanProgress[network] = AllChannels[network][0] return 1 # To keep the timer running
def leftjoin(word, word_eol, userdata): ctx = hexchat.get_context() channel = ctx.get_info('channel') # we need the channel object to get the flags chanobj = None for chan in hexchat.get_list('channels'): if hexchat.nickcmp(chan.channel, channel) == 0: chanobj = chan break if chanobj is None: return hexchat.EAT_NONE # if is this isn't a channel with the "Hide Join/Left" option, just return. if chanobj.flags & 0x40 == 0: return hexchat.EAT_NONE cleanup(userdata['nicks']) lnick = hexchat.strip(word[0]) channel = chan.channel for dnick, dchannel in userdata['nicks']: if hexchat.nickcmp(lnick, dnick) == 0 \ and hexchat.nickcmp(dchannel, channel) == 0: if time.time() <= userdata['nicks'][(dnick, dchannel)]: _emit_print(userdata['type'], *word) return hexchat.EAT_ALL else: del userdata['nicks'][(dnick, dchannel)] return hexchat.EAT_NONE
def save_session(userdata): # Saves the network|channels dictionary in pluginpref networks = {} channels = hexchat.get_list('channels') if not hexchat.get_context(): return # Build dictionary 'networks' # Iterate 'channels' and add all the servers for chan in channels: if chan.type == 1: networks[chan.network] = [] # Iterate 'channels' and add channels. # networks={'freenode':[chan1, chan2, chan3], 'dalnet':[]} for chan in channels: if chan.type == 2 or chan.type == 3: # Ignore notices and server tabs networks[chan.network].append(chan.channel) # Iterate 'networks' and store in hexchat.pluginpref as # session_freenode = chan1,chan2. This is written to # 'addon_python.conf' eventually. for network, channels in networks.items(): if len(network): hexchat.set_pluginpref('session_' + network, ','.join(channels)) return hexchat.EAT_ALL
def is_op(): for user in hexchat.get_list('users'): if user.nick == hexchat.get_info('nick'): if user.prefix == '@': return True else: return False
def _announce_update(site): " bleat to the appropriate channels " now = nowtime() if site['mtime'] == 0: # last-modified time is still empty? how'd we get here? return None if (site['lastanno'] + site['throttle']) > now: # too soon since the last announcement, just stay mum return None if site.get('announceto'): message = site.get('announcemsg') message = message.replace('{name}', site['name']) message = message.replace('{when}', _secs_to_pretty(now - site['mtime'])) targets = [i for i in site['announceto'] if i.startswith('#')] for target in targets: # can't use hexchat.get_context(None, channname) # because that returns only the random first matching context for channel in hexchat.get_list('channels'): if channel.channel == target: channel.context.command("say " + message) targets = [i for i in site['announceto'] if not i.startswith('#')] for target in targets: # TODO: find user among many servers # hexchat.command("msg {} {}".format(target, message)) print("NotImplemented msg % % .format({}, {})".format(target, message)) site['lastanno'] = now
def privmsg_cb(word, word_eol, userdata): if word[0][1:].split("!")[0] == "jtv": for chan in hexchat.get_list("channels"): if chan.type == 1 and chan.id == hexchat.get_prefs("id"): chan.context.set() hexchat.emit_print("Server Text", word_eol[3][1:]) return hexchat.EAT_ALL
def joinChannels(): actualChanList = hexchat.get_list('channels') chanList = db.listChans() for chan in chanList: if chan not in [x.channel for x in actualChanList]: hexchat.command("join %s" % chan)
def channel_msg_hook(self, word, word_eol, userdata, attribs): dest = hexchat.get_info('channel') nick = word[0] msg = word[1] # index user_list by nick, in user_dict # NOTE, TODO: build a way to keep this list maintained user_list = hexchat.get_list("users") user_dict = dict() for user in user_list: user_dict[user.nick] = user user_hostmask = user_dict[nick].host if dex("chanmsgdetail", self.debugSects) != -1: out = "chanmsgdetail dest: " + dest + "; nick: " + nick out += " (" if user_hostmask is not None: out += user_hostmask else: out += "None" out += "); msg: " + msg self.debugPrint(out) return hexchat.EAT_NONE
def channel_msg(word, word_eol, userdata): # only show when not focused on hexchat # if hexchat.get_info("win_status") == "active": # return None # get the channel info for where the message came from for ch in hexchat.get_list("channels"): # handle only channel if ch.type != 2: continue whitelist = hexchat.get_pluginpref('hxnotify_whitelist').split(',') # only show for whitelisted channels if word[2] in whitelist: # check if the chanopt is set if bool(ch.flags & blink_tray): my_nick = hexchat.get_info('nick') from_user = get_usrname(word[0]) # fix getting notifcations from self when # a bouncer playback is running if hexchat.nickcmp(from_user, my_nick) != 0: header = "Message ({0}/{1})".format(ch.network, ch.channel) body = "{0}: {1}".format(from_user, hexchat.strip(word_eol[3][1:], MESSAGE_LIMIT, 3)) # send the notification notification(header, body) return None return None
def checkStreams(): global firstRun if (firstRun): hexchat.unhook(timerHook) hexchat.hook_timer(300000, checkStreams_cb) firstRun = False channels = hexchat.get_list('channels') realChannels = [] for channel in channels: if (channel.server == 'tmi.twitch.tv' and channel.channel[0] == '#'): realChannels.append(channel.channel.strip('#')) for channel in realChannels: obj = loadJSON('https://api.twitch.tv/kraken/streams/' + channel) if (obj['stream'] == None and channel in liveChannels): liveChannels.remove(channel) format(channel.title() + ' is not live anymore.') elif (obj['stream'] != None and channel not in liveChannels): liveChannels.append(channel) format(channel.title() + ' is live!') format(obj['stream']['channel']['status'] + '(' + obj['stream']['game'] + ')') elif (obj['stream'] == None and channel not in liveChannels): format(channel.title() + ' is offline.')
def choose_callback(word, word_eol, user_data): channel = hexchat.get_info("channel") if (channel in channels) and not (set(user.nick for user in hexchat.get_list("users")) & other_bots): option = None user = None input = None matches = choose_regex.match(word[1]) if matches: option = "CHOOSE" user = word[0] input = matches.group(1) else: matches = order_regex.match(word[1]) if matches: option = "ORDER" user = word[0] input = matches.group(1) if option == "CHOOSE" or option == "ORDER": for action in (try_choose, try_order): response = action(option, input) if response != None: context = hexchat.get_context() hexchat.hook_timer( 0, send_response, {"context": hexchat.get_context(), "user": user, "response": response} ) break return hexchat.EAT_NONE
def unload_callback(userdata): # find the join/part tab and close it for chan in hexchat.get_list("channels"): if chan.type == 1 and chan.channel == tab_name: jp_context = hexchat.find_context(channel=tab_name) jp_context.command("CLOSE") hexchat.prnt(__module_name__ + " version " + __module_version__ + " unloaded")
def toggle_bookmark(chan, net): # It's a toggle because /menu sucks if chan == None: chan = hexchat.get_info('channel') if chan == '': return if net == None: try: # If from a $TAB it may be a different network. net = hexchat.find_context(None, chan).get_info('network') except AttributeError: net = hexchat.get_info('network') for channel in hexchat.get_list('channels'): if channel.channel == chan: if channel.type != 2: # Only bookmark channels return networks = get_networks(chan) pref = 'bookmark_' + chan if net in networks: # Remove if len(networks) == 1: hexchat.del_pluginpref(pref) else: networks.remove(net) hexchat.set_pluginpref(pref, ','.join(networks)) hexchat.command('menu del "Bookmarks/{}/{}"'.format(net, chan)) else: # Add networks.append(net) hexchat.set_pluginpref(pref, ','.join(networks)) hexchat.command('menu -p-2 add "Bookmarks/{}'.format(net)) hexchat.command('menu add "Bookmarks/{0}/{1}" "netjoin {1} {0}"'.format(net, chan))
def chanusermatch(word, word_eol, userdata): if (len(word) <= 1): print("You need to specify some pattern to match!") else: if (len(word) > 2): pattern = word_eol[1] else: pattern = word[1] if (('!' not in pattern) or ('@' not in pattern)): # This IRC Pattern is always enforced: [email protected] print("You need to specify a pattern in this form: [email protected]") print("You may specify a realname pattern if you wish by using the form: [email protected]#realname") else: rPattern = _RegexPattern(_SplitPattern(pattern)) users = [user.nick for user in hexchat.get_list('users') if re.match(r'%s' % rPattern[0], user.nick, flags=re.I) and re.match(r'%[email protected]%s' % (rPattern[1],rPattern[2]),user.host, flags=re.I) and re.match(r'%s' % rPattern[3], user.realname, flags=re.I)] print('# of Matches: ' + str(len(users))) if (len(users) > 0): print(users) return hexchat.EAT_ALL
def getCurrentBotCPS(bot): dcclist = hexchat.get_list('dcc') cps = 'Unknown CPS' for item in dcclist: if str(item.nick).lower() == bot.lower(): cps = '%s CPS' % (str(item.cps)) break return cps
def friend_offline(word, word_eol, userdata): names = word[3][1:].split(',') for i in hexchat.get_list("notify"): if i.nick in names and i.on != 0: notification("Friend Offline", "{0} has gone offline".format(name)) return None
def getchannels(): channels = [] network = hexchat.get_info("network") for i in hexchat.get_list("channels"): if i.network == network: if i.type == 2: channels.append(i.channel) return channels
def get_twitch_channels(self): """ Get a list of open TwitchTV channels and store them in self.twitch_chans """ self.twitch_chans = [] for chan in hexchat.get_list("channels"): if chan.type == 2 and chan.context.get_info("host") == "irc.twitch.tv": self.twitch_chans.append(chan.channel)
def netId(ctx = None): if ctx == None or ctx == hexchat.get_context(): return hexchat.get_prefs("id") else: for c in hexchat.get_list("channels"): if c.context == ctx: return c.id return "?"
def is_op(): for user in hexchat.get_list('users'): if user.nick == hexchat.get_info('nick'): # FIXME: This might not work on all networks with 50 op levels.. if '@' in user.prefix: return True else: return False
def get_twitch_channels(self): """ Get a list of open TwitchTV channels and store them in self.twitch_chans """ self.twitch_chans = [] for chan in hexchat.get_list("channels"): if chan.type == 2 and get_pref("twitch_base_domain") in chan.context.get_info("host"): self.twitch_chans.append(chan.channel)
def new_msg(word, word_eol, event, attrs): #handles normal messages global last_seen global halt if halt: return #get username from message user_name = hexchat.strip(word[0]) users = hexchat.get_list("users") #Try to find the user based on the users list user = "******" user_host = "NULL" user_ip = "NULL" for u in users: if(u.nick == user_name): user = u.host user_host = ''.join(user.split('@')[1:]) user_ip = get_ip(user) break #user was logged in before script started if user_host not in last_seen: last_seen[user_host] = [time(), True, user_name, user_ip] #invalid user case (typically user is no longer connected) if user_host == "NULL" or user == "NULL": halt = True hexchat.emit_print(event, *word) halt = False if debug_output: print("\00315Supressed invalid user case") return hexchat.EAT_ALL #user never spoke before if not last_seen[user_host][1]: time_diff = time() - last_seen[user_host][0] #get geoip geoip = get_geoip(user_ip) #add information to message if user_name == last_seen[user_host][2]: word[1] += " \00307(logged in %s ago from \00302%s \00310%s\00307)" % (human_readable(time_diff),user.split('@')[0] + '@' + user_ip,geoip) else: word[1] += " \00307(logged in %s ago. Formerly \00302%s\00307 from \00302%s \00310%s\00307)" % (human_readable(time_diff),last_seen[user_host][2],user.split('@')[0] + '@' + user_ip,geoip) #added host for debug purposes last_seen[user_host][2] = user_name #print message halt = True hexchat.emit_print(event, *word) halt = False last_seen[user_host][1] = True return hexchat.EAT_ALL else: last_seen[user_host][0] = time()
def privmsg_cb(word, word_eol, userdata): if word[0][1:].split('!')[0] == 'jtv': if word[2][0] != '#': for chan in hexchat.get_list('channels'): if chan.type == 1 and chan.id == hexchat.get_prefs('id'): chan.context.emit_print('Server Text', word_eol[3][1:]) return hexchat.EAT_ALL elif word[3] in (':USERCOLOR', ':USERSTATE', ':HISTORYEND', ':EMOTESET', ':CLEARCHAT', ':SPECIALUSER'): return hexchat.EAT_ALL
def check_lasttalk(nick): for user in hexchat.get_list("users"): if user.nick == hexchat.strip(nick): if time() - user.lasttalk > 60 * 5: return hexchat.EAT_HEXCHAT else: return hexchat.EAT_NONE return hexchat.EAT_HEXCHAT