[slack-sdk] 특정 채널에 업로드된 업로드 파일 목록 가져오기

1.슬랙 > 특정 채널 (원하는 채널) > 채널에 업로드 되어 있는 파일 정보(목록) 가져오는 방법입니다.

워크스페이스 전체가 아닌, 개설된 (개설한) 특정 채널의 업로드된 첨부 파일의 목록을 가져오는 코드 입니다.

python slack_sdk 패키지를 이용합니다. ( https://pypi.org/project/slack-sdk/ )

 

2.업로드 된 파일 목록을 조회 하고, 업로드한 사용자 정보를 매칭 하기 위해 2개 API 를 사용 합니다. 

 

https://api.slack.com/methods/conversations.history
https://api.slack.com/methods/users.info

 

API 호출은 다음과 같습니다.

 

1. 업로드된 파일 목록을 알고 싶은 채널의 대화 기록에서
2. 타입이 '파일' 인 것, 즉 첨부된 파일 가져오기 (conversations.history)
3. 각 파일을 업로드 한 사용자를 매칭하여 사용자의 세부 정보를 붙히기 (users.info)
4. 최종 업로드 파일, 업로드한 사용자 정보 출력

 

대화 기록의 목록을 가져올때는 (conversations.history) 설정 해야 하는 파라미터는 3개 입니다. 

 

Slack API 설명에는 limit 파라미터 옵션이라 되어 있지만, 대화의 개수에 포함된 첨부 파일을 가져오므로 지정해서 사용이 사실상 필수 입니다.

 

번호 파라미터 이름  내용 선택 or 필수 여부
1 limit  가져올 대화의 개수 (숫자) 사실상 필수
2 latest  특정 시간 이전의 대화만 가져오기 위한 파라미터 선택
3 oldest  특정 시간 이후의 대화만 가져오고 기 위한 파라미터 선택

 

 

oldest 와 latest 를 설정하면 범위를 지정하여 대화 내용을 가져 오게 되며, 이후 limit 를 에 지정한 숫자 만큼 대화 개수를 가져옵니다.

oldest 와 latest 는 Epoch Unix Timestamp 입니다.

 

테스트를 위한 시간 변환은 https://www.unixtimestamp.com/ 등을 활용 할 수 있습니다.

 

 

3.작성된 코드

bot_token 에 생성한 Bot 의 토큰을 입력하고 실행합니다.

아래의 코드에는 latest, oldest  파라미터는 포함되어 있지 않습니다. 필요한 경우 정의해서 사용 하면 됩니다.

예를 들면 oldest='1693494000', latest='1694358000' 입니다.

__author__ = 'https://github.com/password123456/'
__version__ = '1.0.2-2300828'

import sys
from datetime import datetime
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError


class Bcolors:
    Black = '\033[30m'
    Red = '\033[31m'
    Green = '\033[32m'
    Yellow = '\033[33m'
    Blue = '\033[34m'
    Magenta = '\033[35m'
    Cyan = '\033[36m'
    White = '\033[37m'
    Endc = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'


def get_user_info(token, member_id):
    client = WebClient(token=token)
    try:
        # https://api.slack.com/methods/users.info
        user_info = client.users_info(user=member_id).data

        display_name = user_info['user']['name']
        real_name = user_info['user']['real_name']
        phone = user_info['user']['profile']['phone']
        email = user_info['user']['profile']['email']

        if not display_name:
            display_name = 'null'
        elif not real_name:
            real_name = 'null'
        elif not phone:
            phone = 'null'
        elif not email:
            email = 'null'
            
        return f'"{display_name},{real_name},{email},{phone}"'
    except SlackApiError as e:
        print(f'{Bcolors.Yellow}- Api Error:: {e} {Bcolors.Endc}')
        return None


def get_list_of_uploaded_files_on_channel(token, channel_id):
    client = WebClient(token=token)
    try:
        # https://api.slack.com/methods/conversations.history
        result = client.conversations_history(channel=channel_id)
        conversation_history = result['messages']
        i = 0
        for block in conversation_history:
            if 'files' in block.keys():
                i = i + 1
                for file_list in block['files']:
                    upload_user = file_list['user']
                    upload_user_info = get_user_info(token, upload_user)

                    if not upload_user_info:
                        upload_user_info = 'User not exists'

                    upload_time = file_list['timestamp']
                    record_date = datetime.strptime(str(datetime.fromtimestamp(upload_time, tz=None)), '%Y-%m-%d %H:%M:%S')
                    local_timezone = datetime.now().astimezone().tzinfo
                    local_upload_time = record_date.astimezone(local_timezone)

                    upload_filename = file_list['title']
                    upload_filetype = file_list['filetype']
                    upload_file_preview = file_list['url_private']
                    file_download_url = file_list['url_private_download']

                    result = f'- uploaded_at: {local_upload_time}\n- user_info: {upload_user_info}\n' \
                             f'- filename: {upload_filename}\n- type: {upload_filetype}\n' \
                             f'- upload_preview: {upload_file_preview}\n- download_link: {file_download_url}\n'

                    print(result)

    except SlackApiError as e:
        print(f'{Bcolors.Yellow}- Api Error:: {e} {Bcolors.Endc}')


def main():
    bot_token = 'slack_apps_oauth_token(bot_token)'
    channel = 'Channel number for which you want to know'

    get_list_of_uploaded_files_on_channel(bot_token, channel)


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        sys.exit(0)
    except Exception as e:
        print(f'{Bcolors.Yellow}- ::Exception:: Func:[{__name__.__name__}] '
              f'Line:[{sys.exc_info()[-1].tb_lineno}] [{type(e).__name__}] {e}{Bcolors.Endc}')

 

4.결과 보기

- uploaded_at: 2023-02-01 14:06:30+09:00
- user_info: "k****6,mynameis,****@gmail.com,010-1111-1111"
- filename: 2101254.pdf
- type: pdf
- upload_preview: https://files.slack.com/files-pri/TB37064-F04M9GYES/2101254.pdf
- download_link: https://files.slack.com/files-pri/TB37064-F04M9GYES/download/2101254.pdf

- uploaded_at: 2023-02-01 14:01:12+09:00
- user_info: "k****6,mynameis,****@gmail.com,010-1111-1111"
- filename: blackbean.png
- type: png
- upload_preview: https://files.slack.com/files-pri/TBZ064-F04HRUVS8/blackbean.png
- download_link: https://files.slack.com/files-pri/TBZ064-F04HRUVS8/download/blackbean.png

 

5.유의 사항

채널의 사용자 목록을 확인 하기 위해 봇은 해당 채널에 참가 되어 있어야 합니다.

 

{ "ok": false, "error": "not_in_channel" } 응답이 발생 한다면,  봇이 해당 채널에 참가 되어 있는지 확인 합니다.

참가 되어 있지 않다면 봇을 추가 하여 줍니다.

 

 

봇이 채널에 참여 되어 있는데 코드가 동작되지 않는다면,  API 실행시 필요한 권한을 확인 합니다.

 

번호  API 필요 권한  API 정보
1  conversations.members channels:history
groups:history
im:history
mpim:history
https://api.slack.com/methods/conversations.history
2  users.info users:read https://api.slack.com/methods/users.info

 

 

API 스펙에 정의된 필요 권한을 넣었으나 되지 않는 경우는,  API 에러 에서 출력되는 필요 권한 (무슨 권한이 필요하다고 표시 됩니다.) 을 추가 합니다.

 

슬랙 API 문서에는 API 를 응용, 구현 했을때 필요 권한이 충분히 설명 되어 있지 않는 경우가 있습니다.

 

예를 들면, 채널의 정보를 접근 하기 위해 channels:read 를 추가 하였고, 봇도 join 하였는데, 실행이 되지 않고, API 응답에서 channels:join 을 요구 하는 경우 > channels:join 권한 추가 > 해결

 

 

위 2개 API 와 다른 API 몇개를 조합하면 특정 채널에서 대화 기록을 기록하고, 추적 하는 어플리케이션을 만들 수 있습니다.

 

API 를 사용 할 때는 책임과 권한을 잘 인지 하고 사용 해야 합니다.