444 lines
10 KiB
Dart
444 lines
10 KiB
Dart
import 'package:moxxyv2/service/database/constants.dart';
|
|
import 'package:moxxyv2/service/database/helpers.dart';
|
|
import 'package:moxxyv2/shared/models/preference.dart';
|
|
import 'package:sqflite_sqlcipher/sqflite.dart';
|
|
|
|
Future<void> configureDatabase(Database db) async {
|
|
await db.execute('PRAGMA foreign_keys = OFF');
|
|
}
|
|
|
|
Future<void> createDatabase(Database db, int version) async {
|
|
// XMPP state
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $xmppStateTable (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT
|
|
)''',
|
|
);
|
|
|
|
// Messages
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $messagesTable (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
sender TEXT NOT NULL,
|
|
body TEXT,
|
|
timestamp INTEGER NOT NULL,
|
|
sid TEXT NOT NULL,
|
|
conversationJid TEXT NOT NULL,
|
|
isFileUploadNotification INTEGER NOT NULL,
|
|
encrypted INTEGER NOT NULL,
|
|
errorType INTEGER,
|
|
warningType INTEGER,
|
|
received INTEGER,
|
|
displayed INTEGER,
|
|
acked INTEGER,
|
|
originId TEXT,
|
|
quote_id INTEGER,
|
|
file_metadata_id TEXT,
|
|
isDownloading INTEGER NOT NULL,
|
|
isUploading INTEGER NOT NULL,
|
|
isRetracted INTEGER,
|
|
isEdited INTEGER NOT NULL,
|
|
containsNoStore INTEGER NOT NULL,
|
|
stickerPackId TEXT,
|
|
pseudoMessageType INTEGER,
|
|
pseudoMessageData TEXT,
|
|
CONSTRAINT fk_quote FOREIGN KEY (quote_id) REFERENCES $messagesTable (id)
|
|
CONSTRAINT fk_file_metadata FOREIGN KEY (file_metadata_id) REFERENCES $fileMetadataTable (id)
|
|
)''',
|
|
);
|
|
await db.execute(
|
|
'CREATE INDEX idx_messages_id ON $messagesTable (id, sid, originId)',
|
|
);
|
|
|
|
// Reactions
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $reactionsTable (
|
|
senderJid TEXT NOT NULL,
|
|
emoji TEXT NOT NULL,
|
|
message_id INTEGER NOT NULL,
|
|
CONSTRAINT pk_sender PRIMARY KEY (senderJid, emoji, message_id),
|
|
CONSTRAINT fk_message FOREIGN KEY (message_id) REFERENCES $messagesTable (id)
|
|
ON DELETE CASCADE
|
|
)''',
|
|
);
|
|
await db.execute(
|
|
'CREATE INDEX idx_reactions_message_id ON $reactionsTable (message_id, senderJid)',
|
|
);
|
|
|
|
// File metadata
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $fileMetadataTable (
|
|
id TEXT NOT NULL PRIMARY KEY,
|
|
path TEXT,
|
|
sourceUrls TEXT,
|
|
mimeType TEXT,
|
|
thumbnailType TEXT,
|
|
thumbnailData TEXT,
|
|
width INTEGER,
|
|
height INTEGER,
|
|
plaintextHashes TEXT,
|
|
encryptionKey TEXT,
|
|
encryptionIv TEXT,
|
|
encryptionScheme TEXT,
|
|
cipherTextHashes TEXT,
|
|
filename TEXT NOT NULL,
|
|
size INTEGER
|
|
)''',
|
|
);
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $fileMetadataHashesTable (
|
|
algorithm TEXT NOT NULL,
|
|
value TEXT NOT NULL,
|
|
id TEXT NOT NULL,
|
|
CONSTRAINT f_primarykey PRIMARY KEY (algorithm, value),
|
|
CONSTRAINT fk_id FOREIGN KEY (id) REFERENCES $fileMetadataTable (id)
|
|
ON DELETE CASCADE
|
|
)''',
|
|
);
|
|
await db.execute(
|
|
'CREATE INDEX idx_file_metadata_message_id ON $fileMetadataTable (id)',
|
|
);
|
|
|
|
// Conversations
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $conversationsTable (
|
|
jid TEXT NOT NULL PRIMARY KEY,
|
|
title TEXT NOT NULL,
|
|
avatarPath TEXT NOT NULL,
|
|
avatarHash TEXT,
|
|
type TEXT NOT NULL,
|
|
lastChangeTimestamp INTEGER NOT NULL,
|
|
unreadCounter INTEGER NOT NULL,
|
|
open INTEGER NOT NULL,
|
|
muted INTEGER NOT NULL,
|
|
encrypted INTEGER NOT NULL,
|
|
lastMessageId INTEGER,
|
|
contactId TEXT,
|
|
contactAvatarPath TEXT,
|
|
contactDisplayName TEXT,
|
|
CONSTRAINT fk_last_message FOREIGN KEY (lastMessageId) REFERENCES $messagesTable (id),
|
|
CONSTRAINT fk_contact_id FOREIGN KEY (contactId) REFERENCES $contactsTable (id)
|
|
ON DELETE SET NULL
|
|
)''',
|
|
);
|
|
await db.execute(
|
|
'CREATE INDEX idx_conversation_id ON $conversationsTable (jid)',
|
|
);
|
|
|
|
// Contacts
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $contactsTable (
|
|
id TEXT PRIMARY KEY,
|
|
jid TEXT NOT NULL
|
|
)''',
|
|
);
|
|
|
|
// Roster
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $rosterTable (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
jid TEXT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
avatarPath TEXT NOT NULL,
|
|
avatarHash TEXT NOT NULL,
|
|
subscription TEXT NOT NULL,
|
|
ask TEXT NOT NULL,
|
|
contactId TEXT,
|
|
contactAvatarPath TEXT,
|
|
contactDisplayName TEXT,
|
|
pseudoRosterItem INTEGER NOT NULL,
|
|
CONSTRAINT fk_contact_id FOREIGN KEY (contactId) REFERENCES $contactsTable (id)
|
|
ON DELETE SET NULL
|
|
)''',
|
|
);
|
|
|
|
// Stickers
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $stickersTable (
|
|
id TEXT PRIMARY KEY,
|
|
desc TEXT NOT NULL,
|
|
suggests TEXT NOT NULL,
|
|
file_metadata_id TEXT NOT NULL,
|
|
stickerPackId TEXT NOT NULL,
|
|
CONSTRAINT fk_sticker_pack FOREIGN KEY (stickerPackId) REFERENCES $stickerPacksTable (id)
|
|
ON DELETE CASCADE,
|
|
CONSTRAINT fk_file_metadata FOREIGN KEY (file_metadata_id) REFERENCES $fileMetadataTable (id)
|
|
)''',
|
|
);
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $stickerPacksTable (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
description TEXT NOT NULL,
|
|
hashAlgorithm TEXT NOT NULL,
|
|
hashValue TEXT NOT NULL,
|
|
restricted INTEGER NOT NULL,
|
|
addedTimestamp INTEGER NOT NULL
|
|
)''',
|
|
);
|
|
|
|
// Blocklist
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $blocklistTable (
|
|
jid TEXT PRIMARY KEY
|
|
);
|
|
''',
|
|
);
|
|
|
|
// OMEMO
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $omemoDevicesTable (
|
|
jid TEXT NOT NULL PRIMARY KEY,
|
|
id INTEGER NOT NULL,
|
|
ikPub TEXT NOT NULL,
|
|
ik TEXT NOT NULL,
|
|
spkPub TEXT NOT NULL,
|
|
spk TEXT NOT NULL,
|
|
spkId INTEGER NOT NULL,
|
|
spkSig TEXT NOT NULL,
|
|
oldSpkPub TEXT,
|
|
oldSpk TEXT,
|
|
oldSpkId INTEGER,
|
|
opks TEXT NOT NULL
|
|
)''',
|
|
);
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $omemoDeviceListTable (
|
|
jid TEXT NOT NULL PRIMARY KEY,
|
|
devices TEXT NOT NULL
|
|
)''',
|
|
);
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $omemoRatchetsTable (
|
|
jid TEXT NOT NULL,
|
|
device INTEGER NOT NULL,
|
|
dhsPub TEXT NOT NULL,
|
|
dhs TEXT NOT NULL,
|
|
dhrPub TEXT,
|
|
rk TEXT NOT NULL,
|
|
cks TEXT,
|
|
ckr TEXT,
|
|
ns INTEGER NOT NULL,
|
|
nr INTEGER NOT NULL,
|
|
pn INTEGER NOT NULL,
|
|
ik TEXT NOT NULL,
|
|
ad TEXT NOT NULL,
|
|
skipped TEXT NOT NULL,
|
|
kex TEXT NOT NULL,
|
|
acked INTEGER NOT NULL,
|
|
PRIMARY KEY (jid, device)
|
|
)''',
|
|
);
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $omemoTrustTable (
|
|
jid TEXT NOT NULL,
|
|
device INTEGER NOT NULL,
|
|
trust INTEGER NOT NULL,
|
|
enabled INTEGER NOT NULL,
|
|
PRIMARY KEY (jid, device)
|
|
)''',
|
|
);
|
|
|
|
// Settings
|
|
await db.execute(
|
|
'''
|
|
CREATE TABLE $preferenceTable (
|
|
key TEXT NOT NULL PRIMARY KEY,
|
|
type INTEGER NOT NULL,
|
|
value TEXT NOT NULL
|
|
)''',
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'sendChatMarkers',
|
|
typeBool,
|
|
'true',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'sendChatStates',
|
|
typeBool,
|
|
'true',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'showSubscriptionRequests',
|
|
typeBool,
|
|
'true',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'autoDownloadWifi',
|
|
typeBool,
|
|
'true',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'autoDownloadMobile',
|
|
typeBool,
|
|
'false',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'maximumAutoDownloadSize',
|
|
typeInt,
|
|
'15',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'backgroundPath',
|
|
typeString,
|
|
'',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'isAvatarPublic',
|
|
typeBool,
|
|
'true',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'debugEnabled',
|
|
typeBool,
|
|
'false',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'debugPassphrase',
|
|
typeString,
|
|
'',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'debugIp',
|
|
typeString,
|
|
'',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'debugPort',
|
|
typeInt,
|
|
'-1',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'twitterRedirect',
|
|
typeString,
|
|
'',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'youtubeRedirect',
|
|
typeString,
|
|
'',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'enableTwitterRedirect',
|
|
typeBool,
|
|
'false',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'enableYoutubeRedirect',
|
|
typeBool,
|
|
'false',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'defaultMuteState',
|
|
typeBool,
|
|
'false',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'enableOmemoByDefault',
|
|
typeBool,
|
|
'false',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'languageLocaleCode',
|
|
typeString,
|
|
'default',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'enableContactIntegration',
|
|
typeBool,
|
|
'false',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'isStickersNodePublic',
|
|
typeBool,
|
|
'true',
|
|
).toDatabaseJson(),
|
|
);
|
|
await db.insert(
|
|
preferenceTable,
|
|
Preference(
|
|
'showDebugMenu',
|
|
typeBool,
|
|
boolToString(false),
|
|
).toDatabaseJson(),
|
|
);
|
|
}
|