Coverage for src/tests/test_conversations.py: 100%

1041 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-12-20 11:53 +0000

1from datetime import timedelta 

2 

3import grpc 

4import pytest 

5from google.protobuf import wrappers_pb2 

6 

7from couchers.db import session_scope 

8from couchers.jobs.worker import process_job 

9from couchers.models import ( 

10 GroupChatRole, 

11 GroupChatSubscription, 

12 Notification, 

13 NotificationDelivery, 

14 NotificationDeliveryType, 

15 NotificationTopicAction, 

16 RateLimitAction, 

17) 

18from couchers.proto import api_pb2, conversations_pb2, notification_data_pb2, notifications_pb2 

19from couchers.rate_limits.definitions import RATE_LIMIT_DEFINITIONS, RATE_LIMIT_HOURS 

20from couchers.sql import couchers_select as select 

21from couchers.utils import Duration_from_timedelta, now, to_aware_datetime 

22from tests.test_fixtures import ( # noqa 

23 api_session, 

24 conversations_session, 

25 db, 

26 generate_user, 

27 make_friends, 

28 make_user_block, 

29 make_user_invisible, 

30 mock_notification_email, 

31 moderator, 

32 notifications_session, 

33 testconfig, 

34) 

35 

36 

37@pytest.fixture(autouse=True) 

38def _(testconfig): 

39 pass 

40 

41 

42def test_list_group_chats(db, moderator): 

43 user1, token1 = generate_user() 

44 user2, token2 = generate_user() 

45 user3, token3 = generate_user() 

46 

47 make_friends(user2, user1) 

48 make_friends(user1, user3) 

49 

50 with conversations_session(token1) as c: 

51 # no threads initially 

52 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

53 assert len(res.group_chats) == 0 

54 

55 # create some group chats with messages 

56 res = c.CreateGroupChat( 

57 conversations_pb2.CreateGroupChatReq( 

58 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title") 

59 ) 

60 ) 

61 group_chat1_id = res.group_chat_id 

62 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1")) 

63 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 2")) 

64 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])) 

65 group_chat2_id = res.group_chat_id 

66 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 1")) 

67 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 2")) 

68 

69 moderator.approve_group_chat(group_chat1_id) 

70 moderator.approve_group_chat(group_chat2_id) 

71 

72 with conversations_session(token1) as c: 

73 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

74 assert len(res.group_chats) == 2 

75 assert res.no_more 

76 

77 with conversations_session(token2) as c: 

78 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

79 assert len(res.group_chats) == 2 

80 assert res.no_more 

81 

82 with conversations_session(token3) as c: 

83 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

84 assert len(res.group_chats) == 1 

85 assert res.no_more 

86 

87 

88def test_list_empty_group_chats(db, moderator): 

89 user1, token1 = generate_user() 

90 user2, token2 = generate_user() 

91 user3, token3 = generate_user() 

92 

93 make_friends(user1, user3) 

94 make_friends(user2, user1) 

95 make_friends(user2, user3) 

96 

97 with conversations_session(token1) as c: 

98 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

99 assert len(res.group_chats) == 0 

100 

101 res1 = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

102 res2 = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])) 

103 

104 moderator.approve_group_chat(res1.group_chat_id) 

105 moderator.approve_group_chat(res2.group_chat_id) 

106 

107 with conversations_session(token1) as c: 

108 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

109 assert len(res.group_chats) == 2 

110 assert res.no_more 

111 

112 with conversations_session(token2) as c: 

113 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

114 assert len(res.group_chats) == 2 

115 assert res.no_more 

116 

117 res3 = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])) 

118 moderator.approve_group_chat(res3.group_chat_id) 

119 

120 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

121 assert len(res.group_chats) == 3 

122 assert res.no_more 

123 

124 with conversations_session(token3) as c: 

125 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

126 assert len(res.group_chats) == 2 

127 assert res.no_more 

128 

129 

130def test_list_group_chats_ordering(db, moderator): 

131 # user is member of 5 group chats, order them correctly 

132 user, token = generate_user() 

133 user2, token2 = generate_user() 

134 user3, token3 = generate_user() 

135 user4, token4 = generate_user() 

136 

137 make_friends(user2, user) 

138 make_friends(user2, user3) 

139 make_friends(user2, user4) 

140 make_friends(user3, user) 

141 make_friends(user3, user4) 

142 make_friends(user, user4) 

143 

144 chat_ids = [] 

145 

146 with conversations_session(token2) as c: 

147 res = c.CreateGroupChat( 

148 conversations_pb2.CreateGroupChatReq( 

149 recipient_user_ids=[user.id], title=wrappers_pb2.StringValue(value="Chat 0") 

150 ) 

151 ) 

152 chat_ids.append(res.group_chat_id) 

153 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

154 res = c.CreateGroupChat( 

155 conversations_pb2.CreateGroupChatReq( 

156 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 1") 

157 ) 

158 ) 

159 chat_ids.append(res.group_chat_id) 

160 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

161 res = c.CreateGroupChat( 

162 conversations_pb2.CreateGroupChatReq( 

163 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 2") 

164 ) 

165 ) 

166 chat_ids.append(res.group_chat_id) 

167 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

168 

169 with conversations_session(token3) as c: 

170 res = c.CreateGroupChat( 

171 conversations_pb2.CreateGroupChatReq( 

172 recipient_user_ids=[user.id, user2.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 3") 

173 ) 

174 ) 

175 chat_ids.append(res.group_chat_id) 

176 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

177 

178 for chat_id in chat_ids: 

179 moderator.approve_group_chat(chat_id) 

180 

181 with conversations_session(token) as c: 

182 res = c.CreateGroupChat( 

183 conversations_pb2.CreateGroupChatReq( 

184 recipient_user_ids=[user2.id, user3.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 4") 

185 ) 

186 ) 

187 moderator.approve_group_chat(res.group_chat_id) 

188 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

189 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

190 assert len(res.group_chats) == 5 

191 assert res.group_chats[0].title == "Chat 4" 

192 assert res.group_chats[1].title == "Chat 3" 

193 assert res.group_chats[2].title == "Chat 2" 

194 assert res.group_chats[3].title == "Chat 1" 

195 assert res.group_chats[4].title == "Chat 0" 

196 

197 c.SendMessage( 

198 conversations_pb2.SendMessageReq(group_chat_id=res.group_chats[3].group_chat_id, text="Test message 2a") 

199 ) 

200 c.SendMessage( 

201 conversations_pb2.SendMessageReq(group_chat_id=res.group_chats[2].group_chat_id, text="Test message 2b") 

202 ) 

203 

204 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

205 assert len(res.group_chats) == 5 

206 assert res.group_chats[0].title == "Chat 2" 

207 assert res.group_chats[0].latest_message.text.text == "Test message 2b" 

208 assert res.group_chats[1].title == "Chat 1" 

209 assert res.group_chats[1].latest_message.text.text == "Test message 2a" 

210 assert res.group_chats[2].title == "Chat 4" 

211 assert res.group_chats[3].title == "Chat 3" 

212 assert res.group_chats[4].title == "Chat 0" 

213 

214 

215def test_list_group_chats_ordering_after_left(db, moderator): 

216 # user is member to 4 group chats, and has left one. 

217 # The one user left has the most recent message, but user left before then, 

218 # this should display as e.g. 3rd most recent depending on last message when they were in the chat 

219 user, token = generate_user() 

220 user2, token2 = generate_user() 

221 user3, token3 = generate_user() 

222 user4, token4 = generate_user() 

223 

224 make_friends(user2, user) 

225 make_friends(user2, user3) 

226 make_friends(user2, user4) 

227 make_friends(user3, user) 

228 make_friends(user3, user4) 

229 make_friends(user, user4) 

230 

231 chat_ids = [] 

232 

233 with conversations_session(token2) as c: 

234 res = c.CreateGroupChat( 

235 conversations_pb2.CreateGroupChatReq( 

236 recipient_user_ids=[user.id], title=wrappers_pb2.StringValue(value="Chat 0") 

237 ) 

238 ) 

239 chat_ids.append(res.group_chat_id) 

240 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

241 res = c.CreateGroupChat( 

242 conversations_pb2.CreateGroupChatReq( 

243 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Left Chat 1") 

244 ) 

245 ) 

246 left_chat_id = res.group_chat_id 

247 chat_ids.append(left_chat_id) 

248 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Test message")) 

249 res = c.CreateGroupChat( 

250 conversations_pb2.CreateGroupChatReq( 

251 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 2") 

252 ) 

253 ) 

254 chat2_id = res.group_chat_id 

255 chat_ids.append(chat2_id) 

256 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=chat2_id, text="Test message")) 

257 

258 with conversations_session(token3) as c: 

259 res = c.CreateGroupChat( 

260 conversations_pb2.CreateGroupChatReq( 

261 recipient_user_ids=[user.id, user2.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 3") 

262 ) 

263 ) 

264 chat_ids.append(res.group_chat_id) 

265 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

266 

267 for chat_id in chat_ids: 

268 moderator.approve_group_chat(chat_id) 

269 

270 with conversations_session(token) as c: 

271 res = c.CreateGroupChat( 

272 conversations_pb2.CreateGroupChatReq( 

273 recipient_user_ids=[user2.id, user3.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 4") 

274 ) 

275 ) 

276 moderator.approve_group_chat(res.group_chat_id) 

277 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

278 

279 # leave chat 

280 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=left_chat_id)) 

281 

282 with conversations_session(token3) as c: 

283 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=chat2_id, text="Test message")) 

284 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Test message")) 

285 

286 with conversations_session(token2) as c: 

287 # other user sends a message to that chat 

288 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Another test message")) 

289 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

290 assert len(res.group_chats) == 5 

291 assert res.group_chats[0].title == "Left Chat 1" 

292 assert res.group_chats[1].title == "Chat 2" 

293 assert res.group_chats[2].title == "Chat 4" 

294 assert res.group_chats[3].title == "Chat 3" 

295 assert res.group_chats[4].title == "Chat 0" 

296 

297 with conversations_session(token) as c: 

298 # we can't see the new message since we left before it was sent 

299 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

300 assert len(res.group_chats) == 5 

301 assert res.group_chats[0].title == "Chat 2" 

302 assert res.group_chats[1].title == "Left Chat 1" 

303 assert res.group_chats[2].title == "Chat 4" 

304 assert res.group_chats[3].title == "Chat 3" 

305 assert res.group_chats[4].title == "Chat 0" 

306 

307 

308def test_get_group_chat_messages(db): 

309 user1, token1 = generate_user() 

310 user2, token2 = generate_user() 

311 user3, token3 = generate_user() 

312 

313 make_friends(user1, user2) 

314 

315 with conversations_session(token1) as c: 

316 # create some threads with messages 

317 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

318 group_chat_id = res.group_chat_id 

319 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1")) 

320 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 2")) 

321 

322 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)) 

323 # created + 2 normal 

324 assert len(res.messages) == 3 

325 assert res.no_more 

326 

327 assert res.messages[0].text.text == "Test message 2" 

328 assert res.messages[1].text.text == "Test message 1" 

329 assert res.messages[2].WhichOneof("content") == "chat_created" 

330 

331 # test that another user can't access the thread 

332 with conversations_session(token3) as c: 

333 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)) 

334 assert len(res.messages) == 0 

335 

336 

337def test_get_group_chat_messages_pagination(db, moderator): 

338 user1, token1 = generate_user() 

339 user2, token2 = generate_user() 

340 make_friends(user1, user2) 

341 

342 with conversations_session(token1) as c: 

343 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

344 group_chat_id = res.group_chat_id 

345 for i in range(30): 

346 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=str(i))) 

347 

348 moderator.approve_group_chat(group_chat_id) 

349 

350 with conversations_session(token2) as c: 

351 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)) 

352 # pagination 

353 assert len(res.messages) == 20 

354 assert res.messages[0].text.text == "29" 

355 assert res.messages[19].text.text == "10" 

356 assert not res.no_more 

357 res = c.GetGroupChatMessages( 

358 conversations_pb2.GetGroupChatMessagesReq( 

359 group_chat_id=group_chat_id, last_message_id=res.messages[19].message_id 

360 ) 

361 ) 

362 assert len(res.messages) == 11 

363 assert res.messages[0].text.text == "9" 

364 assert res.messages[9].text.text == "0" 

365 assert res.no_more 

366 

367 

368def test_get_group_chat_messages_joined_left(db, moderator): 

369 user1, token1 = generate_user() 

370 user2, token2 = generate_user() 

371 user3, token3 = generate_user() 

372 user4, token4 = generate_user() 

373 make_friends(user1, user2) 

374 make_friends(user1, user3) 

375 make_friends(user1, user4) 

376 

377 with conversations_session(token1) as c: 

378 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id])) 

379 group_chat_id = res.group_chat_id 

380 moderator.approve_group_chat(group_chat_id) 

381 

382 for i in range(10): 

383 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=str(i))) 

384 

385 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)) 

386 

387 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="10")) 

388 

389 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)) 

390 

391 # created + 10 normal + invited + normal 

392 assert len(res.messages) == 13 

393 

394 with conversations_session(token3) as c: 

395 # can only see last message after invited 

396 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)) 

397 # joined + normal 

398 assert len(res.messages) == 2 

399 assert res.messages[0].text.text == "10" 

400 

401 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

402 

403 with conversations_session(token1) as c: 

404 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="11")) 

405 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="12")) 

406 

407 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)) 

408 

409 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="13")) 

410 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="14")) 

411 

412 with conversations_session(token3) as c: 

413 # can only see last message after invited 

414 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)) 

415 # joined + normal + left + invite + 2 normal 

416 assert len(res.messages) == 6 

417 assert res.messages[0].text.text == "14" 

418 assert res.messages[1].text.text == "13" 

419 assert res.messages[2].WhichOneof("content") == "user_invited" 

420 assert res.messages[3].WhichOneof("content") == "user_left" 

421 assert res.messages[4].text.text == "10" 

422 assert res.messages[5].WhichOneof("content") == "user_invited" 

423 

424 

425def test_get_group_chat_info(db): 

426 user1, token1 = generate_user() 

427 user2, token2 = generate_user() 

428 user3, token3 = generate_user() 

429 

430 make_friends(user1, user2) 

431 make_friends(user3, user1) 

432 

433 with conversations_session(token1) as c: 

434 # create some threads with messages 

435 res = c.CreateGroupChat( 

436 conversations_pb2.CreateGroupChatReq( 

437 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title") 

438 ) 

439 ) 

440 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1")) 

441 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 2")) 

442 group_chat1_id = res.group_chat_id 

443 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])) 

444 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 1")) 

445 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 2")) 

446 group_chat2_id = res.group_chat_id 

447 

448 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat1_id)) 

449 assert res.title == "Test title" 

450 assert user2.id in res.member_user_ids 

451 assert user1.id in res.admin_user_ids 

452 assert to_aware_datetime(res.created) <= now() 

453 assert res.only_admins_invite 

454 assert res.is_dm 

455 

456 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat2_id)) 

457 assert not res.title 

458 assert user2.id in res.member_user_ids 

459 assert user3.id in res.member_user_ids 

460 assert user1.id in res.admin_user_ids 

461 assert to_aware_datetime(res.created) <= now() 

462 assert res.only_admins_invite 

463 assert not res.is_dm 

464 

465 

466def test_get_group_chat_info_denied(db): 

467 user1, token1 = generate_user() 

468 user2, token2 = generate_user() 

469 user3, token3 = generate_user() 

470 user4, token4 = generate_user() 

471 

472 make_friends(user1, user2) 

473 make_friends(user3, user1) 

474 

475 with conversations_session(token1) as c: 

476 # create a group chat with messages 

477 res = c.CreateGroupChat( 

478 conversations_pb2.CreateGroupChatReq( 

479 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title") 

480 ) 

481 ) 

482 group_chat_id = res.group_chat_id 

483 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

484 

485 with conversations_session(token4) as c: 

486 with pytest.raises(grpc.RpcError) as e: 

487 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

488 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

489 

490 

491def test_get_group_chat_info_left(db, moderator): 

492 user1, token1 = generate_user() 

493 user2, token2 = generate_user() 

494 user3, token3 = generate_user() 

495 user4, token4 = generate_user() 

496 

497 make_friends(user1, user2) 

498 make_friends(user3, user1) 

499 make_friends(user1, user4) 

500 

501 with conversations_session(token1) as c: 

502 # create a group chat with messages 

503 res = c.CreateGroupChat( 

504 conversations_pb2.CreateGroupChatReq( 

505 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title") 

506 ) 

507 ) 

508 group_chat_id = res.group_chat_id 

509 moderator.approve_group_chat(group_chat_id) 

510 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

511 

512 with conversations_session(token3) as c: 

513 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

514 

515 with conversations_session(token1) as c: 

516 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user4.id)) 

517 

518 with conversations_session(token3) as c: 

519 # this user left when user4 wasn't a member, 

520 # so the returned members should be user1, user2, and user3 only 

521 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

522 assert len(res.member_user_ids) == 3 

523 assert user1.id in res.member_user_ids 

524 assert user2.id in res.member_user_ids 

525 assert user3.id in res.member_user_ids 

526 

527 

528def test_remove_group_chat_user(db): 

529 # create 3 uses and connect them 

530 user1, token1 = generate_user() 

531 user2, token2 = generate_user() 

532 user3, token3 = generate_user() 

533 make_friends(user1, user2) 

534 make_friends(user1, user3) 

535 

536 # using user token, create a Conversations API for testing 

537 with conversations_session(token1) as c: 

538 # create a group chat 

539 res = c.CreateGroupChat( 

540 conversations_pb2.CreateGroupChatReq( 

541 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title") 

542 ) 

543 ) 

544 group_chat_id = res.group_chat_id 

545 

546 # remove a user from group 

547 c.RemoveGroupChatUser(conversations_pb2.RemoveGroupChatUserReq(group_chat_id=group_chat_id, user_id=user2.id)) 

548 assert user3.id in res.member_user_ids # other users are still in the group 

549 

550 # can't remove the same user twice 

551 with pytest.raises(grpc.RpcError) as e: 

552 c.RemoveGroupChatUser( 

553 conversations_pb2.RemoveGroupChatUserReq(group_chat_id=group_chat_id, user_id=user2.id) 

554 ) 

555 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

556 

557 

558def test_edit_group_chat(db, moderator): 

559 user1, token1 = generate_user() 

560 user2, token2 = generate_user() 

561 user3, token3 = generate_user() 

562 make_friends(user1, user2) 

563 

564 with conversations_session(token1) as c: 

565 # create some threads with messages 

566 res = c.CreateGroupChat( 

567 conversations_pb2.CreateGroupChatReq( 

568 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title") 

569 ) 

570 ) 

571 group_chat_id = res.group_chat_id 

572 moderator.approve_group_chat(group_chat_id) 

573 

574 c.EditGroupChat( 

575 conversations_pb2.EditGroupChatReq( 

576 group_chat_id=group_chat_id, 

577 title=wrappers_pb2.StringValue(value="Modified title"), 

578 only_admins_invite=wrappers_pb2.BoolValue(value=False), 

579 ) 

580 ) 

581 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

582 assert res.title == "Modified title" 

583 assert not res.only_admins_invite 

584 

585 # make sure non-admin is not allowed to modify 

586 with conversations_session(token2) as c: 

587 with pytest.raises(grpc.RpcError) as e: 

588 c.EditGroupChat( 

589 conversations_pb2.EditGroupChatReq( 

590 group_chat_id=group_chat_id, 

591 title=wrappers_pb2.StringValue(value="Other title"), 

592 only_admins_invite=wrappers_pb2.BoolValue(value=True), 

593 ) 

594 ) 

595 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

596 

597 # make sure non-recipient is not allowed to modify 

598 with conversations_session(token3) as c: 

599 with pytest.raises(grpc.RpcError) as e: 

600 c.EditGroupChat( 

601 conversations_pb2.EditGroupChatReq( 

602 group_chat_id=group_chat_id, 

603 title=wrappers_pb2.StringValue(value="Other title"), 

604 only_admins_invite=wrappers_pb2.BoolValue(value=True), 

605 ) 

606 ) 

607 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

608 

609 

610def test_make_remove_group_chat_admin(db, moderator): 

611 user1, token1 = generate_user() 

612 user2, token2 = generate_user() 

613 user3, token3 = generate_user() 

614 

615 make_friends(user1, user2) 

616 make_friends(user1, user3) 

617 make_friends(user2, user3) 

618 

619 with conversations_session(token1) as c: 

620 # create some threads with messages 

621 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])) 

622 group_chat_id = res.group_chat_id 

623 moderator.approve_group_chat(group_chat_id) 

624 

625 # shouldn't be able to remove only admin 

626 with pytest.raises(grpc.RpcError) as e: 

627 c.RemoveGroupChatAdmin( 

628 conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user1.id) 

629 ) 

630 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

631 assert e.value.details() == "You can't remove the last admin." 

632 

633 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id)) 

634 

635 # shouldn't be able to make admin again 

636 with pytest.raises(grpc.RpcError) as e: 

637 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id)) 

638 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

639 assert e.value.details() == "That user is already an admin." 

640 

641 with conversations_session(token2) as c: 

642 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

643 assert user1.id in res.admin_user_ids 

644 assert user2.id in res.admin_user_ids 

645 

646 with conversations_session(token1) as c: 

647 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id)) 

648 

649 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

650 assert user1.id in res.admin_user_ids 

651 assert user2.id not in res.admin_user_ids 

652 

653 with conversations_session(token2) as c: 

654 # shouldn't be able to make admin if not admin 

655 with pytest.raises(grpc.RpcError) as e: 

656 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user3.id)) 

657 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

658 

659 

660def test_send_message(db): 

661 user1, token1 = generate_user() 

662 user2, token2 = generate_user() 

663 user3, token3 = generate_user() 

664 make_friends(user1, user2) 

665 make_friends(user1, user3) 

666 

667 with conversations_session(token1) as c: 

668 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

669 group_chat_id = res.group_chat_id 

670 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

671 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)) 

672 assert res.messages[0].text.text == "Test message 1" 

673 assert to_aware_datetime(res.messages[0].time) <= now() 

674 assert res.messages[0].author_user_id == user1.id 

675 

676 # can't send message if not in chat 

677 with conversations_session(token3) as c: 

678 with pytest.raises(grpc.RpcError) as e: 

679 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 2")) 

680 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

681 

682 make_user_block(user2, user1) 

683 with conversations_session(token1) as c: 

684 with pytest.raises(grpc.RpcError) as e: 

685 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Message after block")) 

686 assert e.value.details() == "You can't send a message in this chat." 

687 

688 

689def test_send_direct_message(db, moderator): 

690 user1, token1 = generate_user(complete_profile=True) 

691 user2, token2 = generate_user(complete_profile=True) 

692 

693 make_friends(user1, user2) 

694 

695 message1 = "Hello, user2!" 

696 message2 = "One more message." 

697 

698 with conversations_session(token1) as c1: 

699 # Send a DM from user1 to user2 

700 res = c1.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=user2.id, text=message1)) 

701 moderator.approve_group_chat(res.group_chat_id) 

702 

703 c1.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=user2.id, text=message2)) 

704 

705 with conversations_session(token2) as c2: 

706 # Fetch the chat by ID returned from SendDirectMessage 

707 chat = c2.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=res.group_chat_id)) 

708 

709 assert chat.is_dm 

710 group_chat_id = chat.group_chat_id 

711 

712 # Verify that the messages was received 

713 messages = c2.GetGroupChatMessages( 

714 conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id) 

715 ).messages 

716 

717 assert len(messages) == 2 

718 assert messages[0].text.text == message2 

719 assert messages[1].text.text == message1 

720 assert messages[0].author_user_id == user1.id 

721 

722 

723def test_excessive_chat_initiations_are_reported(db): 

724 """Test that excessive chat initiations are first reported in a warning email and finally lead blocking of further contacting other users.""" 

725 user, token = generate_user() 

726 rate_limit_definition = RATE_LIMIT_DEFINITIONS[RateLimitAction.chat_initiation] 

727 with conversations_session(token) as c: 

728 # Test warning email 

729 with mock_notification_email() as mock_email: 

730 for _ in range(rate_limit_definition.warning_limit): 

731 recipient_user, _ = generate_user() 

732 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id])) 

733 

734 assert mock_email.call_count == 0 

735 recipient_user, _ = generate_user() 

736 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id])) 

737 

738 assert mock_email.call_count == 1 

739 email = mock_email.mock_calls[0].kwargs["plain"] 

740 assert email.startswith( 

741 f"User {user.username} has sent {rate_limit_definition.warning_limit} chat initiations in the past {RATE_LIMIT_HOURS} hours." 

742 ) 

743 

744 # Test new chat initiations fail after exceeding CHAT_INITIATION_HARD_LIMIT 

745 with mock_notification_email() as mock_email: 

746 for _ in range(rate_limit_definition.hard_limit - rate_limit_definition.warning_limit - 1): 

747 recipient_user, _ = generate_user() 

748 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id])) 

749 

750 assert mock_email.call_count == 0 

751 recipient_user, _ = generate_user() 

752 with pytest.raises(grpc.RpcError) as exc_info: 

753 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id])) 

754 assert exc_info.value.code() == grpc.StatusCode.RESOURCE_EXHAUSTED 

755 assert ( 

756 exc_info.value.details() 

757 == "You have messaged a lot of users in the past 24 hours. To avoid spam, you can't contact any more users for now." 

758 ) 

759 

760 assert mock_email.call_count == 1 

761 email = mock_email.mock_calls[0].kwargs["plain"] 

762 assert email.startswith( 

763 f"User {user.username} has sent {rate_limit_definition.hard_limit} chat initiations in the past {RATE_LIMIT_HOURS} hours." 

764 ) 

765 assert "The user has been blocked from sending further chat initiations for now." in email 

766 

767 

768def test_leave_invite_to_group_chat(db, moderator): 

769 user1, token1 = generate_user() 

770 user2, token2 = generate_user() 

771 user3, token3 = generate_user() 

772 user4, token4 = generate_user() 

773 user5, token5 = generate_user() 

774 user6, token6 = generate_user(delete_user=True) 

775 user7, token7 = generate_user() 

776 user8, token8 = generate_user() 

777 

778 make_friends(user1, user2) 

779 make_friends(user1, user3) 

780 make_friends(user1, user5) 

781 make_friends(user1, user7) 

782 make_friends(user1, user8) 

783 make_friends(user2, user3) 

784 make_friends(user4, user3) 

785 make_user_block(user1, user7) 

786 make_user_block(user8, user1) 

787 

788 with conversations_session(token1) as c: 

789 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user5.id])) 

790 group_chat_id = res.group_chat_id 

791 moderator.approve_group_chat(group_chat_id) 

792 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

793 

794 # other user not in chat 

795 with conversations_session(token3) as c: 

796 with pytest.raises(grpc.RpcError) as e: 

797 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

798 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

799 with pytest.raises(grpc.RpcError) as e: 

800 res = c.InviteToGroupChat( 

801 conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user4.id) 

802 ) 

803 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

804 with pytest.raises(grpc.RpcError) as e: 

805 res = c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

806 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

807 

808 with conversations_session(token2) as c: 

809 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

810 assert user3.id not in res.member_user_ids 

811 

812 # only_admins_invite defaults to true so shouldn't be able to invite 

813 with pytest.raises(grpc.RpcError) as e: 

814 res = c.InviteToGroupChat( 

815 conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id) 

816 ) 

817 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

818 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

819 

820 with conversations_session(token1) as c: 

821 # invite invisible user fails 

822 with pytest.raises(grpc.RpcError) as e: 

823 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user6.id)) 

824 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

825 assert e.value.details() == "Couldn't find that user." 

826 # invite fake user fails 

827 with pytest.raises(grpc.RpcError) as e: 

828 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=999)) 

829 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

830 assert e.value.details() == "Couldn't find that user." 

831 # invite blocked user fails 

832 with pytest.raises(grpc.RpcError) as e: 

833 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user7.id)) 

834 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

835 assert e.value.details() == "Couldn't find that user." 

836 # invite blocking user fails 

837 with pytest.raises(grpc.RpcError) as e: 

838 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user8.id)) 

839 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

840 assert e.value.details() == "Couldn't find that user." 

841 

842 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)) 

843 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

844 assert user1.id in res.member_user_ids 

845 assert user5.id in res.member_user_ids 

846 assert user3.id in res.member_user_ids 

847 

848 # test non-admin inviting 

849 c.EditGroupChat( 

850 conversations_pb2.EditGroupChatReq( 

851 group_chat_id=group_chat_id, only_admins_invite=wrappers_pb2.BoolValue(value=False) 

852 ) 

853 ) 

854 

855 with conversations_session(token3) as c: 

856 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user2.id)) 

857 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

858 assert user2.id in res.member_user_ids 

859 

860 

861def test_group_chats_with_messages_before_join(db, moderator): 

862 """ 

863 If user 1 and 2 have a group chat and send messages, then add user 3; user 3 

864 should still see the group chat! 

865 """ 

866 user1, token1 = generate_user() 

867 user2, token2 = generate_user() 

868 user3, token3 = generate_user() 

869 user4, token4 = generate_user() 

870 

871 make_friends(user1, user2) 

872 make_friends(user1, user3) 

873 make_friends(user2, user3) 

874 make_friends(user1, user4) 

875 

876 with conversations_session(token1) as c: 

877 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id])) 

878 group_chat_id = res.group_chat_id 

879 moderator.approve_group_chat(group_chat_id) 

880 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

881 

882 with conversations_session(token2) as c: 

883 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 2")) 

884 

885 with conversations_session(token1) as c: 

886 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 3")) 

887 

888 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)) 

889 

890 with conversations_session(token3) as c: 

891 # should work 

892 c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

893 

894 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

895 assert len(res.group_chats) == 1 

896 

897 

898def test_invite_to_dm(db): 

899 user1, token1 = generate_user() 

900 user2, token2 = generate_user() 

901 user3, token3 = generate_user() 

902 

903 make_friends(user1, user2) 

904 make_friends(user1, user3) 

905 make_friends(user2, user3) 

906 

907 with conversations_session(token1) as c: 

908 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

909 group_chat_id = res.group_chat_id 

910 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

911 

912 # dm, shou;dn't be able to invite someone else 

913 with pytest.raises(grpc.RpcError) as e: 

914 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)) 

915 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

916 assert e.value.details() == "You can't invite other users to a direct message." 

917 

918 

919def test_sole_admin_leaves(db, moderator): 

920 user1, token1 = generate_user() 

921 user2, token2 = generate_user() 

922 user3, token3 = generate_user() 

923 

924 make_friends(user1, user2) 

925 make_friends(user1, user3) 

926 make_friends(user2, user3) 

927 

928 with conversations_session(token1) as c: 

929 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])) 

930 group_chat_id = res.group_chat_id 

931 moderator.approve_group_chat(group_chat_id) 

932 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

933 

934 # sole admin can't leave group chat 

935 with pytest.raises(grpc.RpcError) as e: 

936 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

937 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

938 assert e.value.details() == "The last admin can't leave a group chat." 

939 

940 with conversations_session(token2) as c: 

941 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

942 

943 with conversations_session(token3) as c: 

944 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

945 

946 # sole admin can leave when last in chat 

947 with conversations_session(token1) as c: 

948 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

949 

950 

951def test_search_messages(db, moderator): 

952 user1, token1 = generate_user() 

953 user2, token2 = generate_user() 

954 user3, token3 = generate_user() 

955 

956 make_friends(user1, user2) 

957 make_friends(user1, user3) 

958 

959 with conversations_session(token1) as c: 

960 # create some threads with messages 

961 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

962 gc1_id = res.group_chat_id 

963 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc1_id, text="Test message 1")) 

964 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc1_id, text="Test message 2")) 

965 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])) 

966 gc2_id = res.group_chat_id 

967 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc2_id, text="Test group message 3")) 

968 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc2_id, text="Test group message 4")) 

969 

970 # Approve group chats so they appear in search results 

971 moderator.approve_group_chat(gc1_id) 

972 moderator.approve_group_chat(gc2_id) 

973 

974 with conversations_session(token1) as c: 

975 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="message ")) 

976 assert len(res.results) == 4 

977 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="group ")) 

978 assert len(res.results) == 2 

979 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="message 5")) 

980 assert len(res.results) == 0 

981 

982 # outside user doesn't get results 

983 with conversations_session(token3) as c: 

984 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message")) 

985 assert len(res.results) == 0 

986 

987 

988def test_search_messages_left_joined(db, moderator): 

989 user1, token1 = generate_user() 

990 user2, token2 = generate_user() 

991 user3, token3 = generate_user() 

992 user4, token4 = generate_user() 

993 make_friends(user1, user2) 

994 make_friends(user1, user3) 

995 make_friends(user1, user4) 

996 

997 with conversations_session(token1) as c: 

998 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id])) 

999 group_chat_id = res.group_chat_id 

1000 moderator.approve_group_chat(group_chat_id) 

1001 for i in range(10): 

1002 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message " + str(i))) 

1003 

1004 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)) 

1005 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 10")) 

1006 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message")) 

1007 

1008 assert len(res.results) == 11 

1009 

1010 with conversations_session(token3) as c: 

1011 # can only see last message after invited 

1012 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message")) 

1013 

1014 assert len(res.results) == 1 

1015 assert res.results[0].message.text.text == "Test message 10" 

1016 

1017 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

1018 

1019 with conversations_session(token1) as c: 

1020 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 11")) 

1021 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 12")) 

1022 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)) 

1023 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 13")) 

1024 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 14")) 

1025 

1026 with conversations_session(token3) as c: 

1027 # can only see last message after invited 

1028 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message")) 

1029 assert len(res.results) == 3 

1030 assert res.results[0].message.text.text == "Test message 14" 

1031 assert res.results[1].message.text.text == "Test message 13" 

1032 assert res.results[2].message.text.text == "Test message 10" 

1033 

1034 

1035def test_admin_behaviour(db, moderator): 

1036 user1, token1 = generate_user() 

1037 user2, token2 = generate_user() 

1038 user3, token3 = generate_user() 

1039 

1040 make_friends(user1, user2) 

1041 make_friends(user1, user3) 

1042 make_friends(user2, user3) 

1043 

1044 with conversations_session(token1) as c: 

1045 gcid = c.CreateGroupChat( 

1046 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]) 

1047 ).group_chat_id 

1048 moderator.approve_group_chat(gcid) 

1049 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user2.id)) 

1050 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1051 assert len(res.admin_user_ids) == 2 

1052 assert user1.id in res.admin_user_ids 

1053 assert user2.id in res.admin_user_ids 

1054 

1055 with conversations_session(token3) as c: 

1056 with pytest.raises(grpc.RpcError) as e: 

1057 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1058 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

1059 with pytest.raises(grpc.RpcError) as e: 

1060 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id)) 

1061 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

1062 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1063 assert len(res.admin_user_ids) == 2 

1064 assert user1.id in res.admin_user_ids 

1065 assert user2.id in res.admin_user_ids 

1066 

1067 with conversations_session(token2) as c: 

1068 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1069 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1070 assert len(res.admin_user_ids) == 3 

1071 assert user1.id in res.admin_user_ids 

1072 assert user2.id in res.admin_user_ids 

1073 assert user3.id in res.admin_user_ids 

1074 

1075 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id)) 

1076 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1077 assert len(res.admin_user_ids) == 2 

1078 assert user2.id in res.admin_user_ids 

1079 assert user3.id in res.admin_user_ids 

1080 

1081 with conversations_session(token1) as c: 

1082 with pytest.raises(grpc.RpcError): 

1083 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id)) 

1084 with pytest.raises(grpc.RpcError): 

1085 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1086 with pytest.raises(grpc.RpcError): 

1087 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user2.id)) 

1088 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1089 assert len(res.admin_user_ids) == 2 

1090 assert user2.id in res.admin_user_ids 

1091 assert user3.id in res.admin_user_ids 

1092 

1093 with conversations_session(token2) as c: 

1094 # can demote self if there are other admins 

1095 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user2.id)) 

1096 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1097 assert len(res.admin_user_ids) == 1 

1098 assert user3.id in res.admin_user_ids 

1099 

1100 with conversations_session(token3) as c: 

1101 with pytest.raises(grpc.RpcError) as e: 

1102 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1103 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1104 assert e.value.details() == "You can't remove the last admin." 

1105 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1106 assert len(res.admin_user_ids) == 1 

1107 assert user3.id in res.admin_user_ids 

1108 

1109 # last admin can't leave 

1110 with pytest.raises(grpc.RpcError) as e: 

1111 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid)) 

1112 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1113 assert e.value.details() == "The last admin can't leave a group chat." 

1114 

1115 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id)) 

1116 

1117 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid)) 

1118 

1119 with conversations_session(token2) as c: 

1120 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid)) 

1121 

1122 # last participant must be admin but can leave to orphan chat 

1123 with conversations_session(token1) as c: 

1124 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid)) 

1125 

1126 

1127def test_add_remove_admin_failures(db): 

1128 user1, token1 = generate_user() 

1129 user2, token2 = generate_user() 

1130 user3, token3 = generate_user() 

1131 user4, token4 = generate_user() 

1132 user5, token5 = generate_user() 

1133 

1134 make_friends(user1, user2) 

1135 make_friends(user1, user3) 

1136 make_friends(user1, user4) 

1137 make_friends(user1, user5) 

1138 

1139 with conversations_session(token1) as c: 

1140 gcid = c.CreateGroupChat( 

1141 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id, user4.id, user5.id]) 

1142 ).group_chat_id 

1143 

1144 make_user_invisible(user3.id) 

1145 make_user_block(user1, user4) 

1146 make_user_block(user5, user1) 

1147 

1148 # make non-existent user admin 

1149 with pytest.raises(grpc.RpcError) as e: 

1150 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=999)) 

1151 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1152 assert e.value.details() == "Couldn't find that user." 

1153 

1154 # make invisible user admin 

1155 with pytest.raises(grpc.RpcError) as e: 

1156 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1157 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1158 assert e.value.details() == "Couldn't find that user." 

1159 

1160 # make blocked user admin 

1161 with pytest.raises(grpc.RpcError) as e: 

1162 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user4.id)) 

1163 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1164 assert e.value.details() == "Couldn't find that user." 

1165 

1166 # make blocking user admin 

1167 with pytest.raises(grpc.RpcError) as e: 

1168 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user5.id)) 

1169 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1170 assert e.value.details() == "Couldn't find that user." 

1171 

1172 with session_scope() as session: 

1173 subscriptions = ( 

1174 session.execute( 

1175 select(GroupChatSubscription) 

1176 .where(GroupChatSubscription.group_chat_id == gcid) 

1177 .where(GroupChatSubscription.role == GroupChatRole.participant) 

1178 ) 

1179 .scalars() 

1180 .all() 

1181 ) 

1182 

1183 for subscription in subscriptions: 

1184 subscription.role = GroupChatRole.admin 

1185 

1186 with conversations_session(token1) as c: 

1187 # remove non-existent user admin 

1188 with pytest.raises(grpc.RpcError) as e: 

1189 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=999)) 

1190 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1191 assert e.value.details() == "Couldn't find that user." 

1192 

1193 # remove invisible admin 

1194 with pytest.raises(grpc.RpcError) as e: 

1195 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1196 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1197 assert e.value.details() == "Couldn't find that user." 

1198 

1199 # remove blocked admin 

1200 with pytest.raises(grpc.RpcError) as e: 

1201 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user4.id)) 

1202 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1203 assert e.value.details() == "Couldn't find that user." 

1204 

1205 # remove blocking admin 

1206 with pytest.raises(grpc.RpcError) as e: 

1207 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user5.id)) 

1208 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1209 assert e.value.details() == "Couldn't find that user." 

1210 

1211 

1212def test_last_seen(db, moderator): 

1213 user1, token1 = generate_user() 

1214 user2, token2 = generate_user() 

1215 user3, token3 = generate_user() 

1216 

1217 make_friends(user1, user2) 

1218 make_friends(user1, user3) 

1219 make_friends(user2, user3) 

1220 

1221 with conversations_session(token3) as c: 

1222 # this is just here to mess up any issues we get if we pretend there's only one group chat ever 

1223 gcid_distraction = c.CreateGroupChat( 

1224 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user1.id]) 

1225 ).group_chat_id 

1226 moderator.approve_group_chat(gcid_distraction) 

1227 

1228 with conversations_session(token1) as c: 

1229 gcid = c.CreateGroupChat( 

1230 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]) 

1231 ).group_chat_id 

1232 moderator.approve_group_chat(gcid) 

1233 

1234 message_ids = [] 

1235 

1236 for i in range(6): 

1237 c.SendMessage( 

1238 conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text=f"gibberish message... {i}") 

1239 ) 

1240 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}")) 

1241 c.SendMessage( 

1242 conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text=f"gibberish message {i}") 

1243 ) 

1244 

1245 message_ids.append( 

1246 c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)).latest_message.message_id 

1247 ) 

1248 

1249 # messages are automatically marked as seen when you send a new message 

1250 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1251 assert res.unseen_message_count == 0 

1252 

1253 with conversations_session(token2) as c: 

1254 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1255 # created + 6 normal 

1256 assert res.unseen_message_count == 7 

1257 

1258 backward_offset = 3 

1259 c.MarkLastSeenGroupChat( 

1260 conversations_pb2.MarkLastSeenGroupChatReq( 

1261 group_chat_id=gcid, last_seen_message_id=message_ids[-backward_offset - 1] 

1262 ) 

1263 ) 

1264 

1265 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1266 assert res.unseen_message_count == backward_offset 

1267 

1268 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="test message ...")) 

1269 

1270 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1271 assert res.unseen_message_count == 0 

1272 

1273 with conversations_session(token3) as c: 

1274 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1275 # created + 7 normal 

1276 assert res.unseen_message_count == 8 

1277 

1278 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="test message ...")) 

1279 

1280 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1281 assert res.unseen_message_count == 0 

1282 

1283 

1284def test_one_dm_per_pair(db, moderator): 

1285 user1, token1 = generate_user() 

1286 user2, token2 = generate_user() 

1287 user3, token3 = generate_user() 

1288 

1289 make_friends(user1, user2) 

1290 make_friends(user1, user3) 

1291 make_friends(user2, user3) 

1292 

1293 with conversations_session(token1) as c: 

1294 # create DM with user 2 

1295 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

1296 assert res.is_dm 

1297 dm_with_user2 = res.group_chat_id 

1298 

1299 # create DM with user 3 

1300 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])) 

1301 assert res.is_dm 

1302 dm_with_user3 = res.group_chat_id 

1303 

1304 # can't create another group chat with just user 2 

1305 with pytest.raises(grpc.RpcError) as e: 

1306 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

1307 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1308 

1309 # can't create another group chat with just user 3 

1310 with pytest.raises(grpc.RpcError) as e: 

1311 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])) 

1312 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1313 

1314 # can create joined group chat 

1315 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])) 

1316 assert not res.is_dm 

1317 

1318 # Approve the DMs so user2 can see them (otherwise they're SHADOWED and only visible to creator) 

1319 moderator.approve_group_chat(dm_with_user2) 

1320 

1321 with conversations_session(token2) as c: 

1322 # can create DM with user 3 

1323 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])) 

1324 assert res.is_dm 

1325 

1326 # can't create another group chat with just user 1 (DM was approved, so user2 can see it) 

1327 with pytest.raises(grpc.RpcError) as e: 

1328 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user1.id])) 

1329 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1330 

1331 

1332def test_GetDirectMessage(db): 

1333 user1, token1 = generate_user() 

1334 user2, token2 = generate_user() 

1335 user3, token3 = generate_user() 

1336 

1337 make_friends(user1, user2) 

1338 make_friends(user1, user3) 

1339 make_friends(user2, user3) 

1340 

1341 with conversations_session(token1) as c: 

1342 # no group chat with user 2 

1343 with pytest.raises(grpc.RpcError) as e: 

1344 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user2.id)) 

1345 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1346 

1347 # no group chat with nor user 3 

1348 with pytest.raises(grpc.RpcError) as e: 

1349 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user3.id)) 

1350 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1351 

1352 # create DM with user 2 

1353 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

1354 assert res.is_dm 

1355 gcid = res.group_chat_id 

1356 

1357 # now should exist 

1358 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user2.id)) 

1359 assert res.group_chat_id == gcid 

1360 

1361 # create DM with user 3 

1362 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])) 

1363 assert res.is_dm 

1364 

1365 # can create joined group chat 

1366 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])) 

1367 assert not res.is_dm 

1368 

1369 with conversations_session(token2) as c: 

1370 # can create DM with user 3 

1371 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])) 

1372 assert res.is_dm 

1373 assert res.can_message 

1374 gcid = res.group_chat_id 

1375 

1376 # DM with 3 should exist, but can't message after being blocked 

1377 make_user_block(user3, user2) 

1378 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user3.id)) 

1379 assert res.group_chat_id == gcid 

1380 assert not res.can_message 

1381 

1382 

1383def test_total_unseen(db, moderator): 

1384 user1, token1 = generate_user() 

1385 user2, token2 = generate_user() 

1386 user3, token3 = generate_user() 

1387 

1388 # distractions 

1389 user4, token4 = generate_user() 

1390 

1391 make_friends(user1, user2) 

1392 make_friends(user1, user3) 

1393 make_friends(user2, user3) 

1394 

1395 # distractions 

1396 make_friends(user1, user4) 

1397 

1398 with conversations_session(token1) as c: 

1399 # distractions 

1400 gcid_distraction = c.CreateGroupChat( 

1401 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user4.id]) 

1402 ).group_chat_id 

1403 moderator.approve_group_chat(gcid_distraction) 

1404 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction...")) 

1405 

1406 gcid = c.CreateGroupChat( 

1407 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]) 

1408 ).group_chat_id 

1409 moderator.approve_group_chat(gcid) 

1410 

1411 for i in range(6): 

1412 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}")) 

1413 

1414 # distractions 

1415 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction...")) 

1416 

1417 # messages are automatically marked as seen when you send a new message 

1418 with api_session(token1) as api: 

1419 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0 

1420 

1421 with api_session(token2) as api: 

1422 # chat created + 6 normal messages 

1423 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 7 

1424 

1425 # now leave chat with user2 

1426 with conversations_session(token2) as c: 

1427 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid)) 

1428 

1429 with api_session(token2) as api: 

1430 # seen messages becomes 0 when leaving 

1431 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0 

1432 

1433 with conversations_session(token1) as c: 

1434 # distractions 

1435 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction...")) 

1436 

1437 # send more stuff without user 2 

1438 for i in range(3): 

1439 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}")) 

1440 

1441 # distractions 

1442 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction...")) 

1443 

1444 with api_session(token2) as api: 

1445 # seen messages becomes 0 when leaving 

1446 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0 

1447 

1448 with conversations_session(token1) as c: 

1449 # add user 2 back 

1450 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=gcid, user_id=user2.id)) 

1451 

1452 # send more stuff with user 2 

1453 for i in range(12): 

1454 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}")) 

1455 

1456 # distractions 

1457 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction...")) 

1458 

1459 with api_session(token2) as api: 

1460 # joined + 12 normal 

1461 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 13 

1462 

1463 

1464def test_regression_ListGroupChats_pagination(db, moderator): 

1465 user1, token1 = generate_user() 

1466 user2, token2 = generate_user() 

1467 user3, token3 = generate_user() 

1468 

1469 make_friends(user1, user2) 

1470 make_friends(user1, user3) 

1471 

1472 with conversations_session(token1) as c: 

1473 # tuples of (group_chat_id, message_id) 

1474 group_chat_and_message_ids = [] 

1475 for i in range(50): 

1476 res1 = c.CreateGroupChat( 

1477 conversations_pb2.CreateGroupChatReq( 

1478 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value=f"Chat {i}") 

1479 ) 

1480 ) 

1481 

1482 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res1.group_chat_id, text=f"Test message {i}")) 

1483 

1484 res2 = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=res1.group_chat_id)) 

1485 

1486 group_chat_and_message_ids.append((res2.group_chat_id, res2.latest_message.message_id)) 

1487 moderator.approve_group_chat(res1.group_chat_id) 

1488 

1489 seen_group_chat_ids = [] 

1490 

1491 last_message_id = 0 

1492 more = True 

1493 while more: 

1494 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(last_message_id=last_message_id)) 

1495 last_message_id = res.last_message_id 

1496 more = not res.no_more 

1497 

1498 seen_group_chat_ids.extend([chat.group_chat_id for chat in res.group_chats]) 

1499 

1500 assert set(seen_group_chat_ids) == {x[0] for x in group_chat_and_message_ids}, "Not all group chats returned" 

1501 

1502 

1503def test_muting(db, moderator): 

1504 user1, token1 = generate_user() 

1505 user2, token2 = generate_user() 

1506 user3, token3 = generate_user() 

1507 

1508 make_friends(user1, user2) 

1509 make_friends(user1, user3) 

1510 make_friends(user2, user3) 

1511 

1512 with conversations_session(token3) as c: 

1513 # this is just here to mess up any issues we get if we pretend there's only one group chat ever 

1514 gcid_distraction = c.CreateGroupChat( 

1515 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user1.id]) 

1516 ).group_chat_id 

1517 moderator.approve_group_chat(gcid_distraction) 

1518 

1519 with conversations_session(token1) as c: 

1520 gcid = c.CreateGroupChat( 

1521 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]) 

1522 ).group_chat_id 

1523 moderator.approve_group_chat(gcid) 

1524 

1525 with conversations_session(token2) as c: 

1526 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1527 assert not res.mute_info.muted 

1528 assert not res.mute_info.HasField("muted_until") 

1529 

1530 c.MuteGroupChat(conversations_pb2.MuteGroupChatReq(group_chat_id=gcid, forever=True)) 

1531 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1532 assert res.mute_info.muted 

1533 assert not res.mute_info.HasField("muted_until") 

1534 

1535 c.MuteGroupChat(conversations_pb2.MuteGroupChatReq(group_chat_id=gcid, unmute=True)) 

1536 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1537 assert not res.mute_info.muted 

1538 assert not res.mute_info.HasField("muted_until") 

1539 

1540 c.MuteGroupChat( 

1541 conversations_pb2.MuteGroupChatReq( 

1542 group_chat_id=gcid, for_duration=Duration_from_timedelta(timedelta(hours=2)) 

1543 ) 

1544 ) 

1545 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1546 assert res.mute_info.muted 

1547 assert res.mute_info.HasField("muted_until") 

1548 assert to_aware_datetime(res.mute_info.muted_until) >= now() + timedelta(hours=1, minutes=59) 

1549 assert to_aware_datetime(res.mute_info.muted_until) <= now() + timedelta(hours=2, minutes=1) 

1550 

1551 

1552def test_chat_notifications(db, moderator): 

1553 user1, token1 = generate_user() 

1554 user2, token2 = generate_user() 

1555 # notifs off 

1556 user3, token3 = generate_user() 

1557 user4, token4 = generate_user() 

1558 user5, token5 = generate_user() 

1559 user6, token6 = generate_user() 

1560 

1561 make_friends(user1, user2) 

1562 make_friends(user1, user3) 

1563 make_friends(user1, user4) 

1564 make_friends(user4, user5) 

1565 make_friends(user4, user6) 

1566 

1567 # have some of them enable/disable notifs 

1568 topic_action = NotificationTopicAction.chat__message 

1569 for token, enabled in [ 

1570 (token1, True), 

1571 (token2, True), 

1572 (token3, False), 

1573 (token4, True), 

1574 (token5, True), 

1575 (token6, True), 

1576 ]: 

1577 with notifications_session(token) as notifications: 

1578 notifications.SetNotificationSettings( 

1579 notifications_pb2.SetNotificationSettingsReq( 

1580 preferences=[ 

1581 notifications_pb2.SingleNotificationPreference( 

1582 topic=topic_action.topic, 

1583 action=topic_action.action, 

1584 delivery_method=delivery_method, 

1585 enabled=enabled, 

1586 ) 

1587 for delivery_method in ["push", "email", "digest"] 

1588 ], 

1589 ) 

1590 ) 

1591 

1592 group_chat_id = None 

1593 

1594 def send_msg(c, i): 

1595 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=f"Test message {i}")) 

1596 

1597 with conversations_session(token1) as c: 

1598 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id, user4.id])) 

1599 group_chat_id = res.group_chat_id 

1600 moderator.approve_group_chat(group_chat_id) 

1601 c.EditGroupChat( 

1602 conversations_pb2.EditGroupChatReq( 

1603 group_chat_id=group_chat_id, only_admins_invite=wrappers_pb2.BoolValue(value=False) 

1604 ) 

1605 ) 

1606 send_msg(c, i=1) 

1607 send_msg(c, i=2) 

1608 

1609 with conversations_session(token4) as c: 

1610 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user5.id)) 

1611 send_msg(c, i=3) 

1612 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user6.id)) 

1613 send_msg(c, i=4) 

1614 send_msg(c, i=5) 

1615 

1616 with conversations_session(token3) as c: 

1617 send_msg(c, i=6) 

1618 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

1619 

1620 with conversations_session(token2) as c: 

1621 send_msg(c, i=7) 

1622 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

1623 

1624 with conversations_session(token6) as c: 

1625 send_msg(c, i=8) 

1626 

1627 # go through all bg jobs 

1628 while process_job(): 

1629 pass 

1630 

1631 # now check notifs... 

1632 expected_notifs = [ 

1633 (user1, "user1", [3, 4, 5, 6, 7, 8]), 

1634 (user2, "user2", [1, 2, 3, 4, 5, 6]), 

1635 (user3, "user3", []), # notifs off 

1636 (user4, "user4", [1, 2, 6, 7, 8]), 

1637 (user5, "user5", [3, 4, 5, 6, 7, 8]), 

1638 (user6, "user6", [4, 5, 6, 7]), 

1639 ] 

1640 

1641 with session_scope() as session: 

1642 for user, label, expected_msgs in expected_notifs: 

1643 deliv = ( 

1644 session.execute( 

1645 select(Notification.data) 

1646 .join(NotificationDelivery, NotificationDelivery.notification_id == Notification.id) 

1647 .where(Notification.user_id == user.id) 

1648 .where(Notification.topic_action == topic_action) 

1649 .where(NotificationDelivery.delivery_type == NotificationDeliveryType.push) 

1650 .order_by(Notification.created) 

1651 ) 

1652 .scalars() 

1653 .all() 

1654 ) 

1655 

1656 def parse_message_payload(data): 

1657 return notification_data_pb2.ChatMessage.FromString(data).text 

1658 

1659 contents = [parse_message_payload(d) for d in deliv] 

1660 

1661 print(contents) 

1662 

1663 assert [f"Test message {i}" for i in expected_msgs] == contents, f"Wrong messages for {label}" 

1664 

1665 

1666def test_incomplete_profile(db): 

1667 user1, token1 = generate_user(complete_profile=True) 

1668 user2, token2 = generate_user(complete_profile=False) 

1669 user3, token3 = generate_user(complete_profile=True) 

1670 make_friends(user1, user2) 

1671 make_friends(user1, user3) 

1672 

1673 # user 1 can make a chat 

1674 with conversations_session(token1) as c: 

1675 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

1676 group_chat_id = res.group_chat_id 

1677 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

1678 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)) 

1679 assert res.messages[0].text.text == "Test message 1" 

1680 assert to_aware_datetime(res.messages[0].time) <= now() 

1681 assert res.messages[0].author_user_id == user1.id 

1682 

1683 # user 2 cannot 

1684 with conversations_session(token2) as c: 

1685 with pytest.raises(grpc.RpcError) as e: 

1686 c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])) 

1687 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1688 assert e.value.details() == "You have to complete your profile before you can send a message."