Giter Club home page Giter Club logo

slack-backup's Introduction

Slack backup

https://travis-ci.org/gryf/slack-backup.svg?branch=master

This project has been archived.

The project aim is to collect conversations from Slack using its API and optionally user account information, and provides convenient way to represent as a log.

Requirements

This project is written in Python 3, 3.4 to be precise (currently it works with version 3.6), although it may work on earlier version of Python3. Sorry no support for Python2.

Other than that, required packages are as follows:

  • slackclient 1.0.2
  • SQLAlchemy 1.0.10

Installation

You can install it using pip install slack-backup command. Recommended way is to create virtualenv, like so:

user@localhost $ virtualenv -p python3 myenv
Running virtualenv with interpreter /usr/bin/python3
Using base prefix '/usr'
New python executable in foobar/bin/python3
Also creating executable in foobar/bin/python
Installing setuptools, pip, wheel...done.
user@localhost $ . myenv/bin/activate
(myenv)user@localhost $ pip install slack-backup

You can also get this repository and install from it, like:

user@localhost ~ $ virtualenv -p python3 myenv
Running virtualenv with interpreter /usr/bin/python3
Using base prefix '/usr'
New python executable in foobar/bin/python3
Also creating executable in foobar/bin/python
Installing setuptools, pip, wheel...done.
user@localhost $ . myenv/bin/activate
(myenv)user@localhost ~ $ cd myenv
(myenv)user@localhost ~/myenv $ git clone https://github.com/gryf/slack-backup
(myenv)user@localhost ~/myenv $ cd slack-backup
(myenv)user@localhost ~/myenv/slack-backup $ pip install .

Usage

There is a commandline tool called slack-backup, which typical use would get to gather the data and generate logs. Using example from above, here is a typical session:

(myenv)user@localhost ~/myenv/slack-backup $ mkdir ~/mylogs && cd ~/mylogs
(myenv)user@localhost ~/mylogs $ slack-backup fetch \
--token xxxx-1111111111-222222222222-333333333333-r4nd0ms7uff \
--user [email protected] --password secret --team myteam \
-qq -d mydatabase.sqlite

where:

  • --token is generated on Slack side token for interaction with the API. It's required.
  • --user is your slack account username…
  • --password …and password. Those two are needed if you care about files posted on the channels, which are hosted on Slack servers. They can be skipped, if you don't care about such files. Avatars still be downloaded though. External resources will not be downloaded - they have URL anyway.
  • --team team name. It is the part of the URL for your slack team; in other words in URL like http://foobar.slack.com foobar is the team name.
  • -q (or --quiet) will suppress any messages from program. In contrary there can be used --verbose to increase verbosity. Using this option several times (up to three, above the number will have no effect) will amplify effectiveness of either be quite or be verbose behaviour.
  • -d or --database is the file path for database (which for now at least is an sqlite database file). It can be omitted - in-memory db would be created, but you'll (obviously) lost all the records. Besides the db file, assets directory might be created for downloadable items.

You can also specify directory, where pure response JSONs from Slack API will be stored by using -r/--raw-dir or by providing it in config file in fetch section as raw_dir (note the underscore in config file contrary to the swith, which have hyphen between raw and dir). This might be useful for debugging purposes.

There is one more switch to take into consideration - -f/--url-file-to-attachment which influence the way how external file share would be treated. First of all, what is external file share from slack point of view, one could ask. Slack have some sort of integration with Google services, like Google Drive, which provide slack users to create or "upload" files from Google Drive. "Upload", since no uploading actually takes place, and only URL is provided for such "uploads". By default slack-backup will create a file which is prefixed manual_download_ which will contain URL and destination path to the file, where user should manual download file to. Example file contents:

http://foo.bar.com/some/file --> assets/files/83340cbe-fee2-4d2e-bdb1-cace9c82e6d4
http://foo.bar.com/some/other/file --> assets/files/8a4c873c-1864-4f1b-b515-bbef119f33a3
http://docs/google.com/some/gdoc/file --> assets/files/ec8752bc-0bf8-4743-a8bd-9756107ab386

By setting --url-file-to-attachment flag (or making an option url_file_to_attachment set to true in config file) such "uploads" would be internally converted into Slack "attachment", which internally is an object to store external links, so there is no need for user interaction.

During DB creation, all available messages are stored in the database. On the next run, fetch would only take those records, which are older from currently oldest in DB. So that it will only fetch a subset of the overall of the messages. As for the channels and users - complete information will be downloaded every time fetch command would be used.

Next, to generate a log files:

(myenv)user@localhost ~/mylogs $ slack-backup generate \
-v -d mydatabase.sqlite --format text -o logs

where:

  • --format is the desired format of the logs. For now only text format of the logs is supported (IRC style format). Format none will produce nothing.
  • -o or --output is the destination directory, where logs and possible assets will land.

The rest of the options (-d and -v) have same meaning as in fetch command.

See help for the slack-backup command for complete list of options.

Configuration

For convenience, you can place all of needed options into configuration file (aka .ini), which all options (with their defaults) will look like:

[common]
channels =
database =
quiet = 0
verbose = 0

[generate]
output =
format = text
theme = plain

[fetch]
url_file_to_attachment = false
user =
password =
team =
token =
raw_dir =

Note, that you don't have to put every option. To illustrate fetch example from above, here is a corresponding config file:

[common]
database = mydatabase.sqlite
quiet = 2

[fetch]
user = [email protected]
password = secret
team = myteam
token = xxxx-1111111111-222222222222-333333333333-r4nd0ms7uff

Note, that only [common] and [fetch] sections are provided, so it is enough to invoke slack-backup command as:

(myenv)user@localhost ~/mylogs $ slack-backup fetch

There are couple of places, where configuration file would be searched for, in particular order:

  • file provided via argument -i or --config
  • slack-backup.ini in current directory
  • $XDG_CONFIG_HOME/slack-backup.ini, where $XDG_CONFIG_HOME usually defaults to $HOME/.config

Details

During first run, database with provided name is generated. For ease of use sqlite database is used, although it is easy to switch the engine, since there is an ORM (SQLAlchemy) used.

Slack users, channels and messages are mapped to SQLAlchemy models, as well as other information, like:

  • user profiles
  • channel topic
  • channel purpose
  • message reactions
  • message attachments
  • and files

Channels and users are always synchronized in every run, so every modification to the user or channels are overwriting old data. During first run, all messages are retrieved for all/selected channels. Every other run will only fetch those messages, which are older then newest message in the database - so that we don't loose any old messages, which might be automatically removed from Slack servers. The drawback of this behaviour is that all past messages which was altered in the meantime will not be updated.

License

This work is licensed on 3-clause BSD license. See LICENSE file for details.

slack-backup's People

Contributors

gryf avatar lhl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

slack-backup's Issues

ValueError when using Generate

The generate command crashed mid-way thru creating log files with a ValueError. Looking at the original Slack thread and comparing it to the outputted log file, it appears to have crashed when it tried to process a link to a Google docs spreadsheet stored on a user's Google Drive. Here is the error message:

2018-05-03 15:59:36,509 INFO: Found configuration file: ./slack-backup.ini
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\Scripts\slack-backup", line 10, in
command.main()
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\command.py", line 141, in main
args.func(args)
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\command.py", line 56, in generate_raport
slack.generate_history()
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\client.py", line 144, in generate_history
self.reporter.generate()
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\reporters.py", line 197, in generate
self.write_msg(messages, log_path)
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\reporters.py", line 79, in write_msg
data = self._process_message(message)
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\reporters.py", line 214, in _process_message
data = super(TextReporter, self)._process_message(msg)
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\reporters.py", line 108, in _process_message
data = processor(msg)
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\reporters.py", line 233, in _msg_file
') ' + msg.file.title, msg.text),
File "C:\ProgramData\Anaconda3\lib\pathlib.py", line 719, in as_uri
raise ValueError("relative path can't be expressed as a file URI")
ValueError: relative path can't be expressed as a file URI

Missing Scope error

I get this error after running the script with the required options

2018-09-16 11:14:12,780 ERROR: missing_scope
2018-09-16 11:14:13,119 ERROR: missing_scope

Upon inspecting the sqlite db, it was found to be empty.

Failed to login into Slack app

i allways got this error even my password and user are correct
ERROR: Failed to login into Slack app
any solution?
thanks

Outputs - Grouping replies and Generating json files

  1. Is there a way to group the replies with the original post and note them as replies? Currently it appears that the replies are are treated as regular posts and filed chronologically.

  2. Have you considered providing a second alternative to the generate function? I like the text option as it makes it easy for searching, but I would also like the ability to view the output using: https://github.com/mcoster/slack-export-viewer This requires the output in json files.

python type error

This occurred while running the slack-backup script ver 0.7.

Traceback (most recent call last):
  File "/Users/user/myenv/bin/slack-backup", line 10, in <module>
    command.main()
  File "/Users/user/myenv/lib/python3.7/site-packages/slack_backup/command.py", line 143, in main
    args.func(args)
  File "/Users/user/myenv/lib/python3.7/site-packages/slack_backup/command.py", line 62, in fetch_data
    slack.update()
  File "/Users/user/myenv/lib/python3.7/site-packages/slack_backup/client.py", line 74, in update
    self.update_history()
  File "/Users/user/myenv/lib/python3.7/site-packages/slack_backup/client.py", line 166, in update_history
    self._create_message(msg, channel)
  File "/Users/user/myenv/lib/python3.7/site-packages/slack_backup/client.py", line 275, in _create_message
    self._file_data(message, data['item'])
  File "/Users/user/myenv/lib/python3.7/site-packages/slack_backup/client.py", line 304, in _file_data
    message.file.filepath = self.downloader.download(priv_url, 'file')
  File "/Users/user/myenv/lib/python3.7/site-packages/slack_backup/download.py", line 88, in download
    shutil.move(temp_file, filepath)
  File "/Users/user/myenv/lib/python3.7/shutil.py", line 546, in move
    if os.path.isdir(dst):
  File "/Users/user/myenv/bin/../lib/python3.7/genericpath.py", line 42, in isdir
    st = os.stat(s)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not NoneType

raw_dir and not producing "empty files"

Excerpt from @aberja :

I was referring to the possibility of not creating a file if the server returned an empty list [...]

Excerpt from @gryf :

It's strictly debugging purpose feature, but I think about that. If you think, that it's a must-have behaviour, please fill another issue for it, so we could have an easy tracking.

Originally posted by @gryf in #8 (comment)

'slack-backup' is not recognized

When I run "slack-backup fetch" from Anaconda Prompt in Windows 10, I receive the following error message:

'slack-backup' is not recognized as an internal or external command, operable program or batch file.

I've created an .ini file with the required options. I've also tried running the fetch command with all of the options directly after fetch.

I can access other scripts without any issue. For example, when I run "conda list", I can see I have the following installed:

slack-backup 0.7
slackclient 1.1.3
SQLAlchemy 1.1.13

I've also confirmed that I have slack-backup in the Scripts folder.

Any idea what the issue might be and how I can resolve it?

Thanks,
Richard

OSError: [Errno 22] Invalid argument

when I run slack-backup for the first time, it creates 2 folders (files & images) and 1 file slackrw.sqlite. It then downloads 12 images to the images folder and returns the following error:

Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\Scripts\slack-backup", line 10, in
command.main()
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\command.py", line 141, in main
args.func(args)
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\command.py", line 62, in fetch_data
slack.update()
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\client.py", line 53, in update
self.update_channels()
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\client.py", line 69, in update_channels
channel = o.Channel()
File "", line 4, in init
File "C:\ProgramData\Anaconda3\lib\site-packages\sqlalchemy\orm\state.py", line 414, in _initialize_instance
manager.dispatch.init_failure(self, args, kwargs)
File "C:\ProgramData\Anaconda3\lib\site-packages\sqlalchemy\util\langhelpers.py", line 66, in exit
compat.reraise(exc_type, exc_value, exc_tb)
File "C:\ProgramData\Anaconda3\lib\site-packages\sqlalchemy\util\compat.py", line 187, in reraise
raise value
File "C:\ProgramData\Anaconda3\lib\site-packages\sqlalchemy\orm\state.py", line 411, in _initialize_instance
return manager.original_init(*mixed[1:], **kwargs)
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\objects.py", line 87, in init
self.update(data_dict)
File "C:\ProgramData\Anaconda3\lib\site-packages\slack_backup\objects.py", line 94, in update
self.created = datetime.fromtimestamp(data_dict.get('created', 0))
OSError: [Errno 22] Invalid argument

I don't see any log files. Should they be in mylogs folder? What number should I set quiet to in common to generate logs. I've tried 2 and 0.

I'm not sure if you are able to resolve this without having access to the data, but I thought I would ask if you have any ideas what is happening and how to resolve it?

Thanks,
Richard

Script fails due to error

Hi! I've tried to use your script, but it fails for some reason. Can you take a look at error log below and fix it? @gryf


2017-08-05 14:39:20,567 INFO: Skipping message from `kotlyar' since it's empty
Traceback (most recent call last):
  File "/home/odmin/myenv/lib/python3.5/site-packages/slack_backup/client.py", line 152, in _create_message
    filter(o.User.slackid == data['user']).one()
KeyError: 'user'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/odmin/myenv/bin/slack-backup", line 10, in <module>
    command.main()
  File "/home/odmin/myenv/lib/python3.5/site-packages/slack_backup/command.py", line 118, in main
    args.func(args)
  File "/home/odmin/myenv/lib/python3.5/site-packages/slack_backup/command.py", line 39, in fetch_data
    slack.update()
  File "/home/odmin/myenv/lib/python3.5/site-packages/slack_backup/client.py", line 53, in update
    self.update_history()
  File "/home/odmin/myenv/lib/python3.5/site-packages/slack_backup/client.py", line 132, in update_history
    self._create_message(msg, channel)
  File "/home/odmin/myenv/lib/python3.5/site-packages/slack_backup/client.py", line 155, in _create_message
    filter(o.User.slackid == data['comment']['user']).one()
KeyError: 'comment'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.