def get_stats(self): dayago = self.now - 86400 channel_message_counts = {} user_message_counts = {} for channel in self.slacker.channels_by_name: if ignore_channel(self.config, channel): self.logger.debug( "Not checking stats for channel: #%s because it's in ignore_channels", channel) continue cid = self.slacker.get_channelid(channel) cur_messages = self.slacker.get_messages_in_time_range( dayago, cid, self.now) channel_message_counts[channel] = len(cur_messages) for message in cur_messages: if message.get('user'): user_name = self.slacker.users_by_id[message['user']] if not self.config.stats_ignore_users or not user_name in self.config.stats_ignore_users: if user_message_counts.get(user_name): user_message_counts[ user_name] = user_message_counts[user_name] + 1 else: user_message_counts[user_name] = 1 return channel_message_counts, user_message_counts
def warn_all(self, days, force_warn=False): """Warn all channels which are `days` idle; if `force_warn`, will warn even if we already have.""" if not self.config.activated: self.logger.info( "Note, destalinator is not activated and is in a dry-run mode. For help, see the " "documentation on the DESTALINATOR_ACTIVATED environment variable." ) self.action( "Warning all channels stale for more than {} days".format(days)) stale = [] for channel in sorted(self.slacker.channels_by_name.keys()): if ignore_channel(self.config, channel): self.logger.debug( "Not warning #%s because it's in ignore_channels", channel) continue if self.stale(channel, days): if self.warn(channel, days, force_warn): stale.append(channel) self.flush_channel_cache(channel) if stale and self.config.general_message_channel: self.logger.debug("Notifying #%s of warned channels", self.config.general_message_channel) self.warn_in_general(stale)
def stale(self, channel_name, days): """ Return True if channel represented by `channel_name` is stale. Definition of stale is: no messages in the last `days` which are not from config.ignore_users. """ if not self.channel_minimum_age(channel_name, days): return False if ignore_channel(self.config, channel_name): return False if self.slacker.channel_has_only_restricted_members(channel_name): return False messages = self.get_messages(channel_name, days) # return True (stale) if none of the messages match the criteria below return not any( # the message is not from an ignored user x.get("user") not in self.config.ignore_users \ and x.get("username") not in self.config.ignore_users \ and ( # the message must have text that doesn't include ignored words (x.get("text") and b":dolphin:" not in x.get("text").encode('utf-8', 'ignore')) \ or x.get("attachments") # or the message must have attachments ) for x in messages )
def get_interesting_messages(self): """ returns [[message, [listofchannelstoannounce]] """ dayago = self.now - 86400 messages = [] for channel in self.slacker.channels_by_name: if ignore_channel(self.config, channel): self.logger.debug("Not checking flags for channel: #%s because it's in ignore_channels", channel) continue cid = self.slacker.get_channelid(channel) cur_messages = self.slacker.get_messages_in_time_range(dayago, cid, self.now) for message in cur_messages: announce = self.message_destination(message) if announce: messages.append([message, announce]) return messages
def warn(self, channel_name, days, force_warn=False): """ Send warning text to channel_name, if it has not been sent already in the last `days`. Using `force_warn=True` will warn even if a previous warning exists. Return True if we actually warned, otherwise False. """ # Might not need to do this since we now do this in `stale` if self.slacker.channel_has_only_restricted_members(channel_name): self.logger.debug( "Would have warned #%s but it contains only restricted users", channel_name) return False # Might not need to do this since we now do this in `stale` if ignore_channel(self.config, channel_name): self.logger.debug( "Not warning #%s because it's in ignore_channels", channel_name) return False messages = self.get_messages(channel_name, days) texts = [x.get("text").strip() for x in messages if x.get("text")] if (not force_warn and (self.add_slack_channel_markup(self.warning_text) in texts or any( any( a.get('fallback') == 'channel_warning' for a in m.get('attachments', [])) for m in messages))): self.logger.debug( "Not warning #%s because we found a prior warning", channel_name) return False if self.config.activated: self.post_marked_up_message(channel_name, self.warning_text, message_type='channel_warning') self.action("Warned #{}".format(channel_name)) return True
def archive(self, channel_name): """Archive the given channel name, returning the Slack API response as a JSON string.""" # Might not need to do this since we now do this in `stale` if ignore_channel(self.config, channel_name): self.logger.debug( "Not archiving #%s because it's in ignore_channels", channel_name) return if self.config.activated: self.logger.debug("Announcing channel closure in #%s", channel_name) self.post_marked_up_message(channel_name, self.closure_text, message_type='channel_archive') members = self.slacker.get_channel_member_names(channel_name) say = "Members at archiving are {}".format(", ".join( sorted(members))) self.logger.debug("Telling channel #%s: %s", channel_name, say) self.post_marked_up_message(channel_name, say, message_type='channel_archive_members') self.action("Archiving channel #{}".format(channel_name)) payload = self.slacker.archive(channel_name) if payload['ok']: self.logger.debug("Slack API response to archive: %s", json.dumps(payload, indent=4)) self.logger.info("Archived %s", channel_name) else: error = payload.get( 'error', '!! No error found in payload %s !!' % payload) self.logger.error( "Failed to archive %s: %s. See https://api.slack.com/methods/channels.archive for more context.", channel_name, error) return payload