Skip to content

Commit 2edc90b

Browse files
committed
Backup files as well as messages
1 parent d065ea9 commit 2edc90b

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# slack-backup-python
22
Exporting slack channels, conversation using Web API
33

4+
```pip3 install requests```
45
```pip3 install slack-sdk```
56

67
```python3 backup.py --token 'xoxp-8910951619-266447157124-433342496065-687a1ceaea9046688ff28bde02bada5c' --outDir './out'```

app_constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010
USER_LIST_FILE = '/users.json'
1111
ONE_TO_ONE_CONVERSATION_DIRECTORY = '/one-to-one'
1212
ONE_TO_ONE_CONVERSATION_HISTORY_FILE = ONE_TO_ONE_CONVERSATION_DIRECTORY+'/{0}-{1}.json'
13+
FILE_LIST_FILE = '/files.json'
14+
FILES_DIRECTORY = '/files'
15+
FILES_FILENAME = FILES_DIRECTORY + '/{id} - {author} ({user}) at {date}: {name}'

backup.py

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import os
22
import argparse
3+
import datetime
34
import json
5+
import requests
46
import app_constants as APP_CONSTANTS
57
from slack_sdk import WebClient
68
from slack_sdk.errors import SlackApiError
@@ -41,20 +43,26 @@ def readRequestJsonFile():
4143
jsonObj = json.load(file)
4244
return jsonObj
4345

44-
45-
def writeJSONFile(jsonObj, filePath):
46-
outputPath = getOutputPath(filePath)
46+
def makedirPath(outputPath):
4747
dirPath = os.path.dirname(outputPath)
4848
if not os.path.exists(dirPath):
4949
os.makedirs(dirPath)
5050

51+
def writeJSONFile(jsonObj, filePath):
52+
outputPath = getOutputPath(filePath)
53+
makedirPath(outputPath)
5154
with open(outputPath, 'w+') as file:
5255
json.dump(jsonObj, file, indent=True)
5356

5457
def getUsers():
5558
response = client.users_list()
5659
return response['members']
5760

61+
def lookupUser(users, userID):
62+
for u in users:
63+
if u['id'] == userID:
64+
return u
65+
5866
def getChannels():
5967
response = client.conversations_list(types='public_channel,private_channel')
6068
return response['channels']
@@ -79,6 +87,42 @@ def getConversationHistory(channelId):
7987
params['latest'] = msgs[-1]['ts']
8088
return msgs
8189

90+
def getFileList():
91+
params = { 'count': 100, 'show_files_hidden_by_limit': True, 'page': 1}
92+
files = []
93+
while True:
94+
response = client.files_list(**params)
95+
if not response['ok']:
96+
break
97+
98+
files.extend(response['files'])
99+
100+
if response['paging']['pages'] <= params['page']:
101+
break
102+
params['page'] += 1
103+
104+
return files
105+
106+
def downloadFiles(users):
107+
files = getFileList()
108+
writeJSONFile(files, APP_CONSTANTS.FILE_LIST_FILE)
109+
110+
for file in files:
111+
url = file['url_private_download']
112+
r = requests.get(url, headers={'Authorization': 'Bearer ' + token}, stream=True)
113+
r.raise_for_status()
114+
115+
file['date'] = datetime.datetime.fromtimestamp(file['timestamp']).strftime('%Y-%m-%d %H:%M:%S')
116+
file['author'] = lookupUser(users, file['user'])['name']
117+
filename = APP_CONSTANTS.FILES_FILENAME.format(**file)
118+
119+
print('Downloading to ' + filename)
120+
121+
outputPath = getOutputPath(filename)
122+
makedirPath(outputPath)
123+
with open(outputPath, 'wb') as f:
124+
for chunk in r.iter_content(chunk_size=32*1024):
125+
f.write(chunk)
82126

83127
def run():
84128
channels = getChannels()
@@ -128,5 +172,7 @@ def run():
128172
APP_CONSTANTS.ONE_TO_ONE_CONVERSATION_HISTORY_FILE, userName, userId)
129173
writeJSONFile(conversationHistory, conversationHistoryFilename)
130174

175+
downloadFiles(users)
176+
131177
if __name__ == '__main__':
132178
run()

0 commit comments

Comments
 (0)