Migrating Skype history to Slack

A flexible data parsing and analytics tool can do pretty much anything, especially if it's something you suddenly and urgently need. Like migrating your team and all your conversations from Skype to Slack. We like Skype but it’s less and less a tool meant for professional teams building a product and talking to their users. It looks like Slack is winning the race in this space so here we go.

Here's the “wait but…” question: can you import your Skype chat history to Slack? A few rounds in Google tell you that there is indeed a Slack import tool for pulling existing messages and members, eg from a CSV or text file.  However, getting your Skype chat history to .csv or text looks like voodoo that the Slack community is still searching for

Enter SpectX. Here are the steps and the script that do the trick on OSX. Your message formatting (bold, italics, code) and emoticons will be safe and stay visible on Slack. 

  1. Get SpectX (you can easily do the next steps with the free 30-day trial)
  2. Make sure the following settings are enabled in conf/sx.conf (restart to make changes effective):
    1. engine.fs_access=true
    2. engine.fs_unmanaged_access=true
    3. engine.db_table.allowed_jdbc_drivers=org.sqlite.JDBC
  3. Specify your local machine and Skype usernames in the init() block
  4. When working on Windows / Linux, replace the URL data on the first line.
  5. Run @list_titles to list all the chat titles.
  6. Choose a title (double click, then copy to the clipboard) and paste it to the chat_title value
  7. Execute @export: comment out @list_titles, uncomment @export and Run.
  8. Save result as CCSV (from the SpectX upper menu Save/Result As/CCSV)
  9. Import to Slack using their import tool.
init(localuser:'osx_user', skypeuser:'skype_user');

$bodyPattern=<<<EOP
  $smile='<ss type=' DQS:smile_type LD*:text '</ss>' <'ss'>:type;
  $href='<a href='   DQS '>' DATA:text '</a>'       <'href'>:type;
  $object=('<URIObject' LD '>' LD '<a href=' DQS '>' LD:text '</a>' LD '</URIObject>' ) <'href'>:type;
  $sText='<s raw_pre' LD '>' DATA:text '</s>'       <'s'>:type;
  $bText='<b raw_pre' LD '>' DATA:text '</b>'       <'b'>:type;
  $iText='<i raw_pre' LD '>' DATA:text '</i>'       <'i'>:type;
  $code='<pre raw_pre'LD '>' DATA:text '</pre>'     <'code'>:type;;
  $default=[!<]{0,128000}:text                       <'default'>:type;
  ARRAY{($code | $smile | $href | $sText | $bText | $iText | $object | $default)}{0,64}:tokens EOF
EOP;

$skype2slack(html_message, tokens)=CREATE FUNCTION(
  language:'javascript',
  returns::string,
  code:<<<END_OF_JS
 
if (tokens == null) return html_message; // in case parser failed.
  if (tokens.length == 1 && tokens[0]['type'] == 'default') return html_message;
  var res = ""; 
  for(i=0; i<tokens.length; i++) { res += token2str(tokens[i]); }
  return res;

  function token2str(token) {
      switch(token['type']) {
      case 'default': return token['text'];
      case 'href': return token['text'];
      case 'code': return '```' + token['text'] + '```';  
      case 's': return '~' + token['text'] + '~';
      case 'b': return '*' + token['text'] + '*';
      case 'i': return '_' + token['text'] + '_';
      case 'ss': return smile(token['smile_type']);
      default: return token;
  }
  }

  function smile(smile_type) {
    switch(smile_type) {
      case 'laugh': return ':laughing:';
      case 'sad': return ':unamused:';
      case 'tongueout': return ':tongue:';
      case 'music': return ':musical_note:';
      case 'yes': return ':thumbsup:';
      case 'wait': return ':face_with_rolling_eyes:';
      case 'worry': return ':worried:';  
    }
    return ':' + smile_type + ':';
  }
  END_OF_JS
);

$db_uri = 'jdbc:sqlite:file:' + '/Users/' + $localuser + '/Library/Application%20Support/Skype/' + $skypeuser + '/main.db';

@chat_ids(chat_title)=DB_TABLE(uri:$db_uri, table:'Conversations')
  .filter(displayname = $chat_title)
  .select(identity)
;

@export(chat_title)=DB_TABLE(uri:$db_uri, table:'messages')
  .filter(chatname IN (@chat_ids($chat_title)) AND (type = 61 or type = 201))
  .select(*, text:replace(HTMLUNESCAPE(body_xml), '&apos;', '\''))
  .select(timestamp, chatname, author, text:$skype2slack(text, parse($bodyPattern, text)))
  .sort(timestamp)
;

@list_titles = DB_TABLE(uri:$db_uri, table:'Conversations').select(chat_title:displayname);

@list_titles
//@export('Selected chat title')

It took about 10 minutes to create this script on SpectX. Another 5 to add support to the unique CSV format preferred by Slack  (it’s CSV but with C/JSON-style strings that require extra effort to escape special symbols). We named it CCSV - you can now convert data into this using both the SpectX UI as well as API calls.

The next question: can you talk to your logs in Slack? Stay tuned and follow us on Twitter.

Back to articles