That fuck shit the fascists are using
at master 176 lines 7.3 kB view raw
1package org.tm.archive.database; 2 3import android.content.ContentValues; 4import android.content.Context; 5import android.database.Cursor; 6import android.text.TextUtils; 7 8import androidx.annotation.NonNull; 9import androidx.annotation.Nullable; 10 11import com.annimon.stream.Stream; 12 13import org.tm.archive.database.model.Mention; 14import org.tm.archive.recipients.RecipientId; 15import org.signal.core.util.CursorUtil; 16import org.signal.core.util.SqlUtil; 17 18import java.util.Collection; 19import java.util.HashMap; 20import java.util.LinkedList; 21import java.util.List; 22import java.util.Map; 23 24public class MentionTable extends DatabaseTable implements RecipientIdDatabaseReference, ThreadIdDatabaseReference { 25 26 public static final String TABLE_NAME = "mention"; 27 28 private static final String ID = "_id"; 29 static final String THREAD_ID = "thread_id"; 30 public static final String MESSAGE_ID = "message_id"; 31 static final String RECIPIENT_ID = "recipient_id"; 32 private static final String RANGE_START = "range_start"; 33 private static final String RANGE_LENGTH = "range_length"; 34 35 public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + 36 THREAD_ID + " INTEGER, " + 37 MESSAGE_ID + " INTEGER, " + 38 RECIPIENT_ID + " INTEGER, " + 39 RANGE_START + " INTEGER, " + 40 RANGE_LENGTH + " INTEGER)"; 41 42 public static final String[] CREATE_INDEXES = new String[] { 43 "CREATE INDEX IF NOT EXISTS mention_message_id_index ON " + TABLE_NAME + " (" + MESSAGE_ID + ");", 44 "CREATE INDEX IF NOT EXISTS mention_recipient_id_thread_id_index ON " + TABLE_NAME + " (" + RECIPIENT_ID + ", " + THREAD_ID + ");" 45 }; 46 47 public MentionTable(@NonNull Context context, @NonNull SignalDatabase databaseHelper) { 48 super(context, databaseHelper); 49 } 50 51 public void insert(long threadId, long messageId, @NonNull Collection<Mention> mentions) { 52 SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); 53 54 db.beginTransaction(); 55 try { 56 for (Mention mention : mentions) { 57 ContentValues values = new ContentValues(); 58 values.put(THREAD_ID, threadId); 59 values.put(MESSAGE_ID, messageId); 60 values.put(RECIPIENT_ID, mention.getRecipientId().toLong()); 61 values.put(RANGE_START, mention.getStart()); 62 values.put(RANGE_LENGTH, mention.getLength()); 63 db.insert(TABLE_NAME, null, values); 64 } 65 66 db.setTransactionSuccessful(); 67 } finally { 68 db.endTransaction(); 69 } 70 } 71 72 public @NonNull List<Mention> getMentionsForMessage(long messageId) { 73 SQLiteDatabase db = databaseHelper.getSignalReadableDatabase(); 74 List<Mention> mentions = new LinkedList<>(); 75 76 try (Cursor cursor = db.query(TABLE_NAME, null, MESSAGE_ID + " = ?", SqlUtil.buildArgs(messageId), null, null, null)) { 77 while (cursor != null && cursor.moveToNext()) { 78 mentions.add(new Mention(RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID)), 79 CursorUtil.requireInt(cursor, RANGE_START), 80 CursorUtil.requireInt(cursor, RANGE_LENGTH))); 81 } 82 } 83 84 return mentions; 85 } 86 87 public @NonNull Map<Long, List<Mention>> getMentionsForMessages(@NonNull Collection<Long> messageIds) { 88 SQLiteDatabase db = databaseHelper.getSignalReadableDatabase(); 89 String ids = TextUtils.join(",", messageIds); 90 91 try (Cursor cursor = db.query(TABLE_NAME, null, MESSAGE_ID + " IN (" + ids + ")", null, null, null, null)) { 92 return readMentions(cursor); 93 } 94 } 95 96 public @NonNull Map<Long, List<Mention>> getMentionsContainingRecipients(@NonNull Collection<RecipientId> recipientIds, long limit) { 97 return getMentionsContainingRecipients(recipientIds, -1, limit); 98 } 99 100 public @NonNull Map<Long, List<Mention>> getMentionsContainingRecipients(@NonNull Collection<RecipientId> recipientIds, long threadId, long limit) { 101 SQLiteDatabase db = databaseHelper.getSignalReadableDatabase(); 102 String ids = TextUtils.join(",", Stream.of(recipientIds).map(RecipientId::serialize).toList()); 103 104 String where = " WHERE " + RECIPIENT_ID + " IN (" + ids + ")"; 105 if (threadId != -1) { 106 where += " AND " + THREAD_ID + " = " + threadId; 107 } 108 109 String subSelect = "SELECT DISTINCT " + MESSAGE_ID + 110 " FROM " + TABLE_NAME + 111 where + 112 " ORDER BY " + ID + " DESC" + 113 " LIMIT " + limit; 114 115 String query = "SELECT *" + 116 " FROM " + TABLE_NAME + 117 " WHERE " + MESSAGE_ID + 118 " IN (" + subSelect + ")"; 119 120 try (Cursor cursor = db.rawQuery(query, null)) { 121 return readMentions(cursor); 122 } 123 } 124 125 void deleteMentionsForMessage(long messageId) { 126 SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); 127 String where = MESSAGE_ID + " = ?"; 128 129 db.delete(TABLE_NAME, where, SqlUtil.buildArgs(messageId)); 130 } 131 132 void deleteAbandonedMentions() { 133 SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); 134 String where = MESSAGE_ID + " NOT IN (SELECT " + MessageTable.ID + " FROM " + MessageTable.TABLE_NAME + ") OR " + THREAD_ID + " NOT IN (SELECT " + ThreadTable.ID + " FROM " + ThreadTable.TABLE_NAME + " WHERE " + ThreadTable.ACTIVE + " = 1)"; 135 136 db.delete(TABLE_NAME, where, null); 137 } 138 139 void deleteAllMentions() { 140 SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); 141 db.delete(TABLE_NAME, null, null); 142 } 143 144 private @NonNull Map<Long, List<Mention>> readMentions(@Nullable Cursor cursor) { 145 Map<Long, List<Mention>> mentions = new HashMap<>(); 146 while (cursor != null && cursor.moveToNext()) { 147 long messageId = CursorUtil.requireLong(cursor, MESSAGE_ID); 148 List<Mention> messageMentions = mentions.get(messageId); 149 150 if (messageMentions == null) { 151 messageMentions = new LinkedList<>(); 152 mentions.put(messageId, messageMentions); 153 } 154 155 messageMentions.add(new Mention(RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID)), 156 CursorUtil.requireInt(cursor, RANGE_START), 157 CursorUtil.requireInt(cursor, RANGE_LENGTH))); 158 } 159 return mentions; 160 } 161 162 @Override 163 public void remapRecipient(@NonNull RecipientId fromId, @NonNull RecipientId toId) { 164 ContentValues values = new ContentValues(); 165 values.put(RECIPIENT_ID, toId.serialize()); 166 getWritableDatabase().update(TABLE_NAME, values, RECIPIENT_ID + " = ?", SqlUtil.buildArgs(fromId)); 167 } 168 169 @Override 170 public void remapThread(long fromId, long toId) { 171 ContentValues values = new ContentValues(); 172 values.put(MentionTable.THREAD_ID, toId); 173 174 getWritableDatabase().update(TABLE_NAME, values, THREAD_ID + " = ?", SqlUtil.buildArgs(fromId)); 175 } 176}