Skip to content

Commit a913b67

Browse files
Merge pull request #474 from teidesu/age-verification
Age verification
2 parents a4bfd78 + 99b5f29 commit a913b67

40 files changed

+890
-123
lines changed

src/components/appMediaPlaybackController.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const SEEK_OFFSET = 10;
4646

4747
export type MediaSearchContext = SearchSuperContext & Partial<{
4848
isScheduled: boolean,
49+
skipSensitive: boolean,
4950
useSearch: boolean
5051
}>;
5152

src/components/appSearchSuper..ts

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ import wrapDocument from './wrappers/document';
7272
import wrapPhoto from './wrappers/photo';
7373
import wrapVideo from './wrappers/video';
7474
import noop from '../helpers/noop';
75-
import wrapMediaSpoiler, {onMediaSpoilerClick} from './wrappers/mediaSpoiler';
75+
import wrapMediaSpoiler, {hasSensitiveSpoiler, onMediaSpoilerClick} from './wrappers/mediaSpoiler';
7676
import filterAsync from '../helpers/array/filterAsync';
7777
import ChatContextMenu, {getSponsoredMessageButtons} from './chat/contextMenu';
7878
import PopupElement from './popups';
@@ -101,6 +101,10 @@ import PopupReportAd from './popups/reportAd';
101101
import createContextMenu from '../helpers/dom/createContextMenu';
102102
import ButtonMenuToggle from './buttonMenuToggle';
103103
import EmptySearchPlaceholder from './emptySearchPlaceholder';
104+
import {SensitiveContentSettings} from '../lib/appManagers/appPrivacyManager';
105+
import {ignoreRestrictionReasons, isSensitive} from '../helpers/restrictions';
106+
import {isMessageSensitive} from '../lib/appManagers/utils/messages/isMessageRestricted';
107+
import {MediaSearchContext} from './appMediaPlaybackController';
104108

105109
// const testScroll = false;
106110

@@ -245,13 +249,13 @@ class SearchContextMenu {
245249
}, {
246250
icon: 'download',
247251
text: 'MediaViewer.Context.Download',
248-
onClick: () => ChatContextMenu.onDownloadClick(this.message, this.noForwards),
249-
verify: () => !this.searchSuper.selection.isSelecting && ChatContextMenu.canDownload(this.message, undefined, this.noForwards)
252+
onClick: () => ChatContextMenu.onDownloadClick(this.message, this.noForwards, this.attachTo),
253+
verify: () => !this.searchSuper.selection.isSelecting && ChatContextMenu.canDownload(this.message, undefined, this.noForwards, this.attachTo)
250254
}, {
251255
icon: 'download',
252256
text: 'Message.Context.Selection.Download',
253-
onClick: () => ChatContextMenu.onDownloadClick(this.selectedMessages, this.noForwards),
254-
verify: () => this.searchSuper.selection.isSelecting && ChatContextMenu.canDownload(this.selectedMessages, undefined, this.noForwards),
257+
onClick: () => ChatContextMenu.onDownloadClick(this.selectedMessages, this.noForwards, this.attachTo),
258+
verify: () => this.searchSuper.selection.isSelecting && ChatContextMenu.canDownload(this.selectedMessages, undefined, this.noForwards, this.attachTo),
255259
withSelection: true
256260
}, {
257261
icon: 'message',
@@ -408,6 +412,9 @@ export default class AppSearchSuper {
408412
private log = logger('SEARCH-SUPER');
409413
public selectTab: ReturnType<typeof horizontalMenu>;
410414

415+
private sensitiveContentSettings: SensitiveContentSettings;
416+
private isChatSensitive: boolean;
417+
411418
private monthContainers: Partial<{
412419
[type in SearchSuperType]: {
413420
[timestamp: number]: {
@@ -710,29 +717,35 @@ export default class AppSearchSuper {
710717
if(mediaSpoiler) {
711718
onMediaSpoilerClick({
712719
event: e,
713-
mediaSpoiler
720+
mediaSpoiler,
721+
sensitiveSettings: this.sensitiveContentSettings
714722
})
715723
return;
716724
}
717725

718726
const peerId = target.dataset.peerId.toPeerId();
727+
const message = await this.managers.appMessagesManager.getMessageByPeer(peerId, mid);
728+
const skipSensitive = !this.isChatSensitive && !isMessageSensitive(message);
719729

720730
const targets = (Array.from(this.tabs[inputFilter].querySelectorAll('.' + targetClassName)) as HTMLElement[]).map((el) => {
721731
const containerEl = findUpClassName(el, className);
732+
if(skipSensitive && hasSensitiveSpoiler(containerEl)) {
733+
return;
734+
}
735+
722736
return {
723737
element: el,
724738
mid: +containerEl.dataset.mid,
725739
peerId: containerEl.dataset.peerId.toPeerId()
726740
};
727-
});
741+
}).filter(Boolean);
728742

729743
// const ids = Object.keys(this.mediaDivsByIds).map((k) => +k).sort((a, b) => a - b);
730744
const idx = targets.findIndex((item) => item.mid === mid && item.peerId === peerId);
731745

732746
const mediaTab = this.mediaTabs.find((mediaTab) => mediaTab.inputFilter === inputFilter);
733-
const message = await this.managers.appMessagesManager.getMessageByPeer(peerId, mid);
734747
new AppMediaViewer()
735-
.setSearchContext(this.copySearchContext(inputFilter, this.nextRates[mediaTab.type]))
748+
.setSearchContext(this.copySearchContext(inputFilter, this.nextRates[mediaTab.type], skipSensitive))
736749
.openMedia({
737750
message,
738751
target: targets[idx].element,
@@ -773,6 +786,10 @@ export default class AppSearchSuper {
773786
}, () => {
774787
this.lazyLoadQueue.unlockAndRefresh(); // ! maybe not so efficient
775788
}, this.listenerSetter);
789+
790+
this.listenerSetter.add(rootScope)('sensitive_content_settings', (sensitiveContentSettings) => {
791+
this.sensitiveContentSettings = sensitiveContentSettings;
792+
});
776793
}
777794

778795
private scrollToStart() {
@@ -887,11 +904,14 @@ export default class AppSearchSuper {
887904
});
888905
}
889906

890-
if((message.media as MessageMedia.messageMediaPhoto).pFlags.spoiler) {
907+
const sensitive = this.isChatSensitive || isMessageSensitive(message);
908+
909+
if((message.media as MessageMedia.messageMediaPhoto).pFlags.spoiler || sensitive) {
891910
const mediaSpoiler = await wrapMediaSpoiler({
892911
animationGroup: 'chat',
893912
media,
894913
middleware,
914+
sensitive,
895915
width: 140,
896916
height: 140,
897917
multiply: 0.3
@@ -922,7 +942,7 @@ export default class AppSearchSuper {
922942
fontWeight: 400,
923943
voiceAsMusic: true,
924944
showSender,
925-
searchContext: this.copySearchContext(inputFilter, this.nextRates.files),
945+
searchContext: this.copySearchContext(inputFilter, this.nextRates.files, false),
926946
lazyLoadQueue: this.lazyLoadQueue,
927947
autoDownloadSize: 0,
928948
getSize: () => 320
@@ -2264,7 +2284,9 @@ export default class AppSearchSuper {
22642284
canViewGroups,
22652285
canViewStories,
22662286
canViewSimilar,
2267-
giftsCount
2287+
giftsCount,
2288+
sensitiveContentSettings,
2289+
chatRestrictions
22682290
] = await Promise.all([
22692291
this.managers.appMessagesManager.getSearchCounters(peerId, filters, undefined, threadId),
22702292
this.canViewSavedDialogs(),
@@ -2273,13 +2295,19 @@ export default class AppSearchSuper {
22732295
this.canViewGroups(),
22742296
this.canViewStories(),
22752297
this.canViewSimilar(),
2276-
this.getGiftsCount()
2298+
this.getGiftsCount(),
2299+
this.managers.appPrivacyManager.getSensitiveContentSettings(),
2300+
this.managers.appPeersManager.getPeerRestrictions(peerId)
22772301
]);
22782302

22792303
if(!middleware()) {
22802304
return;
22812305
}
22822306

2307+
this.sensitiveContentSettings = sensitiveContentSettings;
2308+
ignoreRestrictionReasons(this.sensitiveContentSettings.ignoreRestrictionReasons);
2309+
this.isChatSensitive = isSensitive(chatRestrictions);
2310+
22832311
if(this.loadMutex) {
22842312
await this.loadMutex;
22852313

@@ -2660,10 +2688,11 @@ export default class AppSearchSuper {
26602688
} */
26612689
}
26622690

2663-
private copySearchContext(newInputFilter: MyInputMessagesFilter, nextRate: number) {
2664-
const context = copy(this.searchContext);
2691+
private copySearchContext(newInputFilter: MyInputMessagesFilter, nextRate: number, skipSensitive: boolean) {
2692+
const context = copy(this.searchContext) as MediaSearchContext;
26652693
context.inputFilter = {_: newInputFilter};
26662694
context.nextRate = nextRate;
2695+
context.skipSensitive = skipSensitive;
26672696
return context;
26682697
}
26692698

src/components/chat/bubbles.ts

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ import {PremiumGiftBubble} from './bubbles/premiumGift';
200200
import {UnknownUserBubble} from './bubbles/unknownUser';
201201
import {isMessageForVerificationBot, isVerificationBot} from './utils';
202202
import {ChecklistBubble} from './bubbles/checklist';
203+
import {getRestrictionReason, isSensitive} from '../../helpers/restrictions';
204+
import {isMessageSensitive} from '../../lib/appManagers/utils/messages/isMessageRestricted';
203205

204206
export const USER_REACTIONS_INLINE = false;
205207
export const TEST_BUBBLES_DELETION = false;
@@ -2427,7 +2429,8 @@ export default class ChatBubbles {
24272429
if(mediaSpoiler) {
24282430
onMediaSpoilerClick({
24292431
event: e,
2430-
mediaSpoiler
2432+
mediaSpoiler,
2433+
sensitiveSettings: this.chat.sensitiveContentSettings
24312434
});
24322435
return;
24332436
}
@@ -2846,6 +2849,7 @@ export default class ChatBubbles {
28462849
return media._ === 'photo' || ['video', 'gif'].includes(media.type);
28472850
};
28482851

2852+
const skipSensitive = !this.chat.isSensitive && !isMessageSensitive(message);
28492853
const targets: {element: HTMLElement, mid: number, peerId: PeerId, fullMid: string, index?: number}[] = [];
28502854
const fullMids = isSingleMedia ? [fullMessageId] : this.getRenderedHistory('asc').map((fullMid) => {
28512855
const bubble = this.getBubble(fullMid);
@@ -2856,6 +2860,10 @@ export default class ChatBubbles {
28562860
const message = this.chat.getMessage(fullMid);
28572861
const media = getMediaFromMessage(message);
28582862

2863+
if(skipSensitive && isMessageSensitive(message)) {
2864+
return;
2865+
}
2866+
28592867
return media && f(media) && fullMid;
28602868
}).filter(Boolean) as FullMid[];
28612869

@@ -2891,6 +2899,10 @@ export default class ChatBubbles {
28912899
const parents: Set<HTMLElement> = new Set();
28922900
if(documentDiv) {
28932901
elements.forEach((element) => {
2902+
if(skipSensitive && isMessageSensitive(message)) {
2903+
return;
2904+
}
2905+
28942906
targets.push({
28952907
element: element.querySelector('.document-ico'),
28962908
mid: +element.dataset.mid,
@@ -2946,6 +2958,7 @@ export default class ChatBubbles {
29462958
peerId: this.peerId,
29472959
inputFilter: {_: documentDiv ? 'inputMessagesFilterDocument' : 'inputMessagesFilterPhotoVideo'},
29482960
useSearch: this.chat.type !== ChatType.Scheduled && !isSingleMedia,
2961+
skipSensitive,
29492962
isScheduled: this.chat.type === ChatType.Scheduled
29502963
})
29512964
.openMedia({
@@ -5040,12 +5053,14 @@ export default class ChatBubbles {
50405053
media,
50415054
promise,
50425055
middleware,
5043-
attachmentDiv
5056+
attachmentDiv,
5057+
sensitive
50445058
}: {
50455059
media: Photo.photo | MyDocument,
50465060
promise: Promise<any>,
50475061
middleware: Middleware,
5048-
attachmentDiv: HTMLElement
5062+
attachmentDiv: HTMLElement,
5063+
sensitive?: boolean
50495064
}) {
50505065
await promise;
50515066
if(!middleware()) {
@@ -5058,6 +5073,7 @@ export default class ChatBubbles {
50585073
width: parseInt(width),
50595074
height: parseInt(height),
50605075
middleware,
5076+
sensitive,
50615077
animationGroup: this.chat.animationGroup
50625078
});
50635079

@@ -6101,6 +6117,7 @@ export default class ChatBubbles {
61016117
}
61026118

61036119
const isOutgoing = message.pFlags.is_outgoing/* && this.peerId !== rootScope.myId */;
6120+
const sensitive = this.chat.isSensitive || isMessageSensitive(message);
61046121

61056122
if(isOutgoing && !message.error) {
61066123
bubble.classList.add('is-outgoing');
@@ -6238,7 +6255,8 @@ export default class ChatBubbles {
62386255
lazyLoadQueue: this.lazyLoadQueue,
62396256
chat: this.chat,
62406257
loadPromises,
6241-
autoDownload: this.chat.autoDownload
6258+
autoDownload: this.chat.autoDownload,
6259+
sensitive
62426260
});
62436261

62446262
break;
@@ -6258,12 +6276,13 @@ export default class ChatBubbles {
62586276
autoDownloadSize: this.chat.autoDownload.photo
62596277
});
62606278

6261-
if((messageMedia as MessageMedia.messageMediaPhoto).pFlags?.spoiler) {
6279+
if((messageMedia as MessageMedia.messageMediaPhoto).pFlags?.spoiler || sensitive) {
62626280
loadPromises.push(this.wrapMediaSpoiler({
62636281
media: photo as Photo.photo,
62646282
promise: p,
62656283
middleware,
6266-
attachmentDiv
6284+
attachmentDiv,
6285+
sensitive
62676286
}));
62686287
}
62696288

@@ -6696,7 +6715,8 @@ export default class ChatBubbles {
66966715
lazyLoadQueue: this.lazyLoadQueue,
66976716
chat: this.chat,
66986717
loadPromises,
6699-
autoDownload: this.chat.autoDownload
6718+
autoDownload: this.chat.autoDownload,
6719+
spoilered: sensitive
67006720
});
67016721
} else {
67026722
const withTail = !IS_ANDROID && !IS_APPLE && !isRound && canHaveTail && !withReplies && USE_MEDIA_TAILS;
@@ -7051,7 +7071,7 @@ export default class ChatBubbles {
70517071
chat: this.chat,
70527072
loadPromises,
70537073
autoDownload: this.chat.autoDownload,
7054-
spoilered: !isAlreadyPaid,
7074+
spoilered: !isAlreadyPaid || sensitive,
70557075
videoTimes,
70567076
uploadingFileName: (message as Message.message).uploadingFileName
70577077
});
@@ -7856,6 +7876,7 @@ export default class ChatBubbles {
78567876
title: isWebPage ? peerTitle : undefined,
78577877
subtitle: isWebPage ? undefined : i18n('ExpiredStorySubtitle', [peerTitle]),
78587878
isStoryExpired: true,
7879+
isChatSensitive: this.chat.isSensitive,
78597880
noBorder
78607881
});
78617882

@@ -8390,7 +8411,17 @@ export default class ChatBubbles {
83908411
else if(type === 'noScheduledMessages') title = i18n('NoScheduledMessages');
83918412
else if(type === 'restricted') {
83928413
title = document.createElement('span');
8393-
title.innerText = await this.managers.appPeersManager.getRestrictionReasonText(this.peerId);
8414+
const reason = getRestrictionReason(await this.managers.appPeersManager.getPeerRestrictions(this.peerId))
8415+
8416+
if(reason) {
8417+
if(!reason.text && reason.reason === 'sensitive') {
8418+
title.replaceChildren(i18n('SensitiveChannel'));
8419+
} else {
8420+
title.innerText = reason.text;
8421+
}
8422+
} else {
8423+
title.replaceChildren(i18n(this.peerId.isUser() ? 'RestrictedUser' : 'RestrictedChat'));
8424+
}
83948425
}
83958426

83968427
if(title) {

0 commit comments

Comments
 (0)