Pull to refresh

Экспорт истории сообщений из Skype

Reading time4 min
Views32K
Многие пользователи Skype в Linux замечали насколько неудобно там сделана работа с историей сообщений чата. Нет нормального поиска, сообщения за длительный период времени грузятся очень долго. Нет возможности экспорта в другие форматы/клиенты.

Skype для Linux хранит историю сообщений в недокументированном бинарном формате. Несмотря на то что энтузиасты расковыряли его довольно давно, еще многое остается неизвестным.

Поверхностный поиск готового решения для экспорта истории сообщений не привел к успеху. Поэтому я, собрав всю доступную информацию, написал своё.

Skype API

Первой мыслью было использовать Skype API через D-Bus интерфейс. Казалось бы, есть команда «SEARCH CHATS», но почему-то у меня не получилось её заставить выдавать все чаты. Подозреваю, что она для этого и не предназначена. Skype API достаточен чтобы оперировать текущими событиями, но для доступа к истории надо искать другое решение. Поддержка так и пишет, что возможность экспорта через API в планах не стоит https://jira.skype.com/browse/SPA-596.

DBB файлы

Значит единственный выход это извлечь сообщения из файлов профиля. Не знаю по какой причине, но для хранения данных инженеры Skype придумали довольно странный велосипед. С 4ой версии клиента они одумались и перешли на SQLite, но для Linux пока есть только 2ая со старым форматом.

Данные хранятся в папке профиля в файлах nameXXX.dbb. Каждый файл содержит записи фиксированного размера «степень двойки»+8. Размер записи округляется вверх до ближайшей степени двойки (не меньше 256) и запись пишется в соответствующий файл.

Таким образом, файл chatmsg512.dbb состоит из блоков по 512+8=520 байт в которых содержатся записи длиной между 256 и 512 байт.

Я с трудом представляю для какой задачи такой формат будет эффективным. Из-за округления получаются неиспользуемые дырки, что приводит к неоправданному увеличению размера. Для примера, в моей базе из 21500 сообщений 23.5% места потеряно на округлении, в среднем 73 байта на сообщение. При таком вольном обращении со свободным местом, несколько странно выглядит семибитная кодировка чисел (см ниже). Наконец, так как сообщения пишутся в разные файлы, перед каким-то осмысленным использованием их надо объединять и сортировать, что тоже не прибавляет скорости.

Формат записи

Запись состоит из заголовка и тела. Заголовок имеет длину 17 байт (семнадцать).
4 байта магическое значение «l33l»
4 байта размер записи 32-bit int
4 байта идентификатор 32-bit int
5 байт неизвестно

Далее следуют поля трёх типов 0x00 — число в семибитной кодировке, 0x03 — строка, 0x04 — блок двоичных данных. Каждое поле помимо типа данных содержит тип поля также в семибитной кодировке.

Типы полей
0x00 — тип данных (число)
7bit number — тип поля
7bit number — значение поля

0x03 — тип данных (строка)
7bit number — тип поля
null-terminated string — значение поля

0x04 — тип данных (blob)
7bit number — тип поля
7bit blob size — длина поля
binary blob — значение поля

Семибитная кодировка переменной длины
В каждом байте старший бит указывает является ли этот байт последним (1 — нет, 0 — да). Остальные 7 бит значащие. Чтобы получить число надо склеить 7 битные блоки в порядке big-endian.

Скрипт skypelog.py

Питон скрипт/модуль, который читает DBB файлы можно взять с GitHub https://github.com/Vayu/skypelog.
В модуле собрана известная на данный момент информация об именах полей записей различных типов: SkypeMsg, SkypeAcc, SkypeContact.

Прямой запуск скрипта позволяет экспортировать содержимое файлов chatmsgXXX.dbb в JSON или простой HTML:
  • JSON предназначен для последующей обработки внешними программами и сохраняет всю историю аккаунта в один файл. Есть два варианта: «full» экспортирует все известные поля и «compact» экспортирует минимальный набор «дата, имя, сообщение».
  • HTML создаёт файлы с историей сообщений для каждой пары аккаунт-контакт. Например vasya-petya.html и vasya-masha.html. К сожалению, структура записей для групповых чатов пока до конца не ясна.
Пример использования skypelog.py в качестве модуля:
#!/usr/bin/env python
from skypelog import *
data = SkypeDBB("/home/user/.Skype/account/call256.dbb")
    for r in data.records():
        print r
Более длинный пример apiuse.py на GitHub.

Заключение

Как видно из примера выше, skypelog.py существенно упрощает исследование формата DBB. Имена полей пока известны (угаданы), только для нескольких типов записей:
chatmsgXXX.dbb — сообщения чата, класс SkypeMsg
profileXXX.dbb — учетные записи, класс SkypeAcc
userXXX.dbb — контакты, класс SkypeContact

Желающие приглашаются к угадыванию пока неизвестных значений полей в следующих файлах:
alertXXX.dbb — системные сообщения
chatXXX.dbb — список чатов
chatmemberXXX.dbb — список участников чата (?)
transferXXX.dbb — список переданных файлов
callXXX.dbb — лог звонков
callmemberXXX.dbb — список участников звонка (?)
voicemailXXX.dbb — голосовая почта

Более подробное обсуждение формата (англ)
Neal Krawetz blog — Skype Logs
Neal Krawetz blog — Skype Logs discussion

PS1: Судя по отзывам в комментариях «SEARCH CHATS» раньше работала, возможно зависит от версии Skype. Желающие могут попробовать следующий код:
(нужен dbus модуль для Python)
#!/usr/bin/env python
import dbus
import sys
try:
    skype = dbus.SystemBus().get_object('com.Skype.API''/com/Skype')
except:
    try:
        skype = dbus.SessionBus().get_object('com.Skype.API''/com/Skype')
    except:
        print "Can't find Skype API"
        sys.exit()
 
print skype.Invoke("NAME python")
print skype.Invoke("PROTOCOL 9999")
print skype.Invoke("SEARCH CHATS")
Tags:
Hubs:
Total votes 56: ↑52 and ↓4+48
Comments51

Articles