Как и Skype — Linux-клиент Viber хранит данные в локальной SQLite базе:
$ ls -l ~/.ViberPC/38096***26/ | grep db -rw-r--r-- 1 setevoy setevoy 38912 Jun 30 15:30 data.db -rw-r--r-- 1 setevoy setevoy 32768 Jul 10 10:38 data.db-shm -rw-r--r-- 1 setevoy setevoy 1048032 Jul 10 10:38 data.db-wal -rw-r--r-- 1 setevoy setevoy 5072896 Jul 10 09:59 viber.db -rw-r--r-- 1 setevoy setevoy 32768 Jul 10 10:15 viber.db-shm -rw-r--r-- 1 setevoy setevoy 2329736 Jul 10 10:15 viber.db-wal
История чатов лежит в базе viber.db.
Задача — бекапить по крону чат с одним контактом, и записывать его в текстовый файл.
Содержание
SQLite
Сначала — проверяем вручную, потом добавим скрипт.
Подключаемся к базе:
[simterm]
$ cd ~/.ViberPC/38096***26 $ sqlite3 viber.db SQLite version 3.19.3 2017-06-08 14:26:16 Enter ".help" for usage hints. sqlite>
[/simterm]
Таблицы тут:
[simterm]
sqlite> .tables Calls ChatsMetaData Events RecycleBin ChatInfo Contact EventsMetaData Settings ChatRecovery DownloadFile LikeRelation UploadFile ChatRelation EventInfo Messages Versions
[/simterm]
Нас интересует eventinfo, получаем её описание:
[simterm]
sqlite> pragma table_info(eventinfo); 0|EventID|integer|0||0 ... 33|EncryptedNumber|TEXT|0||0 34|Number|TEXT|0||0
[/simterm]
И Contact:
[simterm]
sqlite> pragma table_info(contact); 0|ContactID|integer|0||1 1|Name|TEXT|0||0 2|ABContact|smallint (0,1)|1|0|0 3|SortName|TEXT|0||0 4|Number|TEXT|0||0 5|ViberContact|smallint (0,1)|1|0|0 6|ClientName|TEXT|0||0 7|DownloadID|TEXT|0||0 8|EncryptedNumber|TEXT|0||0 9|MID|TEXT|0||0 10|VID|TEXT|0||0 11|ContactFlags|long|0|0|0
[/simterm]
Находим пользователя и ID:
[simterm]
sqlite> select name, mid from contact where name='Имя'; Имя|O6ZfYO7jST4=
[/simterm]
Теперь, используя этот ID — находим все сообщения пользователя:
[simterm]
sqlite> select datetime(timestamp, 'unixepoch'), chattoken, body from eventinfo where chattoken like "O6ZfYO7jST4=%" order by timestamp;
[/simterm]
Либо выводим только последние 2 записи:
[simterm]
sqlite> select datetime(timestamp, 'unixepoch'), chattoken, body from eventinfo where chattoken like "O6ZfYO7jST4=%" order by timestamp desc limit 2; 2017-07-10 07:15:46|O6ZfYO7jST4=1494955353356|Согласна 2017-07-10 07:15:28|O6ZfYO7jST4=1494955353356|Господи, ненавижу разговорчивых таксистов... Не умолкает, сцуко!
[/simterm]
Либо сообщения только за сегодня:
[simterm]
sqlite> select datetime(timestamp, 'unixepoch'), chattoken, body from eventinfo where chattoken like "O6ZfYO7jST4=%" and datetime(timestamp, 'unixepoch') like "2017-07-10%" order by timestamp; 2017-07-10 06:07:37|O6ZfYO7jST4=1494955353356| 2017-07-10 06:16:06|O6ZfYO7jST4=1494955353356| 2017-07-10 06:16:10|O6ZfYO7jST4=1494955353356|утречка 2017-07-10 07:15:28|O6ZfYO7jST4=1494955353356|Господи, ненавижу разговорчивых таксистов... Не умолкает, сцуко! 2017-07-10 07:15:46|O6ZfYO7jST4=1494955353356|Согласна
[/simterm]
Python — скрипт бекапа
И последним шагом — небольшой python-скрипт для бекапа чатов с этим контактом:
#!/usr/bin/env python
import os
import sys
import sqlite3
import datetime
# phone number to find path
# i.e. /home/setevoy/.ViberPC/380968889900
if len(sys.argv) < 2:
print('ERROR: specify your cell num as first argument.')
exit(1)
# some globals
db_name = 'viber.db'
dbpath = '/home/setevoy/.ViberPC/'
contact_name = "Имя"
back_path = '/home/setevoy/Backups/ViberChats'
def get_mid():
"""Get contact's MID"""
cur = conn.cursor()
mid = cur.execute("""select name, mid from contact where name='{}';""".format(contact_name))
for i in mid:
return(i[1])
def get_todays_history(mid):
"""Select all messages for today from Contact's MID"""
cur = conn.cursor()
history_today = cur.execute("""select datetime(timestamp, 'unixepoch'), chattoken, body \
from eventinfo where chattoken like '{mid}%' and datetime(timestamp, 'unixepoch') like "{day}%" \
order by timestamp""".format(mid=mid, day=today));
return history_today
def save_history():
"""Save all todays messages to /home/setevoy/Backups/ViberChats/Name_datetime"""
mid = get_mid()
back_file = contact_name + "_" + today
if not os.path.isdir(back_path):
print('WARNING: o {} directory found, creating.').format(back_path)
os.mkdir(back_path)
else:
print("OK: {} found.".format(back_path))
os.chdir(back_path)
with open(back_file, 'w') as bf:
for mes in get_todays_history(mid):
data = "{}\n".format(mes)
bf.write(data)
if __name__ == "__main__":
my_num = sys.argv[1]
# Create database connection,
conn = sqlite3.connect(os.path.join(dbpath, my_num, db_name))
# 2017_07_10
today = datetime.datetime.now().strftime('%Y_%m_%d')
save_history()
Скрипт можно взять тут>>> (с небольшим изменением — Имя контакта передаётся вторым аргументом).
Его выполнение:
[simterm]
$ ./viber_backup.py 38096***6 OK: /home/setevoy/Backups/ViberChats found.
[/simterm]
Проверяем:
[simterm]
$ ls -l ../Backups/ViberChats/ total 4 -rw-r--r-- 1 setevoy setevoy 836 Jul 10 13:34 Имя_2017_07_1
[/simterm]
Содержимое:
[simterm]
$ cat ../Backups/ViberChats/Имя_2017_07_10
('2017-07-10 06:07:37', 'O6ZfYO7jST4=1494955353356', None)
('2017-07-10 06:16:06', 'O6ZfYO7jST4=1494955353356', None)
('2017-07-10 06:16:10', 'O6ZfYO7jST4=1494955353356', 'утречка')
('2017-07-10 07:15:28', 'O6ZfYO7jST4=1494955353356', 'Господи, ненавижу разговорчивых таксистов... \nНе умолкает, сцуко!')
('2017-07-10 07:15:46', 'O6ZfYO7jST4=1494955353356', 'Согласна')
[/simterm]
Последним шагом — добавляем задачу в крон:
[simterm]
$ crontab -e
[/simterm]
0 0 * * * /home/setevoy/Work/RTFM/rtfm/14657/viber_backup.py 38096*****26 Имя
Готово.
Каталог ~/Backups у меня бекапится в AWS S3 с помощью другой утилиты — myBackup.
Из недостатков — смайлики в текстовый файл сохранить проблематично, поэтому они будут None.