# Buggy code
def process_message_files(
    message: ZerverFieldsT,
    domain_name: str,
    realm_id: int,
    message_id: int,
    user: str,
    users: List[ZerverFieldsT],
    added_users: AddedUsersT,
    zerver_attachment: List[ZerverFieldsT],
    uploads_list: List[ZerverFieldsT],
) -> Dict[str, Any]:
    has_attachment = False
    has_image = False
    has_link = False

    files = message.get("files", [])

    subtype = message.get("subtype")

    if subtype == "file_share":
        # In Slack messages, uploads can either have the subtype as 'file_share' or
        # have the upload information in 'files' keyword
        files = [message["file"]]

    markdown_links = []

    for fileinfo in files:
        url = fileinfo["url_private"]

        if "files.slack.com" in url:
            # For attachments with slack download link
            has_attachment = True
            has_link = True
            has_image = True if "image" in fileinfo["mimetype"] else False

            file_user = [
                iterate_user
                for iterate_user in users
                if message["user"] == iterate_user["id"]
            ]
            file_user_email = get_user_email(file_user[0], domain_name)

            s3_path, content_for_link = get_attachment_path_and_content(
                fileinfo, realm_id
            )
            markdown_links.append(content_for_link)

            # construct attachments
            build_uploads(
                added_users[user],
                realm_id,
                file_user_email,
                fileinfo,
                s3_path,
                uploads_list,
            )

            build_attachment(
                realm_id,
                {message_id},
                added_users[user],
                fileinfo,
                s3_path,
                zerver_attachment,
            )
        else:
            # For attachments with link not from slack
            # Example: Google drive integration
            has_link = True
            if "title" in fileinfo:
                file_name = fileinfo["title"]
            else:
                file_name = fileinfo["name"]
            markdown_links.append("[%s](%s)" % (file_name, fileinfo["url_private"]))

    content = "\n".join(markdown_links)

    return dict(
        content=content,
        has_attachment=has_attachment,
        has_image=has_image,
        has_link=has_link,
    )


# Traceback (KeyError)
2019-02-20 13:56:31.207 INFO [] Writing Messages to /home/zulip/deployments/2019-02-11-23-41-46/[…]/messages-000109.json

Traceback (most recent call last):
File "./manage.py", line 50, in <module>
execute_from_command_line(sys.argv)
File "/home/zulip/deployments/2019-02-11-23-41-46/zulip-py3-venv/lib/python3.6/site-packages/django/core/management/__init__.py", line 364, in execute_from_command_line
utility.execute()
File "/home/zulip/deployments/2019-02-11-23-41-46/zulip-py3-venv/lib/python3.6/site-packages/django/core/management/__init__.py", line 356, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/zulip/deployments/2019-02-11-23-41-46/zulip-py3-venv/lib/python3.6/site-packages/django/core/management/base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/zulip/deployments/2019-02-11-23-41-46/zulip-py3-venv/lib/python3.6/site-packages/django/core/management/base.py", line 330, in execute
output = self.handle(*args, **options)
File "/home/zulip/deployments/2019-02-11-23-41-46/zerver/management/commands/convert_slack_data.py", line 58, in handle
do_convert_data(path, output_dir, token, threads=num_threads)
File "/home/zulip/deployments/2019-02-11-23-41-46/zerver/data_import/slack.py", line 888, in do_convert_data
realm, realm['zerver_userprofile'], realm['zerver_realmemoji'], domain_name, output_dir)
File "/home/zulip/deployments/2019-02-11-23-41-46/zerver/data_import/slack.py", line 542, in convert_slack_workspace_messages
domain_name, long_term_idle)
File "/home/zulip/deployments/2019-02-11-23-41-46/zerver/data_import/slack.py", line 683, in channel_message_to_zerver_message
uploads_list=uploads_list,
File "/home/zulip/deployments/2019-02-11-23-41-46/zerver/data_import/slack.py", line 742, in process_message_files
url = fileinfo['url_private']
KeyError: 'url_private'

# Fixed code
def process_message_files(
    message: ZerverFieldsT,
    domain_name: str,
    realm_id: int,
    message_id: int,
    user: str,
    users: List[ZerverFieldsT],
    added_users: AddedUsersT,
    zerver_attachment: List[ZerverFieldsT],
    uploads_list: List[ZerverFieldsT],
) -> Dict[str, Any]:
    has_attachment = False
    has_image = False
    has_link = False

    files = message.get("files", [])

    subtype = message.get("subtype")

    if subtype == "file_share":
        # In Slack messages, uploads can either have the subtype as 'file_share' or
        # have the upload information in 'files' keyword
        files = [message["file"]]

    markdown_links = []

    for fileinfo in files:
        if fileinfo["mode"] == "tombstone":
            # Slack sometimes includes tombstone mode files with no
            # real data on the actual file (presumably in cases where
            # the file was deleted).
            continue

        url = fileinfo["url_private"]

        if "files.slack.com" in url:
            # For attachments with slack download link
            has_attachment = True
            has_link = True
            has_image = True if "image" in fileinfo["mimetype"] else False

            file_user = [
                iterate_user
                for iterate_user in users
                if message["user"] == iterate_user["id"]
            ]
            file_user_email = get_user_email(file_user[0], domain_name)

            s3_path, content_for_link = get_attachment_path_and_content(
                fileinfo, realm_id
            )
            markdown_links.append(content_for_link)

            # construct attachments
            build_uploads(
                added_users[user],
                realm_id,
                file_user_email,
                fileinfo,
                s3_path,
                uploads_list,
            )

            build_attachment(
                realm_id,
                {message_id},
                added_users[user],
                fileinfo,
                s3_path,
                zerver_attachment,
            )
        else:
            # For attachments with link not from slack
            # Example: Google drive integration
            has_link = True
            if "title" in fileinfo:
                file_name = fileinfo["title"]
            else:
                file_name = fileinfo["name"]
            markdown_links.append("[%s](%s)" % (file_name, fileinfo["url_private"]))

    content = "\n".join(markdown_links)

    return dict(
        content=content,
        has_attachment=has_attachment,
        has_image=has_image,
        has_link=has_link,
    )