def run(self): log.info("Starting server thread...") self.running = True self.load_config() self.slack_wrapper = SlackWrapper(self.get_config_option("api_key")) self.start_services() while self.running: try: if self.slack_wrapper.connected: log.info("Connection successful...") self.load_bot_data() read_websocket_delay = 1 # 1 second delay between reading from firehose # Might even pass the bot server for handlers? log.info("Initializing handlers...") handler_factory.initialize(self.slack_wrapper, self) # Main loop log.info("Bot is running...") while self.running: message = self.slack_wrapper.read() if message: reaction, channel, ts, reaction_user = self.parse_slack_reaction( message) if reaction: log.debug("Received reaction : {} ({})".format( reaction, channel)) handler_factory.process_reaction( self.slack_wrapper, reaction, ts, channel, reaction_user) command, channel, user = self.parse_slack_message( message) if command: log.debug( "Received bot command : {} ({})".format( command, channel)) handler_factory.process( self.slack_wrapper, command, channel, user) time.sleep(read_websocket_delay) else: log.error( "Connection failed. Invalid slack token or bot id?") self.running = False except websocket._exceptions.WebSocketConnectionClosedException: log.exception("Web socket error. Executing reconnect...") except SlackConnectionError: # Try to reconnect if slackclient auto_reconnect didn't work out. Keep an eye on the logfiles, # and remove the superfluous exception handling if auto_reconnect works. log.exception( "Slack connection error. Trying manual reconnect in 5 seconds..." ) time.sleep(5) self.stop_services() log.info("Shutdown complete...")
def run(self): self.running = True while self.running: try: parts = input("").split(" ") cmd = parts[0].lower() if cmd == "quit": self.botserver.quit() break # Example command: Useless, but just an example, for what # console handler could do elif cmd == "createchannel": if len(parts) < 2: print("Usage: createchannel <channel>") else: self.botserver.slack_wrapper.create_channel(parts[1]) elif cmd == "set": if len(parts) < 3: self.show_set_usage() else: self.update_config(parts[1], parts[2]) except Exception: log.exception( "An error has occured while processing a console command")
def push(self, repo_user, repo_pass, repo_remote, repo_branch): """Push the current commit to git.""" try: if repo_pass: porcelain.push( self.repo, "https://{}:{}@{}".format(repo_user, repo_pass, repo_remote), bytes(repo_branch, "utf-8")) else: porcelain.push(self.repo, "git@{}".format(repo_remote), bytes(repo_branch, "utf-8")) except dulwich.errors.GitProtocolError: raise InvalidCommand( "Upload file failed: GitProtocolError - Check your username and password in the git configuration..." ) except KeyError: raise InvalidCommand( "Upload file failed: KeyError - Check your git configuration for missing keys..." ) except TypeError: raise InvalidCommand( "Upload file failed: TypeError - Did you forget to create a git configuration?" ) except Exception: log.exception("GitHandler::push()") raise InvalidCommand( "Upload file failed: Unknown - Please check your log files...")
def commit(self, commit_message): """Commit the current changeset.""" try: porcelain.commit(self.repo, bytes(commit_message, "utf-8")) except Exception: # Anonymizing exceptions log.exception("GitHandler::commit()") raise InvalidCommand("Comitting file failed: Please check your log files...")
def __init__(self, repo_path): try: self.repo_path = repo_path self.repo = porcelain.open_repo(repo_path) except Exception: log.exception("GitHandler::__init__()") raise InvalidCommand("Opening repo failed: Please check your log")
def execute(cls, slack_wrapper, args, channel_id, user_id, user_is_admin): """Execute the Version command.""" try: message = GitHandler(".").get_version() slack_wrapper.post_message(channel_id, message) except: log.exception("BotHandler::VersionCommand") raise InvalidCommand("Sorry, couldn't retrieve the git information for the bot...")
def add_file(self, data, filename): """Add a file to the commit.""" try: full_filename = os.path.join(self.repo_path, filename) with open(full_filename, "w") as f: f.write(data) porcelain.add(self.repo, full_filename) except Exception: # Anonymizing exceptions log.exception("GitHandler::add_file()") raise InvalidCommand("Adding file failed: Please check your log files...")
def execute(cls, slack_wrapper, args, timestamp, channel_id, user_id, user_is_admin): current_members = slack_wrapper.get_channel_members(channel_id) # strip uid formatting invited_users = [user.strip("<>@") for user in args] # remove already present members invited_users = [user for user in invited_users if user not in current_members] failed_users = [] for member in invited_users: if not slack_wrapper.invite_user(member, channel_id)["ok"]: failed_users.append(member) if failed_users: log.exception("BotHandler::InviteCommand") raise InvalidCommand("Sorry, couldn't invite the following members to the channel: " + ' '.join(failed_users))
def process_reaction(slack_wrapper, reaction, timestamp, channel_id, user_id): try: log.debug("Processing reaction: %s from %s (%s)", reaction, channel_id, timestamp) admin_users = botserver.get_config_option("admin_users") user_is_admin = admin_users and user_id in admin_users for handler_name, handler in handlers.items(): if handler.can_handle_reaction(reaction): handler.process_reaction(slack_wrapper, reaction, channel_id, timestamp, user_id, user_is_admin) except InvalidCommand as e: slack_wrapper.post_message(channel_id, e, timestamp) except Exception: log.exception("An error has occured while processing a command")
def post_ctf_data(ctf, title): """Create a post and a statistic file and upload it to the configured SolveTracker repository.""" if not ST_GIT_SUPPORT: raise Exception( "Sorry, but the SolveTracker support isn't configured...") try: now = datetime.datetime.now() post_data = resolve_ctf_template( ctf, title, "./templates/post_ctf_template", "./templates/post_challenge_template") post_filename = "_posts/{}-{}-{}-{}.md".format(now.year, now.month, now.day, ctf.name) stat_data = resolve_stats_template(ctf) stat_filename = "_stats/{}.json".format(ctf.name) git = GitHandler(ST_GIT_CONFIG.get("git_repopath")) git.add_file(post_data, post_filename) git.add_file(stat_data, stat_filename) git.commit("Solve post from {}".format(ctf.name)) git.push(ST_GIT_CONFIG.get("git_repouser"), ST_GIT_CONFIG.get("git_repopass"), ST_GIT_CONFIG.get("git_remoteuri"), ST_GIT_CONFIG.get("git_branch")) return ST_GIT_CONFIG.get("git_baseurl") except InvalidCommand as invalid_cmd: # Just pass invalid commands on raise invalid_cmd except Exception: log.exception("SolvePostHelper") raise InvalidCommand( "Something with your configuration files doesn't seem to be correct. Please check your logfiles..." )
def run(self): log.info("Starting server thread...") self.running = True while self.running: try: self.load_config() self.slack_wrapper = SlackWrapper( self.get_config_option("api_key")) if self.slack_wrapper.connected: log.info("Connection successful...") self.init_bot_data() # Main loop log.info("Bot is running...") while self.running: message = self.slack_wrapper.read() if message: self.handle_message(message) time.sleep(self.read_websocket_delay) else: log.error( "Connection failed. Invalid slack token or bot id?") self.running = False except websocket._exceptions.WebSocketConnectionClosedException: log.exception("Web socket error. Executing reconnect...") except SlackConnectionError: # Try to reconnect if slackclient auto_reconnect didn't work out. Keep an eye on the logfiles, # and remove the superfluous exception handling if auto_reconnect works. log.exception( "Slack connection error. Trying manual reconnect in 5 seconds..." ) time.sleep(5) except: log.exception("Unhandled error. Try reconnect...") time.sleep(5) log.info("Shutdown complete...")
def process_command(slack_wrapper, message, args, timestamp, channel_id, user_id, admin_override=False): try: handler_name = args[0].lower() processed = False usage_msg = "" admin_users = botserver.get_config_option("admin_users") user_is_admin = admin_users and user_id in admin_users if admin_override: user_is_admin = True # Call a specific handler with this command handler = handlers.get(handler_name) if handler: # Setup usage message if len(args) < 2 or args[1] == "help": usage_msg += handler.get_usage(user_is_admin) processed = True else: # Send command to specified handler command = args[1].lower() if handler.can_handle(command, user_is_admin): handler.process(slack_wrapper, command, args[2:], timestamp, channel_id, user_id, user_is_admin) processed = True else: # Pass the command to every available handler command = args[0].lower() for handler_name, handler in handlers.items(): if command == "help": # Setup usage message usage_msg += "{}\n".format( handler.get_usage(user_is_admin)) processed = True elif handler.can_handle( command, user_is_admin): # Send command to handler handler.process(slack_wrapper, command, args[1:], timestamp, channel_id, user_id, user_is_admin) processed = True if not processed: # Send error message message = "Unknown handler or command : `{}`".format(message) slack_wrapper.post_message(channel_id, message, timestamp) if usage_msg: # Send usage message send_help_as_dm = botserver.get_config_option( "send_help_as_dm") == "1" target_id = user_id if send_help_as_dm else channel_id slack_wrapper.post_message(target_id, usage_msg) except InvalidCommand as e: slack_wrapper.post_message(channel_id, e, timestamp) except Exception: log.exception("An error has occured while processing a command")