Web Page: Support media repair (#6321)

This commit is contained in:
zubiden 2025-10-08 12:33:22 +02:00 committed by Alexander Zinchuk
parent cccde14f59
commit f0f9993ebd
9 changed files with 91 additions and 26 deletions

View File

@ -25,14 +25,14 @@ export function addMessageToLocalDb(message: GramJs.TypeMessage | GramJs.TypeSpo
}
}
export function addWebPageMediaToLocalDb(webPage: GramJs.TypeWebPage, context?: MediaRepairContext) {
export function addWebPageMediaToLocalDb(webPage: GramJs.TypeWebPage) {
if (webPage instanceof GramJs.WebPage) {
if (webPage.document) {
const document = addMessageRepairInfo(webPage.document, context);
const document = addWebPageRepairInfo(webPage.document, webPage);
addDocumentToLocalDb(document);
}
if (webPage.photo) {
const photo = addMessageRepairInfo(webPage.photo, context);
const photo = addWebPageRepairInfo(webPage.photo, webPage);
addPhotoToLocalDb(photo);
}
}
@ -146,6 +146,22 @@ export function addMessageRepairInfo<T extends GramJs.TypeDocument | GramJs.Type
return repairableMedia;
}
export function addWebPageRepairInfo<T extends GramJs.TypeDocument | GramJs.TypeWebDocument | GramJs.TypePhoto>(
media: T, webPage?: GramJs.TypeWebPage,
): T & RepairInfo {
if (!(webPage instanceof GramJs.WebPage)) return media;
if (!(media instanceof GramJs.Document || media instanceof GramJs.Photo || media instanceof GramJs.WebDocument)) {
return media;
}
const repairableMedia = media as T & RepairInfo;
repairableMedia.localRepairInfo = {
type: 'webPage',
url: webPage.url,
};
return repairableMedia;
}
export function addChatToLocalDb(chat: GramJs.Chat | GramJs.Channel) {
const id = buildApiPeerId(chat.id, chat instanceof GramJs.Chat ? 'chat' : 'channel');
const storedChat = localDb.chats[id];

View File

@ -18,8 +18,13 @@ export type MessageRepairInfo = {
id: number;
};
export type WebPageRepairInfo = {
type: 'webPage';
url: string;
};
export type RepairInfo = {
localRepairInfo?: StoryRepairInfo | MessageRepairInfo;
localRepairInfo?: StoryRepairInfo | MessageRepairInfo | WebPageRepairInfo;
};
export interface LocalDb {

View File

@ -21,6 +21,7 @@ import {
DEBUG, DEBUG_GRAMJS, IS_TEST, LANG_PACK, UPLOAD_WORKERS,
} from '../../../config';
import { pause } from '../../../util/schedulers';
import { buildWebPage } from '../apiBuilders/messageContent';
import {
buildApiMessage,
setMessageBuilderCurrentUserId,
@ -28,9 +29,15 @@ import {
import { buildApiPeerId } from '../apiBuilders/peers';
import { buildApiStory } from '../apiBuilders/stories';
import { buildApiUser, buildApiUserFullInfo } from '../apiBuilders/users';
import { buildInputChannelFromLocalDb, buildInputPeerFromLocalDb, getEntityTypeById } from '../gramjsBuilders';
import {
buildInputChannelFromLocalDb,
buildInputPeerFromLocalDb,
DEFAULT_PRIMITIVES,
getEntityTypeById,
} from '../gramjsBuilders';
import {
addStoryToLocalDb, addUserToLocalDb,
addWebPageMediaToLocalDb,
} from '../helpers/localDb';
import {
isResponseUpdate, log,
@ -522,6 +529,11 @@ export async function repairFileReference({
const result = await repairMessageMedia(localRepairInfo.peerId, localRepairInfo.id);
return result;
}
if (localRepairInfo.type === 'webPage') {
const result = await repairWebPageMedia(localRepairInfo.url);
return result;
}
}
return false;
@ -599,6 +611,27 @@ async function repairStoryMedia(peerId: string, storyId: number) {
return true;
}
export async function repairWebPageMedia(url: string) {
const result = await invokeRequest(new GramJs.messages.GetWebPage({
url,
hash: DEFAULT_PRIMITIVES.INT,
}), {
shouldIgnoreErrors: true,
});
if (!result?.webpage) return false;
const webPage = buildWebPage(result.webpage);
if (!webPage) return false;
addWebPageMediaToLocalDb(result.webpage);
sendApiUpdate({
'@type': 'updateWebPage',
webPage,
});
return webPage.webpageType === 'full';
}
export function setForceHttpTransport(forceHttpTransport: boolean) {
client.setForceHttpTransport(forceHttpTransport);
}

View File

@ -574,7 +574,8 @@
"MemberRequestsRequestToJoinDescriptionChannel" = "This channel accepts new subscribers only after they are approved by its admins.";
"MemberRequestsRequestToJoinDescriptionGroup" = "This group accepts new members only after they are approved by its admins.";
"ShareYouPhoneNumberTitle" = "Share your phone number?";
"AreYouSureShareMyContactInfoBot" = "The bot will know your phone number. This can be useful for integration with other services.";
"AreYouSureShareMyContactInfoBot" = "The bot will know your phone number. This can be useful for integration with other services.\n\n⚠ Warning! Never enter your Telegram login codes in mini apps.";
"ContactShare" = "Share Contact";
"OK" = "OK";
"ForwardTo" = "Forward to...";
"AttachGame" = "Game";
@ -752,7 +753,6 @@
"PollsStopSure" = "Stop";
"PaymentTestInvoice" = "TEST INVOICE";
"PaymentInvoiceNotFound" = "Invoice not found";
"AttachLiveLocation" = "Live Location";
"NoWordsRecognized" = "No words recognized.";
"ViaBot" = "via";
"DiscussChannel" = "channel";
@ -1117,6 +1117,7 @@
"AttachStory" = "Story";
"AttachInvoice" = "Invoice: {description}";
"AttachLocation" = "Location";
"AttachLiveLocation" = "Live Location";
"AttachGiveaway" = "Giveaway";
"AttachGiveawayResults" = "Giveaway Results";
"AttachTodo" = "Checklist";
@ -1478,9 +1479,9 @@
"GiftInfoDescriptionConverted_other" = "You converted this gift to **{amount}** Stars.";
"GiftInfoPeerDescriptionOutConverted_one" = "{peer} converted this gift to **{amount}** Star.";
"GiftInfoPeerDescriptionOutConverted_other" = "{peer} converted this gift to **{amount}** Stars.";
"GiftInfoDescriptionFreeUpgrade" = "Upgrade this gift for free to turn it to a unique collectible.";
"GiftInfoDescriptionFreeUpgrade" = "Upgrade this gift for free to turn it into a unique collectible.";
"GiftInfoDescriptionUpgrade2" = "Upgrade this gift to turn it to a unique collectible.";
"GiftInfoPeerDescriptionFreeUpgradeOut" = "{peer} can turn this gift to a unique collectible";
"GiftInfoPeerDescriptionFreeUpgradeOut" = "{peer} can turn this gift into a unique collectible";
"GiftInfoDescriptionUpgraded" = "This gift was turned into a unique collectible.";
"GiftInfoFrom" = "From";
"GiftInfoDate" = "Date";
@ -1877,8 +1878,8 @@
"ActionStarGiftChannelText" = "Add this gift to your channel's profile or convert it to {amount}.";
"ActionStarGiftDisplaying" = "You added this gift to your profile.";
"ActionStarGiftChannelDisplaying" = "This gift is displayed to visitors of your channel.";
"ActionStarGiftUpgradeText" = "{peer} can turn this gift to a unique collectible.";
"ActionStarGiftUpgradeTextYou" = "Tap “Unpack” to turn this gift to a unique collectible.";
"ActionStarGiftUpgradeText" = "{peer} can turn this gift into a unique collectible.";
"ActionStarGiftUpgradeTextYou" = "Tap “Unpack” to turn this gift into a unique collectible.";
"ActionStarGiftUpgraded" = "This gift was upgraded.";
"ActionStarGiftUnpack" = "Unpack";
"ActionStarGiftLimitedRibbon" = "1 of {total}";
@ -1973,7 +1974,7 @@
"GiftPremiumDescriptionYourBalance" = "Your balance is **{stars}**. {link}";
"StarsGiftCompleted" = "Gift sent!";
"GiftSent" = "Gift sent!";
"PrivacyDescriptionMessagesContactsAndPremium" = "You can restrict messages from users who are not in your contacts and don't have Premium.";
"PrivacyDescriptionMessagesContactsAndPremium" = "You can restrict messages from users who are not in your contacts and whom you haven't messaged first.";
"PrivacyChargeForMessages" = "Charge for Messages";
"PrivacyDescriptionChargeForMessages" = "Charge a fee for messages from people outside your contacts or those you haven't messaged first.";
"RemoveFeeTitle" = "Remove Fee";
@ -2201,7 +2202,7 @@
"DescriptionAboutTon" = "Offer TON to submit post suggestions to channels on Telegram.";
"ButtonTopUpViaFragment" = "Top Up Via Fragment";
"TonModalHint" = "You can top up your TON using Fragment.";
"TonGiftReceived" = "TON Top Up";
"TonGiftReceived" = "TON Top-Up";
"MediaSpoilerSensitive" = "18+";
"TitleSensitiveModal" = "{years}+ content";
"TextSensitiveModal" = "This media may contain sensitive content suitable only for adults. Do you still want to view it?";
@ -2215,8 +2216,8 @@
"TitleAgeCheckSuccess" = "Age Check Success";
"ButtonAgeVerification" = "Verify My Age";
"GiftRibbonPremium" = "premium";
"NotificationGiftsLimit2_one" = "You've already sent **one** of these gifts, and it's the limit.";
"NotificationGiftsLimit2_other" = "You've already sent {count} of these gifts, and it's the limit.";
"NotificationGiftsLimit2_one" = "You already sent **one** of these gifts, which is the limit.";
"NotificationGiftsLimit2_other" = "You already sent **{count}** of these gifts, which is the limit.";
"PremiumGiftHeader" = "Premium Gift";
"DescriptionGiftPremiumRequired2_one" = "Subscribe to **Telegram Premium** to send **one** of these gifts and unlock powerful features.";
"DescriptionGiftPremiumRequired2_other" = "Subscribe to **Telegram Premium** to send up to **{count}** of these gifts and unlock powerful features.";
@ -2257,7 +2258,7 @@
"PostsSearchTransaction" = "Posts Search";
"AllStoriesCategory" = "All stories";
"TitleRating" = "Rating";
"RatingReflectsActivity" = "This rating reflects {name}'s activity on Telegram. It is based on:";
"RatingReflectsActivity" = "This rating reflects **{name}'s** activity on Telegram. It is based on:";
"RatingYourReflectsActivity" = "This rating reflects your activity on Telegram. It is based on:";
"RatingGiftsFromTelegram" = "Gifts from Telegram";
"RatingGiftsFromTelegramDesc" = "100% of the Stars spent on gifts purchased from Telegram.";

View File

@ -12,7 +12,7 @@ import getReadableErrorText from '../../util/getReadableErrorText';
import renderText from '../common/helpers/renderText';
import useFlag from '../../hooks/useFlag';
import useOldLang from '../../hooks/useOldLang';
import useLang from '../../hooks/useLang';
import Button from '../ui/Button';
import Modal from '../ui/Modal';
@ -29,7 +29,7 @@ const Dialogs: FC<StateProps> = ({ dialogs, currentMessageList }) => {
} = getActions();
const [isModalOpen, openModal, closeModal] = useFlag();
const lang = useOldLang();
const lang = useLang();
useEffect(() => {
if (dialogs.length > 0) {
@ -62,7 +62,11 @@ const Dialogs: FC<StateProps> = ({ dialogs, currentMessageList }) => {
title={lang('ShareYouPhoneNumberTitle')}
onCloseAnimationEnd={dismissDialog}
>
{lang('AreYouSureShareMyContactInfoBot')}
{lang(
'AreYouSureShareMyContactInfoBot',
undefined,
{ withNodes: true, withMarkdown: true, renderTextFilters: ['br', 'emoji'],
})}
<div className="dialog-buttons mt-2">
<Button
className="confirm-dialog-button"

View File

@ -1138,10 +1138,14 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
<ConfirmDialog
isOpen={isRequestingPhone}
onClose={handleRejectPhone}
title={oldLang('ShareYouPhoneNumberTitle')}
text={oldLang('AreYouSureShareMyContactInfoBot')}
title={lang('ShareYouPhoneNumberTitle')}
textParts={lang(
'AreYouSureShareMyContactInfoBot',
undefined,
{ withNodes: true, withMarkdown: true, renderTextFilters: ['br', 'emoji'],
})}
confirmHandler={handleAcceptPhone}
confirmLabel={oldLang('ContactShare')}
confirmLabel={lang('ContactShare')}
/>
<ConfirmDialog
isOpen={isRequestingWriteAccess}

View File

@ -26,7 +26,7 @@ export const DEBUG = process.env.APP_ENV !== 'production';
export const DEBUG_MORE = false;
export const DEBUG_LOG_FILENAME = 'tt-log.json';
export const STRICTERDOM_ENABLED = DEBUG;
export const BOT_VERIFICATION_PEERS_LIMIT = 20;
export const FORCE_FALLBACK_LANG = false;
export const BETA_CHANGELOG_URL = 'https://telegra.ph/WebA-Beta-03-20';
@ -364,6 +364,7 @@ export const GIVEAWAY_MAX_ADDITIONAL_COUNTRIES = 10;
export const BOOST_PER_SENT_GIFT = 3;
export const FRAGMENT_PHONE_CODE = '888';
export const FRAGMENT_PHONE_LENGTH = 11;
export const BOT_VERIFICATION_PEERS_LIMIT = 20;
export const LIGHT_THEME_BG_COLOR = '#99BA92';
export const DARK_THEME_BG_COLOR = '#0F0F0F';

View File

@ -516,6 +516,7 @@ export interface LangPair {
'MemberRequestsRequestToJoinDescriptionGroup': undefined;
'ShareYouPhoneNumberTitle': undefined;
'AreYouSureShareMyContactInfoBot': undefined;
'ContactShare': undefined;
'OK': undefined;
'ForwardTo': undefined;
'AttachGame': undefined;
@ -664,7 +665,6 @@ export interface LangPair {
'PollsStopSure': undefined;
'PaymentTestInvoice': undefined;
'PaymentInvoiceNotFound': undefined;
'AttachLiveLocation': undefined;
'NoWordsRecognized': undefined;
'ViaBot': undefined;
'DiscussChannel': undefined;
@ -964,6 +964,7 @@ export interface LangPair {
'AttachContact': undefined;
'AttachStory': undefined;
'AttachLocation': undefined;
'AttachLiveLocation': undefined;
'AttachGiveaway': undefined;
'AttachGiveawayResults': undefined;
'AttachTodo': undefined;

View File

@ -22,7 +22,7 @@ import {
type RegularLangFnParameters,
} from './types';
import { DEBUG, LANG_PACK } from '../../config';
import { DEBUG, FORCE_FALLBACK_LANG, LANG_PACK } from '../../config';
import { callApi } from '../../api/gramjs';
import renderText from '../../components/common/helpers/renderText';
import { IS_INTL_LIST_FORMAT_SUPPORTED } from '../browser/globalEnvironment';
@ -344,7 +344,7 @@ export function getTranslationFn(): LangFn {
}
function getString(langKey: LangKey, count: number) {
let langPackStringValue = langPack?.strings[langKey];
let langPackStringValue = !FORCE_FALLBACK_LANG ? langPack?.strings[langKey] : undefined;
if (!langPackStringValue && !fallbackLangPack) {
loadFallbackPack();