@@ -12,11 +12,9 @@ use crate::config::Config;
12
12
use crate :: constants:: { Chattype , DC_CHAT_ID_TRASH } ;
13
13
use crate :: contact:: { ContactId , Origin , import_vcard, mark_contact_id_as_verified} ;
14
14
use crate :: context:: { Context , get_version_str} ;
15
- use crate :: download:: DownloadState ;
16
15
use crate :: key:: load_self_public_key;
17
16
use crate :: log:: LogExt ;
18
17
use crate :: message:: { Message , Viewtype } ;
19
- use crate :: param:: { Param , Params } ;
20
18
use crate :: tools:: { create_id, time} ;
21
19
22
20
pub ( crate ) const SELF_REPORTING_BOT_EMAIL : & str = "self_reporting@testrun.org" ;
@@ -105,8 +103,6 @@ pub async fn maybe_send_self_report(context: &Context) -> Result<Option<ChatId>>
105
103
async fn send_self_report ( context : & Context ) -> Result < ChatId > {
106
104
info ! ( context, "Sending self report." ) ;
107
105
108
- let last_selfreport_time = context. get_config_i64 ( Config :: LastSelfReportSent ) . await ?;
109
-
110
106
// Setting this config at the beginning avoids endless loops when things do not
111
107
// work out for whatever reason.
112
108
context
@@ -126,7 +122,7 @@ See TODO[blog post] for more information."
126
122
. to_string ( ) ,
127
123
) ;
128
124
129
- let self_report = get_self_report ( context, last_selfreport_time ) . await ?;
125
+ let self_report = get_self_report ( context) . await ?;
130
126
131
127
msg. set_file_from_bytes (
132
128
context,
@@ -141,10 +137,34 @@ See TODO[blog post] for more information."
141
137
. log_err ( context)
142
138
. ok ( ) ;
143
139
140
+ set_last_msgid ( context) . await ?;
141
+
144
142
Ok ( chat_id)
145
143
}
146
144
147
- async fn get_self_report ( context : & Context , last_selfreport_time : i64 ) -> Result < String > {
145
+ pub ( crate ) async fn set_last_msgid ( context : & Context ) -> Result < ( ) > {
146
+ let last_msgid: u64 = context
147
+ . sql
148
+ . query_get_value ( "SELECT MAX(id) FROM msgs" , ( ) )
149
+ . await ?
150
+ . context ( "All messages are gone" ) ?;
151
+
152
+ context
153
+ . sql
154
+ . set_raw_config (
155
+ Config :: SelfReportingLastMsgId . as_ref ( ) ,
156
+ Some ( & last_msgid. to_string ( ) ) ,
157
+ )
158
+ . await ?;
159
+
160
+ Ok ( ( ) )
161
+ }
162
+
163
+ async fn get_self_report ( context : & Context ) -> Result < String > {
164
+ let last_msgid = context
165
+ . get_config_u64 ( Config :: SelfReportingLastMsgId )
166
+ . await ?;
167
+
148
168
let key_created = load_self_public_key ( context)
149
169
. await ?
150
170
. primary_key
@@ -161,12 +181,13 @@ async fn get_self_report(context: &Context, last_selfreport_time: i64) -> Result
161
181
id
162
182
}
163
183
} ;
184
+
164
185
let statistics = Statistics {
165
186
core_version : get_version_str ( ) . to_string ( ) ,
166
187
key_created,
167
188
self_reporting_id,
168
189
contact_stats : get_contact_stats ( context) . await ?,
169
- message_stats : get_message_stats ( context, last_selfreport_time ) . await ?,
190
+ message_stats : get_message_stats ( context, last_msgid ) . await ?, // TODO
170
191
securejoin_source_stats : get_securejoin_source_stats ( context) . await ?,
171
192
} ;
172
193
@@ -303,66 +324,89 @@ async fn get_contact_stats(context: &Context) -> Result<Vec<ContactStat>> {
303
324
Ok ( contacts)
304
325
}
305
326
306
- async fn get_message_stats (
307
- context : & Context ,
308
- mut last_selfreport_time : i64 ,
309
- ) -> Result < MessageStats > {
310
- let enabled_ts: i64 = context
311
- . get_config_i64 ( Config :: SelfReportingEnabledTimestamp )
312
- . await ?;
313
- if last_selfreport_time == 0 {
314
- last_selfreport_time = enabled_ts;
315
- }
316
- ensure ! ( last_selfreport_time > 0 , "Enabled Timestamp missing" ) ;
327
+ async fn get_message_stats ( context : & Context , last_msgid : u64 ) -> Result < MessageStats > {
328
+ ensure ! (
329
+ last_msgid >= 9 ,
330
+ "Last_msgid < 9 would mean including 'special' messages in the report"
331
+ ) ;
317
332
318
333
let selfreporting_bot_chat_id = get_selfreporting_bot ( context) . await ?;
319
334
320
335
let trans_fn = |t : & mut rusqlite:: Transaction | {
321
336
t. pragma_update ( None , "query_only" , "0" ) ?;
337
+
338
+ // This table will hold all 'protected' chats.
339
+ // Protected chats guarantee that all messages in the chat
340
+ // are sent with verified encryption
341
+ // are marked with a green checkmark in the UI.
322
342
t. execute (
323
- "CREATE TEMP TABLE temp.verified_chats (
343
+ "CREATE TEMP TABLE temp.protected_chats (
324
344
id INTEGER PRIMARY KEY
325
345
) STRICT" ,
326
346
( ) ,
327
347
) ?;
328
348
349
+ // id>9 because chat ids 0..9 are "special" chats like the trash chat.
329
350
t. execute (
330
- "INSERT INTO temp.verified_chats
351
+ "INSERT INTO temp.protected_chats
331
352
SELECT id FROM chats
332
353
WHERE protected=1 AND id>9" ,
333
354
( ) ,
334
355
) ?;
335
356
357
+ // In the following SQL statements,
358
+ // - we always have the line
359
+ // `AND from_id=? AND chat_id<>? AND id>? AND hidden=0 AND chat_id<>?`.
360
+ // `from_id=?` is to count only outgoing messages.
361
+ // The rest excludes:
362
+ // - the chat with the self-reporting bot itself,
363
+ // - messages sent with the last report, or before the config was enabled
364
+ // - hidden system messages, which are not actually shown to the user
365
+ // - messages in the 'Trash' chat, which is an internal chat assigned to messages that are not shown to the user
366
+ // - `(param GLOB '*\nc=1*' OR param GLOB 'c=1*')`
367
+ // matches all messages that are end-to-end encrypted
336
368
let to_verified = t. query_row (
337
369
"SELECT COUNT(*) FROM msgs
338
- WHERE chat_id IN temp.verified_chats
339
- AND chat_id<>? AND id>9 AND timestamp>=? AND hidden=0
340
- AND NOT (param GLOB '*\n S=*' OR param GLOB 'S=*')" ,
341
- ( selfreporting_bot_chat_id, last_selfreport_time) ,
370
+ WHERE chat_id IN temp.protected_chats
371
+ AND from_id=? AND chat_id<>? AND id>? AND hidden=0 AND chat_id<>?" ,
372
+ (
373
+ ContactId :: SELF ,
374
+ selfreporting_bot_chat_id,
375
+ last_msgid,
376
+ DC_CHAT_ID_TRASH ,
377
+ ) ,
342
378
|row| row. get ( 0 ) ,
343
379
) ?;
344
380
345
381
let unverified_encrypted = t. query_row (
346
382
"SELECT COUNT(*) FROM msgs
347
- WHERE chat_id not IN temp.verified_chats
383
+ WHERE chat_id not IN temp.protected_chats
348
384
AND (param GLOB '*\n c=1*' OR param GLOB 'c=1*')
349
- AND chat_id<>? AND id>9 AND timestamp>=? AND hidden=0
350
- AND NOT (param GLOB '*\n S=*' OR param GLOB 'S=*')" ,
351
- ( selfreporting_bot_chat_id, last_selfreport_time) ,
385
+ AND from_id=? AND chat_id<>? AND id>? AND hidden=0 AND chat_id<>?" ,
386
+ (
387
+ ContactId :: SELF ,
388
+ selfreporting_bot_chat_id,
389
+ last_msgid,
390
+ DC_CHAT_ID_TRASH ,
391
+ ) ,
352
392
|row| row. get ( 0 ) ,
353
393
) ?;
354
394
355
395
let unencrypted = t. query_row (
356
396
"SELECT COUNT(*) FROM msgs
357
- WHERE chat_id not IN temp.verified_chats
397
+ WHERE chat_id not IN temp.protected_chats
358
398
AND NOT (param GLOB '*\n c=1*' OR param GLOB 'c=1*')
359
- AND chat_id<>? AND id>9 AND timestamp>=? AND hidden=0
360
- AND NOT (param GLOB '*\n S=*' OR param GLOB 'S=*')" ,
361
- ( selfreporting_bot_chat_id, last_selfreport_time) ,
399
+ AND from_id=? AND chat_id<>? AND id>? AND hidden=0 AND chat_id<>?" ,
400
+ (
401
+ ContactId :: SELF ,
402
+ selfreporting_bot_chat_id,
403
+ last_msgid,
404
+ DC_CHAT_ID_TRASH ,
405
+ ) ,
362
406
|row| row. get ( 0 ) ,
363
407
) ?;
364
408
365
- t. execute ( "DROP TABLE temp.verified_chats " , ( ) ) ?;
409
+ t. execute ( "DROP TABLE temp.protected_chats " , ( ) ) ?;
366
410
367
411
Ok ( MessageStats {
368
412
to_verified,
0 commit comments