Compare commits
539 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 95f18f2120 | |||
| ae3dfacdf9 | |||
| aa0d733cde | |||
| a5b446f6df | |||
| 2afc171bec | |||
| d6bd88d119 | |||
| 639a82ce28 | |||
| ef1b197771 | |||
| ad05998575 | |||
| b403f600e7 | |||
| 9b2f2b104f | |||
| e4d920b148 | |||
| c5d1739e95 | |||
| a41bbd27c8 | |||
| 2d67557a91 | |||
| ca1a548fb8 | |||
| 97bd865916 | |||
| f7ab8298cf | |||
| 33cf9a0702 | |||
| 282c076931 | |||
| 135ffb13fd | |||
| 9d4e1689fa | |||
| 27e2a4b5d2 | |||
| c9cad4186b | |||
| 3522d9c62e | |||
| 43aa8825a5 | |||
| 4b28e910e8 | |||
| 4150cdff86 | |||
| 474fa56cc0 | |||
| 6ca777102c | |||
| 49d5cf939c | |||
| b56b9b1fb9 | |||
| 0293700e0f | |||
| 524a7a6a23 | |||
| b1459e41d3 | |||
| ef685aa0da | |||
| 3ac222db62 | |||
| 642b0ed032 | |||
| a7090c5fba | |||
| ebcd4eb97b | |||
| a76534b19f | |||
| ee33d139cd | |||
| c9cabfb084 | |||
| 3dd415d0c2 | |||
| 4592e4e4bb | |||
| 1cb762913c | |||
| 6eb7d68d49 | |||
| 36662c51dd | |||
| 4e915e9d1a | |||
| 86d6280776 | |||
| eea7caeb94 | |||
| b77e74de7f | |||
| 8a804fcfad | |||
| f7ad91e80c | |||
| 61a9d9c01d | |||
| e98f56b0b7 | |||
| b2eeab53c5 | |||
| d7539349c7 | |||
| 5350c97f82 | |||
| 20ba417ddd | |||
| 5b6f26af21 | |||
| ac1da83401 | |||
| 7b32e9af5e | |||
| 332ae22111 | |||
| b8c76cac61 | |||
| 150432e4d1 | |||
| d6c3760646 | |||
| 537c656ee1 | |||
| 4e0490494e | |||
| 56ad825693 | |||
| aab4ac8526 | |||
| 5c98406e1a | |||
| 3b40bc6297 | |||
| 12e164c4df | |||
| 855cc8e900 | |||
| 0a38cf2501 | |||
| 6def067e98 | |||
| a4e5ea01dc | |||
| f4cfbc5ed8 | |||
| 336705a503 | |||
| 764b0d3dcd | |||
| 72c8999e50 | |||
| 79b5f7eda9 | |||
| 6fcf80c6cf | |||
| e9a8acdc54 | |||
| 01573af0de | |||
| 69b24c494e | |||
| 2b4047b20d | |||
| 2b1a46356a | |||
| 36a91dd32b | |||
| d8e38b43d9 | |||
| d2d69a7a36 | |||
| 85fdc04d48 | |||
| 5e28b2d601 | |||
| 33f6fc7d8c | |||
| 3c8188e0b4 | |||
| 3ecf3f7c55 | |||
| fc6d4d66b7 | |||
| 2d097ca9ae | |||
| af03660cab | |||
| 986d347ea4 | |||
| 2dcd8a9640 | |||
| 5a55e850d9 | |||
| aa6edea33a | |||
| e67d2e5db2 | |||
| 67bbb477c7 | |||
| 5b0c48bb52 | |||
| e00016312e | |||
| 9df551a145 | |||
| 1852161fbf | |||
| 1851b6ff30 | |||
| 98f3fa76a2 | |||
| 6db4b8821e | |||
| 0f45abd534 | |||
| 4ad0804d55 | |||
| 9e10a80e00 | |||
| 01d9864036 | |||
| 8927a1b9a2 | |||
| b41c94be29 | |||
| 8ebf329cd9 | |||
| c3251aaf7b | |||
| d031046edb | |||
| 7808cc6d41 | |||
| a7b60c43b5 | |||
| a8b959826c | |||
| 42f96f3c43 | |||
| cc97093c5a | |||
| 7d5d086ade | |||
| 3da44eb5dd | |||
| 4955cdcdce | |||
| b806e714a6 | |||
| 597195a2e2 | |||
| 5966c74a27 | |||
| caa1ae4436 | |||
| 15ee46dab4 | |||
| acea390f3a | |||
| af5ad84e72 | |||
| 728ed02a1c | |||
| 8e369a4aa5 | |||
| 1f66e8ebeb | |||
| d0b0b02b62 | |||
| 35e457c924 | |||
| 097c3c4a5a | |||
| 10022a3c6d | |||
| 0dbb195106 | |||
| 6493cb9ed8 | |||
| 1cfda38345 | |||
| bf20dbe3bc | |||
| 46d3f232af | |||
| ade97fd2d2 | |||
| 39614aab3f | |||
| 6bab2b4df6 | |||
| b4c7272351 | |||
| d831775e2f | |||
| bde39970a0 | |||
| 076291b98f | |||
| 1341907cfd | |||
| b793c06759 | |||
| 475b2ac739 | |||
| d1c310de00 | |||
| 8615a25cd1 | |||
| de4eb1e59b | |||
| 8e8f6f905f | |||
| a57eecd420 | |||
| f306b11676 | |||
| fe15857704 | |||
| 98918e1bed | |||
| 0ed22b67ab | |||
| 53e4b685b4 | |||
| 2ca24aa290 | |||
| 8e7b12a23a | |||
| 745ad45d47 | |||
| 5fee0a7a73 | |||
| 096ddcad6d | |||
| 3b7448ccab | |||
| 478c6c4d36 | |||
| e2ea27cbef | |||
| 625ae87eea | |||
| 597816db09 | |||
| ec3fc8c749 | |||
| e64a096dca | |||
| eaf30d58be | |||
| 94ac9f93fa | |||
| 04f040c9c5 | |||
| af0e87c569 | |||
| 1a503e5f1d | |||
| c46b659aa5 | |||
| 7a754f8b00 | |||
| 29fb263495 | |||
| c8660b5385 | |||
| d47b99b0b5 | |||
| 88e3c87cd9 | |||
| fe0e526b79 | |||
| c480ab1a3b | |||
| 49bc8ccd6a | |||
| b180070ba3 | |||
| b40f30ca98 | |||
| c2a1817400 | |||
| cb6698cf4a | |||
| bcdb1bdfd2 | |||
| effc9873c9 | |||
| 9561026cd4 | |||
| 5d335341ab | |||
| cc8408d11c | |||
| a197ed9e95 | |||
| 3b91e2dee4 | |||
| c035ec6917 | |||
| 041ec1157f | |||
| 17578be4b9 | |||
| 1409d38ac3 | |||
| b463c76eca | |||
| d62fb5786d | |||
| aad157cf56 | |||
| 2d3e2b1ef8 | |||
| 91ab82c9da | |||
| 9c23de7f1a | |||
| 60fb5fdaf0 | |||
| 4709e11e46 | |||
| 8c28ce4c99 | |||
| 20c63b98c7 | |||
| 8b42161898 | |||
| b1823d981b | |||
| b2e8e0431e | |||
| 486d5b63d3 | |||
| 84a1fec7b1 | |||
| 3a84c6afdd | |||
| 16d18b437d | |||
| 12fab565a4 | |||
| f8d5a8a203 | |||
| b9af4f3cb0 | |||
| 4b6107fa56 | |||
| f90a010b84 | |||
| ef0539c9fc | |||
| 00db325e91 | |||
| d5429e769f | |||
| 714dae054a | |||
| 981babf302 | |||
| 0926bb1288 | |||
| e13768ea50 | |||
| 6c19274eac | |||
| 394883b986 | |||
| 4240568ea5 | |||
| a77131dfd6 | |||
| caca679336 | |||
| b08869abdb | |||
| d5147c9d28 | |||
| 859e41f95a | |||
| 0e45f3ebd9 | |||
| 7f9461820b | |||
| e59a60b3b5 | |||
| 926aae6847 | |||
| 744c1b925e | |||
| 3fc9ed0ccb | |||
| 0b7d544615 | |||
| d19baeace2 | |||
| cd0f58fa65 | |||
| 1f25301283 | |||
| 0788f3d7b0 | |||
| f93b7a60f8 | |||
| d0875a1178 | |||
| 29f8493a82 | |||
| d4db838d43 | |||
| 0be2e8b672 | |||
| 0aa1031402 | |||
| 53c73accd0 | |||
| be38800a70 | |||
| f2fa1cd70d | |||
| 5dfce5f7b2 | |||
| 2b10e1e595 | |||
| eb1ef6d2a7 | |||
| b2ce1d2d15 | |||
| b285b4d309 | |||
| eff273dd7d | |||
| fde63ccb21 | |||
| b209683c8e | |||
| b6be799938 | |||
| ec8c634e9c | |||
| b7a9aa9a0e | |||
| 2ca489b2fb | |||
| daf76c1bc2 | |||
| d3aa0664a7 | |||
| f61c22b065 | |||
| 8041941565 | |||
| 0aa1cd0b52 | |||
| 1bbac5784b | |||
| f925a9e961 | |||
| 8b6d475882 | |||
| d82c422ea1 | |||
| d7e57e42d8 | |||
| 7ee2ec13f0 | |||
| a6e13a9f9e | |||
| 66f73a5a64 | |||
| 575684670c | |||
| 9661bac876 | |||
| 4b618a3578 | |||
| 0e79bd3d12 | |||
| dd692f2d26 | |||
| cba8387589 | |||
| 01c2ade501 | |||
| b9fa14139a | |||
| a8cb5419d6 | |||
| f775670938 | |||
| c035a25aaa | |||
| 6cae088d1f | |||
| bee0534052 | |||
| 3e11d44cac | |||
| 4d269f6e97 | |||
| e9496fb612 | |||
| c9c82446cb | |||
| 0dec803177 | |||
| 2dc45ac907 | |||
| a3d8db4ac0 | |||
| aee6b6e224 | |||
| 736efd4692 | |||
| ec5e846374 | |||
| caf32cccd3 | |||
| 594b2bc8f2 | |||
| d1ba270a8c | |||
| 2c1abd32bf | |||
| 79662dffa4 | |||
| a79e025151 | |||
| 3fa168cee0 | |||
| 9c1ef76e49 | |||
| 8497b83f7c | |||
| 393c23ad12 | |||
| 01821cd779 | |||
| 3da733520d | |||
| a605275157 | |||
| 8564e4d727 | |||
| fc3acff5d6 | |||
| 515850ec9b | |||
| 837b256778 | |||
| d16cab30d4 | |||
| fcdd7ecd61 | |||
| da9720530a | |||
| 4a10d86a29 | |||
| 3b5a007db5 | |||
| 2479b56c3b | |||
| 0909e8bd08 | |||
| 6109ec70b8 | |||
| c20bd17029 | |||
| 10e3115c39 | |||
| 3425b40746 | |||
| 42fc4fbb31 | |||
| f081917cd0 | |||
| bdfb0ffe04 | |||
| 2b282c8d7d | |||
| 77d23ad182 | |||
| 79442fde97 | |||
| f8e80bc266 | |||
| cb4c629178 | |||
| af0e11a1aa | |||
| 8ac6aca315 | |||
| 2638e54181 | |||
| db97db4aba | |||
| ded3f135bb | |||
| be82df72e6 | |||
| 3fa6335b24 | |||
| 23868bf9cc | |||
| 5b67f4ac9b | |||
| 17fdef7d9e | |||
| cf82e12bf4 | |||
| 6f27aeef10 | |||
| df53ddf837 | |||
| a3fd4f3fac | |||
| 24c0624704 | |||
| 33724be6ea | |||
| 4624d34f68 | |||
| aeee016dc9 | |||
| 8ded88baf5 | |||
| bdd35a6e2b | |||
| d9a08bb6a6 | |||
| cee833f102 | |||
| c19a527872 | |||
| 6995fcafb5 | |||
| b261d23645 | |||
| 21c1ba7607 | |||
| 5a2b8d06e3 | |||
| 9046daa1a6 | |||
| 65ccb4059e | |||
| d2578e9e47 | |||
| be17e2b919 | |||
| 26c2e7f245 | |||
| 9051716172 | |||
| 71b6a58683 | |||
| 32cd454554 | |||
| 6ffe555f6a | |||
| 7ac9ab3a51 | |||
| a9b0464726 | |||
| e4e85e5a39 | |||
| c5f294a1ac | |||
| 5dc078a3f8 | |||
| 83753343cb | |||
| 42215343cf | |||
| bedefee1d1 | |||
| 788eb014d4 | |||
| 13b7a07d2e | |||
| f026271436 | |||
| d13fe39629 | |||
| 62b3b60c45 | |||
| 74313d23f3 | |||
| 646390141a | |||
| 83cf12b475 | |||
| a0226f9789 | |||
| 54fecd497e | |||
| 2106747496 | |||
| ecce9dbaaa | |||
| b606a7b21d | |||
| 35ff45971f | |||
| 7a436f32dd | |||
| 54d5358b75 | |||
| 20c2250abb | |||
| 2ddc1ee2e1 | |||
| b55d2008c0 | |||
| 11b932707c | |||
| d50aca0d33 | |||
| 671e81033c | |||
| 361d269bf3 | |||
| ae81373cff | |||
| 160794b26c | |||
| 1dc57afbe1 | |||
| d9f397ea3f | |||
| c9a976bf87 | |||
| 7b921dea3b | |||
| fcc6aaed91 | |||
| eb0ab9609f | |||
| bb359f6493 | |||
| b24be50afe | |||
| 3e55380eed | |||
| 25c97a3ee8 | |||
| 2055cc70d1 | |||
| 788a81df6c | |||
| 1209bd35c5 | |||
| f473a1a804 | |||
| c8e95f7297 | |||
| b1ed8cd1b1 | |||
| 64bb818fe9 | |||
| ee172d951d | |||
| 41bc47eb6f | |||
| 423d2293f9 | |||
| e6559276c0 | |||
| 13959ca36c | |||
| 520989a7e6 | |||
| 4c02d19a51 | |||
| 734e1166ad | |||
| 94fd3e32dd | |||
| 367adaa44d | |||
| 73b4621121 | |||
| 8256a4c686 | |||
| b6b6673214 | |||
| 8ba2e95e6c | |||
| 40ab042fb5 | |||
| 25f401c22e | |||
| d8566f770f | |||
| f76f69b5cd | |||
| 487dd27ca1 | |||
| 32df03f08d | |||
| 658db59aaf | |||
| 695542cfd2 | |||
| 07cd35b1a8 | |||
| 74aae29b64 | |||
| 70713d5f62 | |||
| dd1b006d8a | |||
| ec8d604db7 | |||
| 9e8d60065b | |||
| d603f4de51 | |||
| 77695091b3 | |||
| 20e81177a6 | |||
| ce3ad95950 | |||
| c5684e768a | |||
| c8d5a60c74 | |||
| 4dad0a215a | |||
| 15698fd6f0 | |||
| cd4654dfd2 | |||
| 3a3d4480cc | |||
| 5c3748db56 | |||
| 7dfdcc7be0 | |||
| d1f2950167 | |||
| 59f61586a9 | |||
| 629dd6f9de | |||
| f4fc8ec2c4 | |||
| e8aa55d4d8 | |||
| 26b17325aa | |||
| c71f35778d | |||
| c9eb9a3ee0 | |||
| 06948ad15e | |||
| 029e0c9488 | |||
| c0219cb95d | |||
| 78e553b724 | |||
| b5b70beea0 | |||
| 177a7eaf43 | |||
| ca863bfb5b | |||
| c45025c6e5 | |||
| 10968d0da2 | |||
| b0a65885c9 | |||
| ad8f8513c3 | |||
| f457a9d109 | |||
| 830fb3ccc2 | |||
| 9116328f29 | |||
| aa7575dec4 | |||
| bfe272e39f | |||
| a7ca15657b | |||
| 41dada2c06 | |||
| 501784cd15 | |||
| ac699ccf80 | |||
| aadaf47569 | |||
| 6bc0179919 | |||
| 93fbad50bc | |||
| a5ec616382 | |||
| bf3f474195 | |||
| 14f68c2f33 | |||
| 92fadd2652 | |||
| b68a7c7f04 | |||
| 50097e1a81 | |||
| 464a36b515 | |||
| b46214a51e | |||
| 2414e927bd | |||
| da768ac1d1 | |||
| 396c229a4d | |||
| 235e0ae713 | |||
| 2b3f17e982 | |||
| 5ef48cac9c | |||
| 6ba922d7b0 | |||
| f881192dd0 | |||
| ef2a0bb05e | |||
| 54efa2353e | |||
| 2878533078 | |||
| ac520b314d | |||
| 871fef2c4a | |||
| 99f4b93745 | |||
| a757e07c3a | |||
| 5c4f006550 | |||
| 9ad38b9638 | |||
| fe8ebc1659 | |||
| a732d8f5e7 | |||
| 7ddcc47fcd | |||
| 70f22293cf | |||
| 0c50d6d7e7 | |||
| 90fb59348c |
@@ -30,7 +30,7 @@ jobs:
|
||||
curl -sSL https://install.python-poetry.org | python3 -
|
||||
|
||||
- name: Free up some disk space.
|
||||
uses: jlumbroso/free-disk-space@76866dbe54312617f00798d1762df7f43def6e5c
|
||||
uses: jlumbroso/free-disk-space@f68fdb76e2ea636224182cfb7377ff9a1708f9b8
|
||||
|
||||
- name: Docker image build.
|
||||
run: |
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
name: MacOS Packaged.
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/mac_packaged.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/configure.bat'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**.md'
|
||||
- 'changelog.txt'
|
||||
- 'LEGAL'
|
||||
- 'LICENSE'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/mac_packaged.yml'
|
||||
- 'lib/xdg/**'
|
||||
- 'snap/**'
|
||||
- 'Telegram/build/**'
|
||||
- 'Telegram/Resources/uwp/**'
|
||||
- 'Telegram/Resources/winrc/**'
|
||||
- 'Telegram/SourceFiles/platform/win/**'
|
||||
- 'Telegram/SourceFiles/platform/linux/**'
|
||||
- 'Telegram/configure.bat'
|
||||
|
||||
jobs:
|
||||
|
||||
macos:
|
||||
name: MacOS
|
||||
runs-on: macos-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
defines:
|
||||
- ""
|
||||
|
||||
env:
|
||||
GIT: "https://github.com"
|
||||
OPENALDIR: "/usr/local/opt/openal-soft"
|
||||
UPLOAD_ARTIFACT: "false"
|
||||
ONLY_CACHE: "false"
|
||||
MANUAL_CACHING: "1"
|
||||
AUTO_CACHING: "1"
|
||||
|
||||
steps:
|
||||
- name: Get repository name.
|
||||
run: echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v3.1.0
|
||||
with:
|
||||
submodules: recursive
|
||||
path: ${{ env.REPO_NAME }}
|
||||
|
||||
- name: First set up.
|
||||
run: |
|
||||
brew install autoconf automake boost cmake ffmpeg openal-soft openssl opus ninja pkg-config python qt yasm xz
|
||||
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
|
||||
|
||||
xcodebuild -version > CACHE_KEY.txt
|
||||
echo $MANUAL_CACHING >> CACHE_KEY.txt
|
||||
echo "$GITHUB_WORKSPACE" >> CACHE_KEY.txt
|
||||
if [ "$AUTO_CACHING" = "1" ]; then
|
||||
thisFile=$REPO_NAME/.github/workflows/mac_packaged.yml
|
||||
echo `md5 -q $thisFile` >> CACHE_KEY.txt
|
||||
fi
|
||||
echo "CACHE_KEY=`md5 -q CACHE_KEY.txt`" >> $GITHUB_ENV
|
||||
|
||||
echo "LibrariesPath=`pwd`" >> $GITHUB_ENV
|
||||
|
||||
curl -o tg_owt-version.json https://api.github.com/repos/desktop-app/tg_owt/git/refs/heads/master
|
||||
|
||||
- name: RNNoise.
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone --depth=1 https://gitlab.xiph.org/xiph/rnnoise.git
|
||||
cd rnnoise
|
||||
./autogen.sh
|
||||
./configure --disable-examples --disable-doc
|
||||
make -j$(sysctl -n hw.logicalcpu)
|
||||
make install
|
||||
|
||||
- name: WebRTC cache.
|
||||
id: cache-webrtc
|
||||
uses: actions/cache@v3.0.11
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/tg_owt
|
||||
key: ${{ runner.OS }}-webrtc-${{ env.CACHE_KEY }}-${{ hashFiles('**/tg_owt-version.json') }}
|
||||
- name: WebRTC.
|
||||
if: steps.cache-webrtc.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd $LibrariesPath
|
||||
|
||||
git clone --recursive --depth=1 $GIT/desktop-app/tg_owt.git
|
||||
cd tg_owt
|
||||
|
||||
cmake -B build . -GNinja -DCMAKE_BUILD_TYPE=Debug
|
||||
cmake --build build --parallel
|
||||
|
||||
- name: Telegram Desktop build.
|
||||
if: env.ONLY_CACHE == 'false'
|
||||
env:
|
||||
tg_owt_DIR: ${{ env.LibrariesPath }}/tg_owt/build
|
||||
run: |
|
||||
cd $REPO_NAME
|
||||
|
||||
DEFINE=""
|
||||
if [ -n "${{ matrix.defines }}" ]; then
|
||||
DEFINE="-D ${{ matrix.defines }}=ON"
|
||||
echo Define from matrix: $DEFINE
|
||||
echo "ARTIFACT_NAME=Telegram_${{ matrix.defines }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "ARTIFACT_NAME=Telegram" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
cmake -Bbuild -GNinja . \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_FIND_FRAMEWORK=LAST \
|
||||
-DTDESKTOP_API_TEST=ON \
|
||||
-DDESKTOP_APP_USE_PACKAGED_LAZY=ON \
|
||||
$DEFINE
|
||||
|
||||
cmake --build build --parallel
|
||||
|
||||
cd build
|
||||
macdeployqt Telegram.app
|
||||
codesign --remove-signature Telegram.app
|
||||
|
||||
mkdir dmgsrc
|
||||
mv Telegram.app dmgsrc
|
||||
hdiutil create -volname Telegram -srcfolder dmgsrc -ov -format UDZO Telegram.dmg
|
||||
|
||||
- name: Move artifact.
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
run: |
|
||||
cd $REPO_NAME/build
|
||||
mkdir artifact
|
||||
mv Telegram.dmg artifact/
|
||||
- uses: actions/upload-artifact@master
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
name: Upload artifact.
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME }}
|
||||
path: ${{ env.REPO_NAME }}/build/artifact/
|
||||
@@ -11,7 +11,9 @@ jobs:
|
||||
SKIP: "0"
|
||||
to_branch: "master"
|
||||
steps:
|
||||
- uses: actions/checkout@v3.1.0
|
||||
- uses: actions/checkout@v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
if: env.SKIP == '0'
|
||||
- name: Push the code to the master branch.
|
||||
if: env.SKIP == '0'
|
||||
|
||||
@@ -100,3 +100,6 @@
|
||||
[submodule "Telegram/ThirdParty/wayland"]
|
||||
path = Telegram/ThirdParty/wayland
|
||||
url = https://github.com/gitlab-freedesktop-mirrors/wayland.git
|
||||
[submodule "Telegram/ThirdParty/libprisma"]
|
||||
path = Telegram/ThirdParty/libprisma
|
||||
url = https://github.com/desktop-app/libprisma.git
|
||||
|
||||
@@ -59,9 +59,9 @@ include(cmake/options.cmake)
|
||||
|
||||
if (NOT DESKTOP_APP_USE_PACKAGED)
|
||||
if (WIN32)
|
||||
set(qt_version 5.15.10)
|
||||
set(qt_version 5.15.11)
|
||||
elseif (APPLE)
|
||||
set(qt_version 6.2.5)
|
||||
set(qt_version 6.2.6)
|
||||
endif()
|
||||
endif()
|
||||
include(cmake/external/qt/package.cmake)
|
||||
|
||||
@@ -28,6 +28,7 @@ include(cmake/lib_ffmpeg.cmake)
|
||||
include(cmake/lib_stripe.cmake)
|
||||
include(cmake/lib_tgvoip.cmake)
|
||||
include(cmake/lib_tgcalls.cmake)
|
||||
include(cmake/lib_prisma.cmake)
|
||||
include(cmake/td_export.cmake)
|
||||
include(cmake/td_mtproto.cmake)
|
||||
include(cmake/td_lang.cmake)
|
||||
@@ -218,6 +219,8 @@ PRIVATE
|
||||
api/api_sensitive_content.h
|
||||
api/api_single_message_search.cpp
|
||||
api/api_single_message_search.h
|
||||
api/api_statistics.cpp
|
||||
api/api_statistics.h
|
||||
api/api_text_entities.cpp
|
||||
api/api_text_entities.h
|
||||
api/api_toggling_media.cpp
|
||||
@@ -262,6 +265,8 @@ PRIVATE
|
||||
boxes/peers/edit_participant_box.h
|
||||
boxes/peers/edit_participants_box.cpp
|
||||
boxes/peers/edit_participants_box.h
|
||||
boxes/peers/edit_peer_color_box.cpp
|
||||
boxes/peers/edit_peer_color_box.h
|
||||
boxes/peers/edit_peer_common.h
|
||||
boxes/peers/edit_peer_info_box.cpp
|
||||
boxes/peers/edit_peer_info_box.h
|
||||
@@ -283,6 +288,8 @@ PRIVATE
|
||||
boxes/peers/peer_short_info_box.h
|
||||
boxes/peers/prepare_short_info_box.cpp
|
||||
boxes/peers/prepare_short_info_box.h
|
||||
boxes/peers/replace_boost_box.cpp
|
||||
boxes/peers/replace_boost_box.h
|
||||
boxes/about_box.cpp
|
||||
boxes/about_box.h
|
||||
boxes/about_sponsored_box.cpp
|
||||
@@ -517,6 +524,7 @@ PRIVATE
|
||||
data/data_audio_msg_id.h
|
||||
data/data_auto_download.cpp
|
||||
data/data_auto_download.h
|
||||
data/data_boosts.h
|
||||
data/data_bot_app.cpp
|
||||
data/data_bot_app.h
|
||||
data/data_chat.cpp
|
||||
@@ -619,6 +627,7 @@ PRIVATE
|
||||
data/data_sparse_ids.h
|
||||
data/data_sponsored_messages.cpp
|
||||
data/data_sponsored_messages.h
|
||||
data/data_statistics.h
|
||||
data/data_stories.cpp
|
||||
data/data_stories.h
|
||||
data/data_stories_ids.cpp
|
||||
@@ -713,6 +722,8 @@ PRIVATE
|
||||
history/view/controls/history_view_compose_controls.h
|
||||
history/view/controls/history_view_compose_search.cpp
|
||||
history/view/controls/history_view_compose_search.h
|
||||
history/view/controls/history_view_draft_options.cpp
|
||||
history/view/controls/history_view_draft_options.h
|
||||
history/view/controls/history_view_forward_panel.cpp
|
||||
history/view/controls/history_view_forward_panel.h
|
||||
history/view/controls/history_view_ttl_button.cpp
|
||||
@@ -721,6 +732,8 @@ PRIVATE
|
||||
history/view/controls/history_view_voice_record_bar.h
|
||||
history/view/controls/history_view_voice_record_button.cpp
|
||||
history/view/controls/history_view_voice_record_button.h
|
||||
history/view/controls/history_view_webpage_processor.cpp
|
||||
history/view/controls/history_view_webpage_processor.h
|
||||
history/view/media/history_view_call.cpp
|
||||
history/view/media/history_view_call.h
|
||||
history/view/media/history_view_contact.cpp
|
||||
@@ -739,6 +752,8 @@ PRIVATE
|
||||
history/view/media/history_view_game.h
|
||||
history/view/media/history_view_gif.cpp
|
||||
history/view/media/history_view_gif.h
|
||||
history/view/media/history_view_giveaway.cpp
|
||||
history/view/media/history_view_giveaway.h
|
||||
history/view/media/history_view_invoice.cpp
|
||||
history/view/media/history_view_invoice.h
|
||||
history/view/media/history_view_large_emoji.cpp
|
||||
@@ -824,6 +839,8 @@ PRIVATE
|
||||
history/view/history_view_quick_action.h
|
||||
history/view/history_view_replies_section.cpp
|
||||
history/view/history_view_replies_section.h
|
||||
history/view/history_view_reply.cpp
|
||||
history/view/history_view_reply.h
|
||||
history/view/history_view_requests_bar.cpp
|
||||
history/view/history_view_requests_bar.h
|
||||
history/view/history_view_schedule_box.cpp
|
||||
@@ -878,20 +895,14 @@ PRIVATE
|
||||
history/history_view_highlight_manager.h
|
||||
history/history_widget.cpp
|
||||
history/history_widget.h
|
||||
info/info_content_widget.cpp
|
||||
info/info_content_widget.h
|
||||
info/info_controller.cpp
|
||||
info/info_controller.h
|
||||
info/info_layer_widget.cpp
|
||||
info/info_layer_widget.h
|
||||
info/info_memento.cpp
|
||||
info/info_memento.h
|
||||
info/info_section_widget.cpp
|
||||
info/info_section_widget.h
|
||||
info/info_top_bar.cpp
|
||||
info/info_top_bar.h
|
||||
info/info_wrap_widget.cpp
|
||||
info/info_wrap_widget.h
|
||||
info/boosts/giveaway/giveaway_list_controllers.cpp
|
||||
info/boosts/giveaway/giveaway_list_controllers.h
|
||||
info/boosts/create_giveaway_box.cpp
|
||||
info/boosts/create_giveaway_box.h
|
||||
info/boosts/info_boosts_inner_widget.cpp
|
||||
info/boosts/info_boosts_inner_widget.h
|
||||
info/boosts/info_boosts_widget.cpp
|
||||
info/boosts/info_boosts_widget.h
|
||||
info/common_groups/info_common_groups_inner_widget.cpp
|
||||
info/common_groups/info_common_groups_inner_widget.h
|
||||
info/common_groups/info_common_groups_widget.cpp
|
||||
@@ -947,6 +958,15 @@ PRIVATE
|
||||
info/profile/info_profile_widget.h
|
||||
info/settings/info_settings_widget.cpp
|
||||
info/settings/info_settings_widget.h
|
||||
info/statistics/info_statistics_common.h
|
||||
info/statistics/info_statistics_inner_widget.cpp
|
||||
info/statistics/info_statistics_inner_widget.h
|
||||
info/statistics/info_statistics_list_controllers.cpp
|
||||
info/statistics/info_statistics_list_controllers.h
|
||||
info/statistics/info_statistics_recent_message.cpp
|
||||
info/statistics/info_statistics_recent_message.h
|
||||
info/statistics/info_statistics_widget.cpp
|
||||
info/statistics/info_statistics_widget.h
|
||||
info/stories/info_stories_inner_widget.cpp
|
||||
info/stories/info_stories_inner_widget.h
|
||||
info/stories/info_stories_provider.cpp
|
||||
@@ -965,6 +985,20 @@ PRIVATE
|
||||
info/userpic/info_userpic_emoji_builder_preview.h
|
||||
info/userpic/info_userpic_emoji_builder_widget.cpp
|
||||
info/userpic/info_userpic_emoji_builder_widget.h
|
||||
info/info_content_widget.cpp
|
||||
info/info_content_widget.h
|
||||
info/info_controller.cpp
|
||||
info/info_controller.h
|
||||
info/info_layer_widget.cpp
|
||||
info/info_layer_widget.h
|
||||
info/info_memento.cpp
|
||||
info/info_memento.h
|
||||
info/info_section_widget.cpp
|
||||
info/info_section_widget.h
|
||||
info/info_top_bar.cpp
|
||||
info/info_top_bar.h
|
||||
info/info_wrap_widget.cpp
|
||||
info/info_wrap_widget.h
|
||||
inline_bots/bot_attach_web_view.cpp
|
||||
inline_bots/bot_attach_web_view.h
|
||||
inline_bots/inline_bot_layout_internal.cpp
|
||||
@@ -1583,7 +1617,39 @@ elseif (APPLE)
|
||||
endif()
|
||||
|
||||
set(icons_path ${CMAKE_CURRENT_SOURCE_DIR}/Telegram/Images.xcassets)
|
||||
target_add_resource(Telegram ${icons_path})
|
||||
if (CMAKE_GENERATOR STREQUAL Xcode)
|
||||
target_add_resource(Telegram ${icons_path})
|
||||
else()
|
||||
set(icon_path ${icons_path}/Icon.iconset)
|
||||
find_program(ICONUTIL iconutil)
|
||||
find_program(PNG2ICNS png2icns)
|
||||
if (ICONUTIL)
|
||||
add_custom_command(
|
||||
OUTPUT Icon.icns
|
||||
COMMAND ${ICONUTIL}
|
||||
ARGS
|
||||
--convert icns
|
||||
--output Icon.icns
|
||||
${icon_path}
|
||||
)
|
||||
elseif (PNG2ICNS)
|
||||
add_custom_command(
|
||||
OUTPUT Icon.icns
|
||||
COMMAND ${PNG2ICNS}
|
||||
ARGS
|
||||
Icon.icns
|
||||
${icon_path}/icon_16x16.png
|
||||
${icon_path}/icon_32x32.png
|
||||
${icon_path}/icon_128x128.png
|
||||
${icon_path}/icon_256x256.png
|
||||
${icon_path}/icon_512x512.png
|
||||
)
|
||||
endif()
|
||||
if (ICONUTIL OR PNG2ICNS)
|
||||
set_source_files_properties(Icon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
target_add_resource(Telegram Icon.icns)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(lang_packs
|
||||
en
|
||||
@@ -1608,25 +1674,19 @@ elseif (APPLE)
|
||||
PRE_LINK
|
||||
COMMAND mkdir -p $<TARGET_FILE_DIR:Telegram>/../Resources
|
||||
COMMAND cp ${CMAKE_BINARY_DIR}/lib_ui.rcc $<TARGET_FILE_DIR:Telegram>/../Resources
|
||||
COMMAND cp ${CMAKE_BINARY_DIR}/lib_spellcheck.rcc $<TARGET_FILE_DIR:Telegram>/../Resources
|
||||
)
|
||||
if (NOT build_macstore)
|
||||
if (NOT build_macstore AND NOT DESKTOP_APP_DISABLE_CRASH_REPORTS)
|
||||
if (DESKTOP_APP_MAC_ARCH STREQUAL "x86_64" OR DESKTOP_APP_MAC_ARCH STREQUAL "arm64")
|
||||
set(crashpad_dir_part ".${DESKTOP_APP_MAC_ARCH}")
|
||||
else()
|
||||
set(crashpad_dir_part "")
|
||||
endif()
|
||||
add_custom_command(TARGET Telegram
|
||||
PRE_LINK
|
||||
COMMAND mkdir -p $<TARGET_FILE_DIR:Telegram>/../Frameworks
|
||||
COMMAND cp $<TARGET_FILE:Updater> $<TARGET_FILE_DIR:Telegram>/../Frameworks/
|
||||
COMMAND mkdir -p $<TARGET_FILE_DIR:Telegram>/../Helpers
|
||||
COMMAND cp ${libs_loc}/crashpad/out/$<IF:$<CONFIG:Debug>,Debug,Release>${crashpad_dir_part}/crashpad_handler $<TARGET_FILE_DIR:Telegram>/../Helpers/
|
||||
)
|
||||
if (NOT DESKTOP_APP_DISABLE_CRASH_REPORTS)
|
||||
if (DESKTOP_APP_MAC_ARCH STREQUAL "x86_64" OR DESKTOP_APP_MAC_ARCH STREQUAL "arm64")
|
||||
set(crashpad_dir_part ".${DESKTOP_APP_MAC_ARCH}")
|
||||
else()
|
||||
set(crashpad_dir_part "")
|
||||
endif()
|
||||
add_custom_command(TARGET Telegram
|
||||
PRE_LINK
|
||||
COMMAND mkdir -p $<TARGET_FILE_DIR:Telegram>/../Helpers
|
||||
COMMAND cp ${libs_loc}/crashpad/out/$<IF:$<CONFIG:Debug>,Debug,Release>${crashpad_dir_part}/crashpad_handler $<TARGET_FILE_DIR:Telegram>/../Helpers/
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(Telegram
|
||||
@@ -1675,7 +1735,11 @@ if (build_macstore)
|
||||
COMMAND rm -rf $<TARGET_FILE_DIR:Telegram>/../Frameworks/Breakpad.framework/Resources/Inspector
|
||||
)
|
||||
else()
|
||||
set(bundle_identifier "com.tdesktop.Telegram$<$<CONFIG:Debug>:Debug>")
|
||||
if (CMAKE_GENERATOR STREQUAL Xcode)
|
||||
set(bundle_identifier "com.tdesktop.Telegram$<$<CONFIG:Debug>:Debug>")
|
||||
else()
|
||||
set(bundle_identifier "com.tdesktop.Telegram")
|
||||
endif()
|
||||
set(bundle_entitlements "Telegram.entitlements")
|
||||
if (LINUX AND DESKTOP_APP_USE_PACKAGED)
|
||||
set(output_name "ayugram-desktop")
|
||||
@@ -1684,6 +1748,12 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (CMAKE_GENERATOR STREQUAL Xcode)
|
||||
set(bundle_identifier_plist "$(PRODUCT_BUNDLE_IDENTIFIER)")
|
||||
else()
|
||||
set(bundle_identifier_plist ${bundle_identifier})
|
||||
endif()
|
||||
|
||||
set_target_properties(Telegram PROPERTIES
|
||||
OUTPUT_NAME ${output_name}
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER ${bundle_identifier}
|
||||
@@ -1757,7 +1827,7 @@ endif()
|
||||
|
||||
target_prepare_qrc(Telegram)
|
||||
|
||||
if ((NOT DESKTOP_APP_DISABLE_AUTOUPDATE OR APPLE) AND NOT build_macstore AND NOT build_winstore)
|
||||
if (NOT DESKTOP_APP_DISABLE_AUTOUPDATE AND NOT build_macstore AND NOT build_winstore)
|
||||
add_executable(Updater WIN32)
|
||||
init_non_host_target(Updater)
|
||||
|
||||
@@ -1795,6 +1865,12 @@ if ((NOT DESKTOP_APP_DISABLE_AUTOUPDATE OR APPLE) AND NOT build_macstore AND NOT
|
||||
else()
|
||||
target_link_options(Updater PRIVATE -municode)
|
||||
endif()
|
||||
elseif (APPLE)
|
||||
add_custom_command(TARGET Updater
|
||||
PRE_LINK
|
||||
COMMAND mkdir -p $<TARGET_FILE_DIR:Telegram>/../Frameworks
|
||||
COMMAND cp $<TARGET_FILE:Updater> $<TARGET_FILE_DIR:Telegram>/../Frameworks/
|
||||
)
|
||||
endif()
|
||||
|
||||
if (DESKTOP_APP_SPECIAL_TARGET)
|
||||
@@ -1848,6 +1924,7 @@ if (LINUX AND DESKTOP_APP_USE_PACKAGED)
|
||||
install(FILES "Resources/art/icon128.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps" RENAME "ayugram.png")
|
||||
install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "ayugram.png")
|
||||
install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "ayugram.png")
|
||||
install(FILES "Resources/icons/tray_monochrome.svg" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/symbolic/apps" RENAME "telegram-symbolic.svg")
|
||||
install(FILES "../lib/xdg/ayugram.desktop.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ayugram.desktop.service" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/dbus-1/services")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ayugram.desktop.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo")
|
||||
|
||||
|
After Width: | Height: | Size: 312 B |
|
After Width: | Height: | Size: 517 B |
|
After Width: | Height: | Size: 754 B |
|
After Width: | Height: | Size: 324 B |
|
After Width: | Height: | Size: 521 B |
|
After Width: | Height: | Size: 692 B |
|
After Width: | Height: | Size: 613 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 621 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 727 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 386 B |
|
After Width: | Height: | Size: 630 B |
|
After Width: | Height: | Size: 841 B |
|
After Width: | Height: | Size: 368 B |
|
After Width: | Height: | Size: 648 B |
|
After Width: | Height: | Size: 864 B |
|
After Width: | Height: | Size: 661 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 324 B |
|
After Width: | Height: | Size: 484 B |
|
After Width: | Height: | Size: 623 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 277 B |
|
After Width: | Height: | Size: 474 B |
|
After Width: | Height: | Size: 619 B |
|
After Width: | Height: | Size: 324 B |
|
After Width: | Height: | Size: 610 B |
|
After Width: | Height: | Size: 890 B |
|
After Width: | Height: | Size: 239 B |
|
After Width: | Height: | Size: 416 B |
|
After Width: | Height: | Size: 554 B |
|
Before Width: | Height: | Size: 280 B After Width: | Height: | Size: 141 B |
|
Before Width: | Height: | Size: 519 B After Width: | Height: | Size: 151 B |
|
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 182 B |
|
After Width: | Height: | Size: 589 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 357 B After Width: | Height: | Size: 622 B |
|
Before Width: | Height: | Size: 603 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 822 B After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 450 B |
|
After Width: | Height: | Size: 725 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 454 B |
|
After Width: | Height: | Size: 761 B |
|
After Width: | Height: | Size: 1017 B |
|
After Width: | Height: | Size: 582 B |
|
After Width: | Height: | Size: 965 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 542 B |
|
After Width: | Height: | Size: 991 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 599 B |
|
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 806 B After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 548 B |
|
After Width: | Height: | Size: 938 B |
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="plane" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M1.3311718,6.36592184 C5.3576954,4.67244493 8.04267511,3.5560013 9.38611094,3.01659096 C13.2218932,1.47646481 14.0189359,1.2089284 14.5384372,1.2 C14.6526967,1.19815119 14.9081723,1.22548649 15.0736587,1.35511219 C15.2133922,1.4645656 15.2518384,1.61242159 15.2702362,1.71619544 C15.288634,1.81996929 15.3115436,2.05636876 15.2933322,2.24108442 C15.0854698,4.34939964 14.1860526,9.46572464 13.7284802,11.8270738 C13.5348641,12.8262491 13.1536281,13.1612675 12.7845475,13.1940535 C11.9824498,13.265305 11.3733733,12.6823476 10.5965026,12.190753 C9.3808532,11.4215044 8.69408865,10.9426448 7.51409044,10.1920004 C6.15039834,9.32450079 7.03442319,8.84770795 7.81158733,8.06849502 C8.01497489,7.86457129 11.5490353,4.7615061 11.6174372,4.48000946 C11.625992,4.44480359 11.6339313,4.31357282 11.5531696,4.24427815 C11.472408,4.17498349 11.3532107,4.19867957 11.2671947,4.21752527 C11.1452695,4.24423848 9.20325394,5.48334063 5.44114787,7.93483171 C4.88991321,8.30022994 4.39062196,8.47826423 3.94327414,8.46893456 C3.45010907,8.45864936 2.50145729,8.19975808 1.79623221,7.97846422 C0.931244952,7.70703829 0.243770289,7.56353344 0.303633888,7.10256824 C0.334814555,6.86246904 0.677327192,6.61692024 1.3311718,6.36592184 Z" id="Path-3" fill="#FFFFFF"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -129,6 +129,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_reconnecting#other" = "Reconnect in {count} s...";
|
||||
"lng_reconnecting_try_now" = "Try now";
|
||||
|
||||
"lng_code_block_header_copy" = "copy";
|
||||
|
||||
"lng_status_service_notifications" = "service notifications";
|
||||
"lng_status_support" = "support";
|
||||
"lng_status_bot" = "bot";
|
||||
@@ -402,6 +404,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_dlg_search_from" = "From: {user}";
|
||||
|
||||
"lng_settings_save" = "Save";
|
||||
"lng_settings_apply" = "Apply";
|
||||
|
||||
"lng_username_title" = "Username";
|
||||
"lng_username_description1" = "You can choose a username on Telegram. If you do, other people will be able to find you by this username and contact you without knowing your phone number.";
|
||||
@@ -543,6 +546,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_settings_workmode_tray" = "Show tray icon";
|
||||
"lng_settings_workmode_window" = "Show taskbar icon";
|
||||
"lng_settings_close_to_taskbar" = "Close to taskbar";
|
||||
"lng_settings_monochrome_icon" = "Use monochrome icon";
|
||||
"lng_settings_window_system" = "Window title";
|
||||
"lng_settings_title_chat_name" = "Show chat name";
|
||||
"lng_settings_title_account_name" = "Show active account";
|
||||
@@ -770,11 +774,33 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_clear_payment_info_clear" = "Clear";
|
||||
"lng_clear_payment_info_confirm" = "Delete your shipping info and instruct all payment providers to remove your saved credit cards? Note that Telegram never stores your credit card data.";
|
||||
|
||||
"lng_settings_theme_settings" = "Theme settings";
|
||||
"lng_settings_theme_name_color" = "Your name color";
|
||||
"lng_settings_auto_night_mode" = "Auto-Night mode";
|
||||
"lng_settings_auto_night_enabled" = "Match the system settings";
|
||||
"lng_settings_auto_night_mode_off" = "Off";
|
||||
"lng_settings_auto_night_mode_on" = "System";
|
||||
"lng_settings_auto_night_warning" = "You have enabled auto-night mode. If you want to change the dark mode settings, you'll need to disable it first.";
|
||||
"lng_settings_auto_night_disable" = "Disable";
|
||||
|
||||
"lng_settings_color_title" = "Color preview";
|
||||
"lng_settings_color_reply" = "Reply to your message";
|
||||
"lng_settings_color_reply_channel" = "Reply to your channel message";
|
||||
"lng_settings_color_text" = "Your name and replies to your messages will be shown in the selected color.";
|
||||
"lng_settings_color_text_channel" = "The name of the channel and replies to its messages will be shown in the selected color.";
|
||||
"lng_settings_color_link_name" = "Telegram";
|
||||
"lng_settings_color_link_title" = "Link Preview";
|
||||
"lng_settings_color_link_description" = "Your selected color will also tint the link preview.";
|
||||
"lng_settings_color_about" = "You can choose a color to tint your name, the links you send, and replies to your messages.";
|
||||
"lng_settings_color_about_channel" = "You can choose a color to tint your channel's name, the links it sends, and replies to its messages.";
|
||||
"lng_settings_color_emoji" = "Add icons to replies";
|
||||
"lng_settings_color_emoji_remove" = "Remove icon";
|
||||
"lng_settings_color_emoji_off" = "Off";
|
||||
"lng_settings_color_emoji_about" = "Make replies to your messages stand out by adding custom patterns to them.";
|
||||
"lng_settings_color_emoji_about_channel" = "Make replies to your channel's messages stand out by adding custom patterns to them.";
|
||||
"lng_settings_color_subscribe" = "Subscribe to {link} to choose a custom color for your name.";
|
||||
"lng_settings_color_changed" = "Your name color has been updated!";
|
||||
"lng_settings_color_changed_channel" = "Your channel color has been updated!";
|
||||
|
||||
"lng_suggest_hide_new_title" = "Hide new chats?";
|
||||
"lng_suggest_hide_new_about" = "You are receiving lots of new chats from users who are not in your Contact List.\n\nDo you want to have such chats **automatically muted** and **archived**?";
|
||||
"lng_suggest_hide_new_to_settings" = "Go to Settings";
|
||||
@@ -802,7 +828,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_background_text1" = "Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff!";
|
||||
"lng_background_text2" = "I can't even take you seriously right now.";
|
||||
"lng_background_bad_link" = "This background link appears to be invalid.";
|
||||
"lng_background_apply" = "Apply";
|
||||
"lng_background_share" = "Share";
|
||||
"lng_background_link_copied" = "Link copied to clipboard";
|
||||
"lng_background_blur" = "Blurred";
|
||||
@@ -1142,6 +1167,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_mute_box_title" = "Mute notifications for...";
|
||||
|
||||
"lng_preview_loading" = "Getting Link Info...";
|
||||
"lng_preview_cant" = "Could not generate preview for this link.";
|
||||
|
||||
"lng_profile_settings_section" = "Settings";
|
||||
"lng_profile_bot_settings" = "Bot Settings";
|
||||
@@ -1640,6 +1666,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_action_story_mention_button" = "View Story";
|
||||
"lng_action_story_mention_me_unavailable" = "The story where you mentioned {user} is no longer available.";
|
||||
"lng_action_story_mention_unavailable" = "The story where {user} mentioned you is no longer available.";
|
||||
"lng_action_giveaway_started" = "{from} just started a giveaway of Telegram Premium subscriptions to its followers.";
|
||||
|
||||
"lng_premium_gift_duration_months#one" = "for {count} month";
|
||||
"lng_premium_gift_duration_months#other" = "for {count} months";
|
||||
@@ -2003,6 +2030,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_premium_gift_terms_link" = "here";
|
||||
|
||||
"lng_boost_channel_button" = "Boost Channel";
|
||||
"lng_boost_again_button" = "Boost Again";
|
||||
"lng_boost_level#one" = "Level {count}";
|
||||
"lng_boost_level#other" = "Level {count}";
|
||||
"lng_boost_channel_title_first" = "Enable stories for channel";
|
||||
@@ -2024,6 +2052,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_boost_channel_post_stories#other" = "post **{count} stories** per day";
|
||||
"lng_boost_error_gifted_title" = "Can't boost with gifted Premium!";
|
||||
"lng_boost_error_gifted_text" = "Because your **Telegram Premium** subscription was gifted to you, you can't use it to boost channels.";
|
||||
"lng_boost_need_more" = "More boosts needed";
|
||||
"lng_boost_need_more_text#one" = "To boost {channel}, gift **Telegram Premium** to a friend and get **{count}** boosts.";
|
||||
"lng_boost_need_more_text#other" = "To boost {channel}, gift **Telegram Premium** to a friend and get **{count}** boosts.";
|
||||
"lng_boost_need_more_again#one" = "To boost {channel} again, gift **Telegram Premium** to a friend and get **{count}** additional boost.";
|
||||
"lng_boost_need_more_again#other" = "To boost {channel} again, gift **Telegram Premium** to a friend and get **{count}** additional boosts.";
|
||||
"lng_boost_error_already_title" = "Already Boosted!";
|
||||
"lng_boost_error_already_text" = "You are already boosting this channel.";
|
||||
"lng_boost_error_premium_title" = "Premium needed!";
|
||||
@@ -2033,6 +2066,162 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_boost_error_flood_text" = "You can change the channel you boost only once a day. Next time you can boost is in {left}.";
|
||||
"lng_boost_now_instead" = "You currently boost {channel}. Do you want to boost {other} instead?";
|
||||
"lng_boost_now_replace" = "Replace";
|
||||
"lng_boost_reassign_title" = "Reassign boost";
|
||||
"lng_boost_reassign_text" = "To boost {channel}, reassign a previous boost or {gift}.";
|
||||
"lng_boost_reassign_gift#one" = "gift **Telegram Premium** to a friend to get **{count}** additional boost";
|
||||
"lng_boost_reassign_gift#other" = "gift **Telegram Premium** to a friend to get **{count}** additional boosts";
|
||||
"lng_boost_remove_title" = "Remove your boost from";
|
||||
"lng_boost_reassign_button" = "Reassign";
|
||||
"lng_boost_available_in" = "available in {duration}";
|
||||
"lng_boost_available_in_toast#one" = "Wait until the boost is available or get **{count}** more boost by gifting a **Telegram Premium** subscription.";
|
||||
"lng_boost_available_in_toast#other" = "Wait until the boost is available or get **{count}** more boosts by gifting a **Telegram Premium** subscription.";
|
||||
"lng_boost_reassign_done#one" = "{count} boost is reassigned from {channels}.";
|
||||
"lng_boost_reassign_done#other" = "{count} boosts are reassigned from {channels}.";
|
||||
"lng_boost_reassign_channels#one" = "{count} channel";
|
||||
"lng_boost_reassign_channels#other" = "{count} channels";
|
||||
|
||||
"lng_boost_channel_title_color" = "Enable colors";
|
||||
"lng_boost_channel_needs_level_color#one" = "Your channel needs to reach **Level {count}** to change channel color.";
|
||||
"lng_boost_channel_needs_level_color#other" = "Your channel needs to reach **Level {count}** to change channel color.";
|
||||
"lng_boost_channel_ask" = "Ask your **Premium** subscribers to boost your channel with this link:";
|
||||
"lng_boost_channel_ask_button" = "Copy Link";
|
||||
"lng_boost_channel_or" = "or";
|
||||
"lng_boost_channel_gifting" = "Boost your channel by gifting your subscribers Telegram Premium. {link}";
|
||||
"lng_boost_channel_gifting_link" = "Get boosts >";
|
||||
|
||||
"lng_giveaway_new_title" = "Boosts via Gifts";
|
||||
"lng_giveaway_new_about" = "Get more boosts for your channel by gifting Premium to your subscribers.";
|
||||
"lng_giveaway_create_option" = "Create Giveaway";
|
||||
"lng_giveaway_create_subtitle" = "winners are chosen randomly";
|
||||
"lng_giveaway_award_option" = "Award Specific Users";
|
||||
"lng_giveaway_award_subtitle" = "Select recipients >";
|
||||
"lng_giveaway_award_chosen#one" = "{count} recipient >";
|
||||
"lng_giveaway_award_chosen#other" = "{count} recipients >";
|
||||
"lng_giveaway_quantity_title" = "Quantity of prizes";
|
||||
"lng_giveaway_quantity#one" = "{count} boost";
|
||||
"lng_giveaway_quantity#other" = "{count} boosts";
|
||||
"lng_giveaway_quantity_about" = "Choose how many Premium subscriptions to give away and boosts to receive.";
|
||||
"lng_giveaway_channels_title" = "Channels included in the giveaway";
|
||||
"lng_giveaway_channels_this#one" = "this channel will receive {count} boost";
|
||||
"lng_giveaway_channels_this#other" = "this channel will receive {count} boosts";
|
||||
"lng_giveaway_channels_add" = "Add Channel";
|
||||
"lng_giveaway_channels_about" = "Choose the channels the users need to join to take part in the giveaway.";
|
||||
"lng_giveaway_users_title" = "Users eligible for the giveaway";
|
||||
"lng_giveaway_users_all" = "All subscribers";
|
||||
"lng_giveaway_users_from_all_countries" = "from all countries";
|
||||
"lng_giveaway_users_from_one_country" = "from {country}";
|
||||
"lng_giveaway_users_from_countries#one" = "from {count} country";
|
||||
"lng_giveaway_users_from_countries#other" = "from {count} countries";
|
||||
"lng_giveaway_users_new" = "Only new subscribers";
|
||||
"lng_giveaway_users_about" = "Choose if you want to limit the giveaway only to those who joined the channel after the giveaway started or to users from specific countries.";
|
||||
"lng_giveaway_start" = "Start Giveaway";
|
||||
"lng_giveaway_award" = "Gift Premium";
|
||||
"lng_giveaway_start_sure" = "Are you sure you want to start this prepaid giveaway now? This action cannot be undone.";
|
||||
"lng_giveaway_date_title" = "Date when giveaway ends";
|
||||
"lng_giveaway_date" = "Date and Time";
|
||||
"lng_giveaway_date_about#one" = "Choose when {count} subscriber of your channel will be randomly selected to receive Telegram Premium.";
|
||||
"lng_giveaway_date_about#other" = "Choose when {count} subscribers of your channel will be randomly selected to receive Telegram Premium.";
|
||||
"lng_giveaway_duration_title#one" = "Duration of Premium subscription";
|
||||
"lng_giveaway_duration_title#other" = "Duration of Premium subscriptions";
|
||||
"lng_giveaway_duration_price" = "{price} x {amount}";
|
||||
"lng_giveaway_date_select" = "Select Date and Time";
|
||||
"lng_giveaway_date_confirm" = "Confirm";
|
||||
"lng_giveaway_channels_select#one" = "Select up to {count} channel";
|
||||
"lng_giveaway_channels_select#other" = "Select up to {count} channels";
|
||||
"lng_giveaway_recipients_save" = "Save Recipients";
|
||||
"lng_giveaway_recipients_deselect" = "Deselect All";
|
||||
"lng_giveaway_maximum_countries_error#one" = "You can select maximum {count} country.";
|
||||
"lng_giveaway_maximum_countries_error#other" = "You can select maximum {count} countries.";
|
||||
"lng_giveaway_maximum_channels_error#one" = "You can select maximum {count} channel.";
|
||||
"lng_giveaway_maximum_channels_error#other" = "You can select maximum {count} channels.";
|
||||
"lng_giveaway_maximum_users_error#one" = "You can select maximum {count} user.";
|
||||
"lng_giveaway_maximum_users_error#other" = "You can select maximum {count} users.";
|
||||
"lng_giveaway_channels_confirm_title" = "Channel is Private";
|
||||
"lng_giveaway_channels_confirm_about" = "Are you sure you want to add a private channel? Users won't be able to join it without an invite link.";
|
||||
|
||||
"lng_giveaway_created_title" = "Giveaway created";
|
||||
"lng_giveaway_created_body" = "Check your channels' {link} to see how this giveaway boosted your channel.";
|
||||
"lng_giveaway_awarded_title" = "Premium subscriptions gifted";
|
||||
"lng_giveaway_awarded_body" = "Check your channels' {link} to see how gifts boosted your channel.";
|
||||
"lng_giveaway_created_link" = "Statistics";
|
||||
|
||||
"lng_prize_title" = "Congratulations!";
|
||||
"lng_prize_about" = "You won a prize in a giveaway organized by {channel}.";
|
||||
"lng_prize_duration" = "Your prize is a **Telegram Premium** subscription {duration}.";
|
||||
"lng_prize_gift_about" = "You've received a gift from {channel}.";
|
||||
"lng_prize_gift_duration" = "Your gift is a **Telegram Premium** subscription {duration}.";
|
||||
"lng_prize_open" = "Open Gift Link";
|
||||
"lng_prize_unclaimed_title" = "Unclaimed Prize";
|
||||
"lng_prize_unclaimed_about" = "You have an unclaimed prize from a giveaway by {channel}.";
|
||||
"lng_prize_unclaimed_duration" = "This prize is a **Telegram Premium** subscription {duration}.";
|
||||
|
||||
"lng_prizes_title#one" = "Giveaway Prize";
|
||||
"lng_prizes_title#other" = "Giveaway Prizes";
|
||||
"lng_prizes_about#one" = "**{count}** Telegram Premium Subscription {duration}.";
|
||||
"lng_prizes_about#other" = "**{count}** Telegram Premium Subscriptions {duration}.";
|
||||
"lng_prizes_participants" = "Participants";
|
||||
"lng_prizes_participants_all#one" = "All subscribers of the channel:";
|
||||
"lng_prizes_participants_all#other" = "All subscribers of the channels:";
|
||||
"lng_prizes_participants_new#one" = "All users who joined the channel below after this date:";
|
||||
"lng_prizes_participants_new#other" = "All users who joined the channels below after this date:";
|
||||
"lng_prizes_countries" = "from {countries}";
|
||||
"lng_prizes_countries_and_one" = "{countries}, {country}";
|
||||
"lng_prizes_countries_and_last" = "{countries} and {country}";
|
||||
"lng_prizes_date" = "Winners Selection Date";
|
||||
"lng_prizes_how_works" = "Learn more";
|
||||
"lng_prizes_how_title" = "About this giveaway";
|
||||
"lng_prizes_end_title" = "Giveaway ended";
|
||||
"lng_prizes_how_text" = "This giveaway is sponsored by {admins}.";
|
||||
"lng_prizes_end_text" = "This giveaway was sponsored by {admins}.";
|
||||
"lng_prizes_admins#one" = "the admins of {channel}, who aquired **{count} Telegram Premium** subscription {duration} for its followers";
|
||||
"lng_prizes_admins#other" = "the admins of {channel}, who aquired **{count} Telegram Premium** subscriptions {duration} for its followers.";
|
||||
"lng_prizes_how_when_finish" = "On {date}, Telegram will automatically select {winners}.";
|
||||
"lng_prizes_end_when_finish" = "On {date}, Telegram automatically selected {winners}.";
|
||||
"lng_prizes_end_activated#one" = "**{count}** of the winners already used their gift link.";
|
||||
"lng_prizes_end_activated#other" = "**{count}** of the winners already used their gift links.";
|
||||
"lng_prizes_winners_all_of_one#one" = "{count} random subscribers of {channel}";
|
||||
"lng_prizes_winners_all_of_one#other" = "{count} random subscribers of {channel}";
|
||||
"lng_prizes_winners_all_of_many#one" = "{count} random subscribers of {channel} and other listed channels";
|
||||
"lng_prizes_winners_all_of_many#other" = "{count} random subscribers of {channel} and other listed channels";
|
||||
"lng_prizes_winners_new_of_one#one" = "{count} random user that joined {channel} after {start_date}";
|
||||
"lng_prizes_winners_new_of_one#other" = "{count} random users that joined {channel} after {start_date}";
|
||||
"lng_prizes_winners_new_of_many#one" = "{count} random user that joined {channel} and other listed channels after {start_date}";
|
||||
"lng_prizes_winners_new_of_many#other" = "{count} random users that joined {channel} and other listed channels after {start_date}";
|
||||
"lng_prizes_how_participate_one" = "To take part in this giveaway please join channel {channel} before {date}.";
|
||||
"lng_prizes_how_participate_many" = "To take part in this giveaway please join channel {channel} and other listed channels before {date}.";
|
||||
"lng_prizes_how_no_admin" = "You are not eligible to participate in this giveaway, because you are an admin of participating channel ({channel}).";
|
||||
"lng_prizes_how_no_joined" = "You are not eligible to participate in this giveaway, because you joined this channel on {date}, which is before the contest started.";
|
||||
"lng_prizes_how_no_country" = "You are not eligible to participate in this giveaway, because your country is not included in the terms of the giveaway.";
|
||||
"lng_prizes_how_yes_joined_one" = "You are participating in this giveaway, because you have joined channel {channel}.";
|
||||
"lng_prizes_how_yes_joined_many" = "You are participating in this giveaway, because you have joined channel {channel} (and other listed channels).";
|
||||
"lng_prizes_you_won" = "You won a prize in this giveaway {cup}";
|
||||
"lng_prizes_view_prize" = "View my prize";
|
||||
"lng_prizes_you_didnt" = "You didn't win a prize in this giveaway.";
|
||||
"lng_prizes_cancelled" = "The channel cancelled the prizes by reversing the payment for them.";
|
||||
"lng_prizes_badge" = "x{amount}";
|
||||
|
||||
"lng_gift_link_title" = "Gift Link";
|
||||
"lng_gift_link_about" = "This link allows you to activate\na **Telegram Premium** subscription.";
|
||||
"lng_gift_link_label_from" = "From";
|
||||
"lng_gift_link_label_to" = "To";
|
||||
"lng_gift_link_label_to_unclaimed" = "No recipient";
|
||||
"lng_gift_link_label_gift" = "Gift";
|
||||
"lng_gift_link_gift_premium" = "Telegram Premium {duration}";
|
||||
"lng_gift_link_label_reason" = "Reason";
|
||||
"lng_gift_link_reason_giveaway" = "Giveaway";
|
||||
"lng_gift_link_reason_unclaimed" = "Incomplete Giveaway";
|
||||
"lng_gift_link_reason_chosen" = "You were selected by the channel";
|
||||
"lng_gift_link_label_date" = "Date";
|
||||
"lng_gift_link_also_send" = "You can also {link} to a friend as a gift.";
|
||||
"lng_gift_link_also_send_link" = "send this link";
|
||||
"lng_gift_link_use" = "Use Link";
|
||||
"lng_gift_link_used_title" = "Used Gift Link";
|
||||
"lng_gift_link_used_about" = "This link was used to activate\na **Telegram Premium** subscription.";
|
||||
"lng_gift_link_used_footer" = "This link was used on {date}.";
|
||||
"lng_gift_link_expired" = "Gift code link expired";
|
||||
"lng_gift_link_pending_about" = "This link allows {user} to activate\na **Telegram Premium** subscription.";
|
||||
"lng_gift_link_pending_toast" = "Only the recipient can see the link.";
|
||||
"lng_gift_link_pending_footer" = "This link hasn't been activated yet.";
|
||||
|
||||
"lng_accounts_limit_title" = "Limit Reached";
|
||||
"lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected accounts.";
|
||||
@@ -2213,6 +2402,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_saved_messages" = "Saved Messages";
|
||||
"lng_saved_short" = "Save";
|
||||
"lng_saved_forward_here" = "Forward messages here for quick access";
|
||||
"lng_saved_quote_here" = "Quote here to save";
|
||||
|
||||
"lng_scheduled_messages" = "Scheduled Messages";
|
||||
"lng_scheduled_messages_empty" = "No scheduled messages here yet...";
|
||||
@@ -2420,6 +2610,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_context_attached_stickers" = "Attached Stickers";
|
||||
"lng_context_to_msg" = "Go To Message";
|
||||
"lng_context_reply_msg" = "Reply";
|
||||
"lng_context_quote_and_reply" = "Quote & Reply";
|
||||
"lng_context_edit_msg" = "Edit";
|
||||
"lng_context_forward_msg" = "Forward Message";
|
||||
"lng_context_send_now_msg" = "Send now";
|
||||
@@ -2524,6 +2715,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_inline_switch_choose" = "Choose conversation...";
|
||||
"lng_inline_switch_cant" = "Sorry, no way to write here :(";
|
||||
|
||||
"lng_reply_in_another_title" = "Reply in...";
|
||||
"lng_reply_in_another_chat" = "Reply in Another Chat";
|
||||
"lng_reply_show_in_chat" = "Show in Chat";
|
||||
"lng_reply_remove" = "Do Not Reply";
|
||||
"lng_reply_about_quote" = "You can select specific part to quote.";
|
||||
"lng_reply_options_header" = "Reply to Message";
|
||||
"lng_reply_options_quote" = "Update Quote";
|
||||
"lng_reply_header_short" = "Reply";
|
||||
"lng_reply_quote_selected" = "Quote Selected";
|
||||
"lng_reply_from_private_chat" = "This reply is from a private chat.";
|
||||
"lng_link_options_header" = "Link Preview Settings";
|
||||
"lng_link_header_short" = "Link";
|
||||
"lng_link_move_up" = "Move Up";
|
||||
"lng_link_move_down" = "Move Down";
|
||||
"lng_link_shrink_photo" = "Shrink Photo";
|
||||
"lng_link_enlarge_photo" = "Enlarge Photo";
|
||||
"lng_link_remove" = "Do Not Preview";
|
||||
"lng_link_about_choose" = "Click on a link to generate its preview.";
|
||||
|
||||
"lng_share_cant" = "Sorry, no way to share here :(";
|
||||
"lng_reply_cant" = "Sorry, no way to reply to an old message in supergroup :(";
|
||||
"lng_reply_cant_forward" = "Sorry, you can't reply to a message that was sent before the group was upgraded to a supergroup. Do you wish to forward it and add your comment?";
|
||||
@@ -2546,6 +2756,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_edit_bot_title" = "Edit bot";
|
||||
"lng_edit_sign_messages" = "Sign messages";
|
||||
"lng_edit_group" = "Edit group";
|
||||
"lng_edit_channel_color" = "Change name color";
|
||||
"lng_edit_self_title" = "Edit your name";
|
||||
"lng_confirm_contact_data" = "New Contact";
|
||||
"lng_add_contact" = "Create";
|
||||
@@ -2674,6 +2885,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_menu_formatting_italic" = "Italic";
|
||||
"lng_menu_formatting_underline" = "Underline";
|
||||
"lng_menu_formatting_strike_out" = "Strike-through";
|
||||
"lng_menu_formatting_blockquote" = "Quote";
|
||||
"lng_menu_formatting_monospace" = "Monospace";
|
||||
"lng_menu_formatting_spoiler" = "Spoiler";
|
||||
"lng_menu_formatting_link_create" = "Create link";
|
||||
@@ -2686,6 +2898,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_formatting_link_create" = "Create";
|
||||
|
||||
"lng_text_copied" = "Text copied to clipboard.";
|
||||
"lng_code_copied" = "Block copied to clipboard.";
|
||||
|
||||
"lng_spellchecker_submenu" = "Spelling";
|
||||
"lng_spellchecker_add" = "Add to Dictionary";
|
||||
@@ -3351,6 +3564,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_admin_log_participant_volume_channel" = "{from} changed live stream volume for {user} to {percent}";
|
||||
"lng_admin_log_antispam_enabled" = "{from} enabled aggressive anti-spam";
|
||||
"lng_admin_log_antispam_disabled" = "{from} disabled aggressive anti-spam";
|
||||
"lng_admin_log_change_color" = "{from} changed channel color from {previous} to {color}";
|
||||
"lng_admin_log_set_background_emoji" = "{from} set channel background emoji to {emoji}";
|
||||
"lng_admin_log_change_background_emoji" = "{from} changed channel background emoji from {previous} to {emoji}";
|
||||
"lng_admin_log_removed_background_emoji" = "{from} removed channel background emoji {emoji}";
|
||||
"lng_admin_log_user_with_username" = "{name} ({mention})";
|
||||
"lng_admin_log_messages_ttl_set" = "{from} enabled messages auto-delete after {duration}";
|
||||
"lng_admin_log_messages_ttl_changed" = "{from} changed messages auto-delete period from {previous} to {duration}";
|
||||
@@ -4065,6 +4282,99 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
"lng_stories_link_invalid" = "This link is broken or has expired.";
|
||||
|
||||
"lng_stats_title" = "Statistics";
|
||||
"lng_stats_message_title" = "Message Statistic";
|
||||
"lng_stats_zoom_out" = "Zoom Out";
|
||||
|
||||
"lng_stats_overview_title" = "Overview";
|
||||
"lng_stats_overview_member_count" = "Followers";
|
||||
"lng_stats_overview_mean_view_count" = "Views Per Post";
|
||||
"lng_stats_overview_mean_share_count" = "Shared Per Post";
|
||||
"lng_stats_overview_enabled_notifications" = "Enabled Notifications";
|
||||
"lng_stats_overview_messages" = "Messages";
|
||||
"lng_stats_overview_group_mean_view_count" = "Viewing Members";
|
||||
"lng_stats_overview_group_mean_post_count" = "Posting Members";
|
||||
"lng_stats_overview_message_private_shares" = "Private Shares";
|
||||
"lng_stats_overview_message_public_shares" = "Public Shares";
|
||||
"lng_stats_overview_message_views" = "Views";
|
||||
"lng_stats_overview_message_public_share#one" = "{count} public share";
|
||||
"lng_stats_overview_message_public_share#other" = "{count} public shares";
|
||||
|
||||
"lng_stats_members_title" = "Top members";
|
||||
"lng_stats_admins_title" = "Top admins";
|
||||
"lng_stats_inviters_title" = "Top inviters";
|
||||
"lng_stats_member_messages#one" = "{count} message";
|
||||
"lng_stats_member_messages#other" = "{count} messages";
|
||||
"lng_stats_member_characters#one" = "{count} symbol per message";
|
||||
"lng_stats_member_characters#other" = "{count} symbols per message";
|
||||
"lng_stats_member_deletions#one" = "{count} deletions";
|
||||
"lng_stats_member_deletions#other" = "{count} deletions";
|
||||
"lng_stats_member_bans#one" = "{count} ban";
|
||||
"lng_stats_member_bans#other" = "{count} bans";
|
||||
"lng_stats_member_restrictions#one" = "{count} restriction";
|
||||
"lng_stats_member_restrictions#other" = "{count} restrictions";
|
||||
"lng_stats_member_invitations#one" = "{count} invitation";
|
||||
"lng_stats_member_invitations#other" = "{count} invitations";
|
||||
|
||||
"lng_stats_recent_messages_title" = "Recent posts";
|
||||
"lng_stats_recent_messages_views#one" = "{count} view";
|
||||
"lng_stats_recent_messages_views#other" = "{count} views";
|
||||
"lng_stats_recent_messages_shares#one" = "{count} share";
|
||||
"lng_stats_recent_messages_shares#other" = "{count} shares";
|
||||
|
||||
"lng_stats_loading" = "Loading stats...";
|
||||
"lng_stats_loading_subtext" = "Please wait a few moments while we generate your stats.";
|
||||
|
||||
"lng_chart_title_member_count" = "Growth";
|
||||
"lng_chart_title_join" = "Followers";
|
||||
"lng_chart_title_mute" = "Notifications";
|
||||
"lng_chart_title_view_count_by_hour" = "Views by hours";
|
||||
"lng_chart_title_view_count_by_source" = "Views by source";
|
||||
"lng_chart_title_join_by_source" = "New followers by source";
|
||||
"lng_chart_title_language" = "Languages";
|
||||
"lng_chart_title_message_interaction" = "Interactions";
|
||||
"lng_chart_title_instant_view_interaction" = "IV Interactions";
|
||||
|
||||
"lng_chart_title_group_join" = "Group members";
|
||||
"lng_chart_title_group_join_by_source" = "New members by source";
|
||||
"lng_chart_title_group_language" = "Members's primary language";
|
||||
"lng_chart_title_group_message_content" = "Messages";
|
||||
"lng_chart_title_group_action" = "Actions";
|
||||
"lng_chart_title_group_day" = "Views by hours";
|
||||
"lng_chart_title_group_week" = "Top days of week";
|
||||
|
||||
"lng_boosts_title" = "Boosts";
|
||||
"lng_boosts_level" = "Level";
|
||||
"lng_boosts_existing" = "Existing boosts";
|
||||
"lng_boosts_premium_audience" = "Premium subscribers";
|
||||
"lng_boosts_next_level" = "Boosts to level up";
|
||||
"lng_boosts_list_title#one" = "{count} Boost";
|
||||
"lng_boosts_list_title#other" = "{count} Boosts";
|
||||
"lng_boosts_list_subtext" = "Your channel is currently boosted by these users.";
|
||||
"lng_boosts_show_more_boosts#one" = "Show {count} More Boosts";
|
||||
"lng_boosts_show_more_boosts#other" = "Show {count} More Boosts";
|
||||
"lng_boosts_show_more_gifts#one" = "Show {count} More Boosts";
|
||||
"lng_boosts_show_more_gifts#other" = "Show {count} More Boosts";
|
||||
"lng_boosts_list_status" = "boost expires on {date}";
|
||||
"lng_boosts_link_title" = "Link for boosting";
|
||||
"lng_boosts_link_subtext" = "Share this link with your subscribers to get more boosts.";
|
||||
"lng_boosts_get_boosts" = "Get Boosts via Gifts";
|
||||
"lng_boosts_get_boosts_subtext" = "Get more boosts for your channel by gifting Telegram Premium to your subscribers.";
|
||||
"lng_boosts_list_unclaimed" = "Unclaimed";
|
||||
"lng_boosts_list_pending" = "To be distributed";
|
||||
"lng_boosts_list_pending_about" = "The recipient will be selected when the giveaway ends.";
|
||||
"lng_boosts_list_tab_gifts#one" = "{count} Gifts";
|
||||
"lng_boosts_list_tab_gifts#other" = "{count} Gifts";
|
||||
|
||||
"lng_boosts_prepaid_giveaway_title" = "Prepaid giveaways";
|
||||
"lng_boosts_prepaid_giveaway_single" = "Prepaid giveaway";
|
||||
"lng_boosts_prepaid_giveaway_quantity#one" = "{count} Telegram Premium";
|
||||
"lng_boosts_prepaid_giveaway_quantity#other" = "{count} Telegram Premium";
|
||||
"lng_boosts_prepaid_giveaway_moths#one" = "{count}-month subscriptions";
|
||||
"lng_boosts_prepaid_giveaway_moths#other" = "{count}-month subscriptions";
|
||||
"lng_boosts_prepaid_giveaway_status#one" = "{count} subscription {duration}";
|
||||
"lng_boosts_prepaid_giveaway_status#other" = "{count} subscriptions {duration}";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
"lng_wnd_choose_program_menu" = "Choose Default Program...";
|
||||
@@ -4135,6 +4445,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
// AyuGram keys generated
|
||||
|
||||
"ayu_AyuPreferences" = "AyuGram Preferences";
|
||||
"ayu_DocsText" = "Documentation";
|
||||
"ayu_GhostEssentialsHeader" = "Ghost essentials";
|
||||
"ayu_DontReadMessages" = "Don't read messages";
|
||||
"ayu_DontReadStories" = "Don't read stories";
|
||||
@@ -4182,6 +4493,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"ayu_SettingsShowID_Hide" = "Hide";
|
||||
"ayu_SettingsRecentStickersCount" = "Recent stickers count";
|
||||
"ayu_SettingsCustomizationHint" = "After making changes to the \"Customization\" section, you must restart the application.";
|
||||
"ayu_DrawerElementsHeader" = "Drawer Elements";
|
||||
"ayu_TrayElementsHeader" = "Tray Elements";
|
||||
"ayu_RegexFilters" = "Message Filters";
|
||||
"ayu_RegexFiltersAmount" = "filters";
|
||||
"ayu_RegexFiltersHeader" = "Filters";
|
||||
@@ -4195,6 +4508,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"ayu_EnableExpression" = "Enable expression";
|
||||
"ayu_CaseInsensitiveExpression" = "Case insensitive expression";
|
||||
"ayu_RegexFiltersAddError" = "Regex syntax error";
|
||||
"ayu_RegexFilterQuickAdd" = "Add filter";
|
||||
"ayu_AyuSyncHeader" = "AyuSync";
|
||||
"ayu_AyuSyncStatusTitle" = "Sync status";
|
||||
"ayu_AyuSyncStatusOk" = "connected";
|
||||
@@ -4217,7 +4531,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"ayu_AyuSyncDownloadAgent" = "Download agent";
|
||||
"ayu_IconDefault" = "Default";
|
||||
"ayu_IconAlternative" = "AyuGram Alt";
|
||||
"ayu_IconDiscord" = "Discord";
|
||||
"ayu_IconSpotify" = "Spotify";
|
||||
"ayu_IconExtera" = "extera";
|
||||
"ayu_IconNothing" = "Nothing";
|
||||
"ayu_IconBard" = "Google Bard";
|
||||
"ayu_IconYaPlus" = "Yandex Plus";
|
||||
"ayu_WALMode" = "Enable WAL mode";
|
||||
"ayu_PushNotificationCount" = "FCM notifications received";
|
||||
"ayu_ClearAyuDatabase" = "Clear Ayu Database";
|
||||
@@ -4244,8 +4563,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"ayu_DisableStreamerModeTray" = "Disable Streamer Mode";
|
||||
"ayu_EditsHistoryTitle" = "Edits history";
|
||||
"ayu_EditsHistoryMenuText" = "History";
|
||||
"ayu_PeekOnlineMenuText" = "Peek Online";
|
||||
"ayu_ClearDeletedMenuText" = "Clear Deleted";
|
||||
"ayu_ViewFiltersMenuText" = "View Filters";
|
||||
"ayu_PeekOnlineSuccess" = "Peeked via";
|
||||
"ayu_OneViewTTL" = "one view";
|
||||
"ayu_ReadUntilMenuText" = "Read Message";
|
||||
"ayu_DeleteKeepLocally" = "Keep locally";
|
||||
@@ -4256,11 +4577,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"ayu_ClearDeletedMessagesText" = "Are you sure you want to clear all deleted messages in this chat?";
|
||||
"ayu_ClearDeletedMessagesActionText" = "Clear";
|
||||
"ayu_SuggestGhostModeTitle" = "Ghost Mode";
|
||||
"ayu_SuggestGhostModeStoryText" = "Do you want to enable Ghost Mode before viewing the story?";
|
||||
"ayu_SuggestGhostModeStoryActionText" = "Enable";
|
||||
"ayu_SuggestGhostModeStoryText" = "Do you want to enable **Ghost Mode** before viewing the story?";
|
||||
"ayu_SuggestGhostModeStoryActionTextYes" = "Yes";
|
||||
"ayu_SuggestGhostModeStoryActionTextNo" = "No";
|
||||
"ayu_HideNextViewsDescriptionAyu" = "Hide my views forever, until Ghost Mode disabled.";
|
||||
"ayu_EnableGhostModeStories" = "Enable Ghost Mode";
|
||||
"ayu_GhostModeIsActive" = "Ghost Mode Is Active";
|
||||
"ayu_SimpleQuotesAndReplies" = "Simple quotes & replies";
|
||||
"ayu_MainFont" = "Application font";
|
||||
"ayu_MonospaceFont" = "Monospace font";
|
||||
"ayu_FontDefault" = "Default";
|
||||
@@ -4270,6 +4593,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"ayu_AyuForwardForwardingDescription" = "Please keep this window open while AyuGram is forwarding your messages.";
|
||||
"ayu_AyuForwardLoadingMediaDescription" = "Please keep this window open while AyuGram is downloading media from your messages.";
|
||||
"ayu_DeleteDateMenuText" = "Delete Date";
|
||||
"ayu_ForwardableMenuText" = "Forwardable";
|
||||
"ayu_ForwardableMenuTextNo" = "No";
|
||||
"ayu_LikelyOfflineStatus" = "offline ?";
|
||||
"ayu_GhostModeShortcut" = "Enter with Ghost";
|
||||
"ayu_SettingsShowMessageSeconds" = "Show message seconds";
|
||||
|
||||
@@ -10,5 +10,6 @@
|
||||
<file alias="cloud_password/email.tgs">../../animations/cloud_password/email.tgs</file>
|
||||
<file alias="ttl.tgs">../../animations/ttl.tgs</file>
|
||||
<file alias="discussion.tgs">../../animations/discussion.tgs</file>
|
||||
<file alias="stats.tgs">../../animations/stats.tgs</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
<file alias="icons/settings/dino.svg">../../icons/settings/dino.svg</file>
|
||||
<file alias="icons/settings/star.svg">../../icons/settings/star.svg</file>
|
||||
<file alias="icons/settings/starmini.svg">../../icons/settings/starmini.svg</file>
|
||||
<file alias="icons/tray/monochrome.svg">../../icons/tray_monochrome.svg</file>
|
||||
<file alias="topic_icons/blue.svg">../../art/topic_icons/blue.svg</file>
|
||||
<file alias="topic_icons/yellow.svg">../../art/topic_icons/yellow.svg</file>
|
||||
<file alias="topic_icons/violet.svg">../../art/topic_icons/violet.svg</file>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="4.10.2.0" />
|
||||
Version="4.11.6.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
||||
|
||||
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,10,2,0
|
||||
PRODUCTVERSION 4,10,2,0
|
||||
FILEVERSION 4,11,6,0
|
||||
PRODUCTVERSION 4,11,6,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -62,10 +62,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Radolyn Labs"
|
||||
VALUE "FileDescription", "AyuGram Desktop"
|
||||
VALUE "FileVersion", "4.10.2.0"
|
||||
VALUE "FileVersion", "4.11.6.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
|
||||
VALUE "ProductName", "AyuGram Desktop"
|
||||
VALUE "ProductVersion", "4.10.2.0"
|
||||
VALUE "ProductVersion", "4.11.6.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,10,2,0
|
||||
PRODUCTVERSION 4,10,2,0
|
||||
FILEVERSION 4,11,6,0
|
||||
PRODUCTVERSION 4,11,6,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -53,10 +53,10 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Radolyn Labs"
|
||||
VALUE "FileDescription", "AyuGram Desktop Updater"
|
||||
VALUE "FileVersion", "4.10.2.0"
|
||||
VALUE "FileVersion", "4.11.6.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
|
||||
VALUE "ProductName", "AyuGram Desktop"
|
||||
VALUE "ProductVersion", "4.10.2.0"
|
||||
VALUE "ProductVersion", "4.11.6.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -169,9 +169,7 @@ void SendBotCallbackData(
|
||||
void HideSingleUseKeyboard(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<HistoryItem*> item) {
|
||||
controller->content()->hideSingleUseKeyboard(
|
||||
item->history()->peer,
|
||||
item->id);
|
||||
controller->content()->hideSingleUseKeyboard(item->fullId());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -312,12 +310,14 @@ void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
|
||||
case ButtonType::Default: {
|
||||
// Copy string before passing it to the sending method
|
||||
// because the original button can be destroyed inside.
|
||||
const auto replyTo = item->isRegular() ? item->id : 0;
|
||||
const auto replyTo = item->isRegular()
|
||||
? item->fullId()
|
||||
: FullMsgId();
|
||||
controller->content()->sendBotCommand({
|
||||
.peer = item->history()->peer,
|
||||
.command = QString(button->text),
|
||||
.context = item->fullId(),
|
||||
.replyTo = replyTo,
|
||||
.replyTo = { replyTo },
|
||||
});
|
||||
} break;
|
||||
|
||||
@@ -363,7 +363,7 @@ void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
|
||||
|
||||
case ButtonType::RequestPhone: {
|
||||
HideSingleUseKeyboard(controller, item);
|
||||
const auto itemId = item->id;
|
||||
const auto itemId = item->fullId();
|
||||
const auto topicRootId = item->topicRootId();
|
||||
const auto history = item->history();
|
||||
controller->show(Ui::MakeConfirmBox({
|
||||
@@ -376,7 +376,7 @@ void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
|
||||
auto action = Api::SendAction(history);
|
||||
action.clearDraft = false;
|
||||
action.replyTo = {
|
||||
.msgId = itemId,
|
||||
.messageId = itemId,
|
||||
.topicRootId = topicRootId,
|
||||
};
|
||||
history->session().api().shareContact(
|
||||
@@ -397,13 +397,11 @@ void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
|
||||
chosen |= PollData::Flag::Quiz;
|
||||
}
|
||||
}
|
||||
const auto replyToId = MsgId(0);
|
||||
const auto topicRootId = MsgId(0);
|
||||
const auto replyTo = FullReplyTo();
|
||||
Window::PeerMenuCreatePoll(
|
||||
controller,
|
||||
item->history()->peer,
|
||||
replyToId,
|
||||
topicRootId,
|
||||
replyTo,
|
||||
chosen,
|
||||
disabled);
|
||||
} break;
|
||||
|
||||
@@ -19,8 +19,8 @@ SendAction::SendAction(
|
||||
SendOptions options)
|
||||
: history(thread->owningHistory())
|
||||
, options(options)
|
||||
, replyTo({ .msgId = thread->topicRootId() }) {
|
||||
replyTo.topicRootId = replyTo.msgId;
|
||||
, replyTo({ .messageId = { history->peer->id, thread->topicRootId() } }) {
|
||||
replyTo.topicRootId = replyTo.messageId.msg;
|
||||
}
|
||||
|
||||
SendOptions DefaultSendWhenOnlineOptions() {
|
||||
@@ -31,7 +31,7 @@ SendOptions DefaultSendWhenOnlineOptions() {
|
||||
}
|
||||
|
||||
MTPInputReplyTo SendAction::mtpReplyTo() const {
|
||||
return Data::ReplyToForMTP(&history->owner(), replyTo);
|
||||
return Data::ReplyToForMTP(history, replyTo);
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
||||
@@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "data/data_drafts.h"
|
||||
|
||||
class History;
|
||||
|
||||
namespace Data {
|
||||
@@ -22,7 +24,6 @@ struct SendOptions {
|
||||
TimeId scheduled = 0;
|
||||
bool silent = false;
|
||||
bool handleSupportSwitch = false;
|
||||
bool removeWebPageId = false;
|
||||
bool hideViaBot = false;
|
||||
};
|
||||
[[nodiscard]] SendOptions DefaultSendWhenOnlineOptions();
|
||||
@@ -54,7 +55,7 @@ struct MessageToSend {
|
||||
|
||||
SendAction action;
|
||||
TextWithTags textWithTags;
|
||||
WebPageId webPageId = 0;
|
||||
Data::WebPageDraft webPage;
|
||||
};
|
||||
|
||||
struct RemoteFileInfo {
|
||||
|
||||
@@ -11,8 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "api/api_media.h"
|
||||
#include "api/api_text_entities.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "data/data_histories.h"
|
||||
#include "data/data_scheduled_messages.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_web_page.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "lang/lang_keys.h"
|
||||
@@ -45,6 +47,7 @@ template <typename DoneCallback, typename FailCallback>
|
||||
mtpRequestId EditMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities &textWithEntities,
|
||||
Data::WebPageDraft webpage,
|
||||
SendOptions options,
|
||||
DoneCallback &&done,
|
||||
FailCallback &&fail,
|
||||
@@ -65,15 +68,21 @@ mtpRequestId EditMessage(
|
||||
|
||||
const auto emptyFlag = MTPmessages_EditMessage::Flag(0);
|
||||
const auto flags = emptyFlag
|
||||
| (!text.isEmpty() || media
|
||||
| ((!text.isEmpty() || media)
|
||||
? MTPmessages_EditMessage::Flag::f_message
|
||||
: emptyFlag)
|
||||
| ((media && inputMedia.has_value())
|
||||
? MTPmessages_EditMessage::Flag::f_media
|
||||
: emptyFlag)
|
||||
| (options.removeWebPageId
|
||||
| (webpage.removed
|
||||
? MTPmessages_EditMessage::Flag::f_no_webpage
|
||||
: emptyFlag)
|
||||
| ((!webpage.removed && !webpage.url.isEmpty())
|
||||
? MTPmessages_EditMessage::Flag::f_media
|
||||
: emptyFlag)
|
||||
| ((!webpage.removed && !webpage.url.isEmpty() && webpage.invert)
|
||||
? MTPmessages_EditMessage::Flag::f_invert_media
|
||||
: emptyFlag)
|
||||
| (!sentEntities.v.isEmpty()
|
||||
? MTPmessages_EditMessage::Flag::f_entities
|
||||
: emptyFlag)
|
||||
@@ -89,7 +98,7 @@ mtpRequestId EditMessage(
|
||||
item->history()->peer->input,
|
||||
MTP_int(id),
|
||||
MTP_string(text),
|
||||
inputMedia.value_or(MTPInputMedia()),
|
||||
inputMedia.value_or(Data::WebPageForMTP(webpage, text.isEmpty())),
|
||||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(options.scheduled)
|
||||
@@ -133,9 +142,15 @@ mtpRequestId EditMessage(
|
||||
FailCallback &&fail,
|
||||
std::optional<MTPInputMedia> inputMedia = std::nullopt) {
|
||||
const auto &text = item->originalText();
|
||||
const auto webpage = (!item->media() || !item->media()->webpage())
|
||||
? Data::WebPageDraft{ .removed = true }
|
||||
: Data::WebPageDraft{
|
||||
.id = item->media()->webpage()->id,
|
||||
};
|
||||
return EditMessage(
|
||||
item,
|
||||
text,
|
||||
webpage,
|
||||
options,
|
||||
std::forward<DoneCallback>(done),
|
||||
std::forward<FailCallback>(fail),
|
||||
@@ -216,12 +231,19 @@ mtpRequestId EditCaption(
|
||||
SendOptions options,
|
||||
Fn<void()> done,
|
||||
Fn<void(const QString &)> fail) {
|
||||
return EditMessage(item, caption, options, done, fail);
|
||||
return EditMessage(
|
||||
item,
|
||||
caption,
|
||||
Data::WebPageDraft(),
|
||||
options,
|
||||
done,
|
||||
fail);
|
||||
}
|
||||
|
||||
mtpRequestId EditTextMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities &caption,
|
||||
Data::WebPageDraft webpage,
|
||||
SendOptions options,
|
||||
Fn<void(mtpRequestId requestId)> done,
|
||||
Fn<void(const QString &, mtpRequestId requestId)> fail) {
|
||||
@@ -229,7 +251,7 @@ mtpRequestId EditTextMessage(
|
||||
applyUpdates();
|
||||
done(id);
|
||||
};
|
||||
return EditMessage(item, caption, options, callback, fail);
|
||||
return EditMessage(item, caption, webpage, options, callback, fail);
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
||||
@@ -9,6 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
class HistoryItem;
|
||||
|
||||
namespace Data {
|
||||
struct WebPageDraft;
|
||||
} // namespace Data
|
||||
|
||||
namespace MTP {
|
||||
class Error;
|
||||
} // namespace MTP
|
||||
@@ -48,6 +52,7 @@ mtpRequestId EditCaption(
|
||||
mtpRequestId EditTextMessage(
|
||||
not_null<HistoryItem*> item,
|
||||
const TextWithEntities &caption,
|
||||
Data::WebPageDraft webpage,
|
||||
SendOptions options,
|
||||
Fn<void(mtpRequestId requestId)> done,
|
||||
Fn<void(const QString &error, mtpRequestId requestId)> fail);
|
||||
|
||||
@@ -510,40 +510,57 @@ void PeerPhoto::requestUserPhotos(
|
||||
_userPhotosRequests.emplace(user, requestId);
|
||||
}
|
||||
|
||||
auto PeerPhoto::emojiList(EmojiListType type) -> EmojiListData & {
|
||||
switch (type) {
|
||||
case EmojiListType::Profile: return _profileEmojiList;
|
||||
case EmojiListType::Group: return _groupEmojiList;
|
||||
case EmojiListType::Background: return _backgroundEmojiList;
|
||||
}
|
||||
Unexpected("Type in PeerPhoto::emojiList.");
|
||||
}
|
||||
|
||||
auto PeerPhoto::emojiList(EmojiListType type) const
|
||||
-> const EmojiListData & {
|
||||
return const_cast<PeerPhoto*>(this)->emojiList(type);
|
||||
}
|
||||
|
||||
void PeerPhoto::requestEmojiList(EmojiListType type) {
|
||||
if (_requestIdEmojiList) {
|
||||
auto &list = emojiList(type);
|
||||
if (list.requestId) {
|
||||
return;
|
||||
}
|
||||
const auto isGroup = (type == EmojiListType::Group);
|
||||
const auto d = [=](const MTPEmojiList &result) {
|
||||
_requestIdEmojiList = 0;
|
||||
result.match([](const MTPDemojiListNotModified &data) {
|
||||
}, [&](const MTPDemojiList &data) {
|
||||
auto &list = isGroup ? _profileEmojiList : _groupEmojiList;
|
||||
list = ranges::views::all(
|
||||
data.vdocument_id().v
|
||||
) | ranges::views::transform(&MTPlong::v) | ranges::to_vector;
|
||||
});
|
||||
const auto send = [&](auto &&request) {
|
||||
return _api.request(
|
||||
std::move(request)
|
||||
).done([=](const MTPEmojiList &result) {
|
||||
auto &list = emojiList(type);
|
||||
list.requestId = 0;
|
||||
result.match([](const MTPDemojiListNotModified &data) {
|
||||
}, [&](const MTPDemojiList &data) {
|
||||
list.list = ranges::views::all(
|
||||
data.vdocument_id().v
|
||||
) | ranges::views::transform(
|
||||
&MTPlong::v
|
||||
) | ranges::to_vector;
|
||||
});
|
||||
}).fail([=] {
|
||||
emojiList(type).requestId = 0;
|
||||
}).send();
|
||||
};
|
||||
const auto f = [=] { _requestIdEmojiList = 0; };
|
||||
_requestIdEmojiList = isGroup
|
||||
? _api.request(
|
||||
MTPaccount_GetDefaultGroupPhotoEmojis()
|
||||
).done(d).fail(f).send()
|
||||
: _api.request(
|
||||
MTPaccount_GetDefaultProfilePhotoEmojis()
|
||||
).done(d).fail(f).send();
|
||||
list.requestId = (type == EmojiListType::Profile)
|
||||
? send(MTPaccount_GetDefaultProfilePhotoEmojis())
|
||||
: (type == EmojiListType::Group)
|
||||
? send(MTPaccount_GetDefaultGroupPhotoEmojis())
|
||||
: send(MTPaccount_GetDefaultBackgroundEmojis());
|
||||
}
|
||||
|
||||
rpl::producer<PeerPhoto::EmojiList> PeerPhoto::emojiListValue(
|
||||
EmojiListType type) {
|
||||
auto &list = (type == EmojiListType::Group)
|
||||
? _profileEmojiList
|
||||
: _groupEmojiList;
|
||||
if (list.current().empty() && !_requestIdEmojiList) {
|
||||
auto &list = emojiList(type);
|
||||
if (list.list.current().empty() && !list.requestId) {
|
||||
requestEmojiList(type);
|
||||
}
|
||||
return list.value();
|
||||
return list.list.value();
|
||||
}
|
||||
|
||||
// Non-personal photo in case a personal photo is set.
|
||||
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
enum class EmojiListType {
|
||||
Profile,
|
||||
Group,
|
||||
Background,
|
||||
};
|
||||
|
||||
struct UserPhoto {
|
||||
@@ -73,6 +74,10 @@ private:
|
||||
Suggestion,
|
||||
Fallback,
|
||||
};
|
||||
struct EmojiListData {
|
||||
rpl::variable<EmojiList> list;
|
||||
mtpRequestId requestId = 0;
|
||||
};
|
||||
|
||||
void ready(
|
||||
const FullMsgId &msgId,
|
||||
@@ -84,6 +89,9 @@ private:
|
||||
UploadType type,
|
||||
Fn<void()> done);
|
||||
|
||||
[[nodiscard]] EmojiListData &emojiList(EmojiListType type);
|
||||
[[nodiscard]] const EmojiListData &emojiList(EmojiListType type) const;
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
MTP::Sender _api;
|
||||
|
||||
@@ -101,9 +109,9 @@ private:
|
||||
not_null<UserData*>,
|
||||
not_null<PhotoData*>> _nonPersonalPhotos;
|
||||
|
||||
mtpRequestId _requestIdEmojiList = 0;
|
||||
rpl::variable<EmojiList> _profileEmojiList;
|
||||
rpl::variable<EmojiList> _groupEmojiList;
|
||||
EmojiListData _profileEmojiList;
|
||||
EmojiListData _groupEmojiList;
|
||||
EmojiListData _backgroundEmojiList;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ void Polls::create(
|
||||
|
||||
const auto history = action.history;
|
||||
const auto peer = history->peer;
|
||||
const auto topicRootId = action.replyTo.msgId
|
||||
const auto topicRootId = action.replyTo.messageId
|
||||
? action.replyTo.topicRootId
|
||||
: 0;
|
||||
auto sendFlags = MTPmessages_SendMedia::Flags(0);
|
||||
|
||||
@@ -9,14 +9,52 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "api/api_premium_option.h"
|
||||
#include "api/api_text_entities.h"
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "apiwrap.h"
|
||||
#include "base/random.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_session.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_app_config.h"
|
||||
#include "main/main_session.h"
|
||||
#include "payments/payments_form.h"
|
||||
#include "ui/text/format_values.h"
|
||||
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] GiftCode Parse(const MTPDpayments_checkedGiftCode &data) {
|
||||
return {
|
||||
.from = peerFromMTP(data.vfrom_id()),
|
||||
.to = data.vto_id() ? peerFromUser(*data.vto_id()) : PeerId(),
|
||||
.giveawayId = data.vgiveaway_msg_id().value_or_empty(),
|
||||
.date = data.vdate().v,
|
||||
.used = data.vused_date().value_or_empty(),
|
||||
.months = data.vmonths().v,
|
||||
.giveaway = data.is_via_giveaway(),
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] Data::SubscriptionOptions GiftCodesFromTL(
|
||||
const QVector<MTPPremiumGiftCodeOption> &tlOptions) {
|
||||
auto options = SubscriptionOptionsFromTL(tlOptions);
|
||||
for (auto i = 0; i < options.size(); i++) {
|
||||
const auto &tlOption = tlOptions[i].data();
|
||||
const auto perUserText = Ui::FillAmountAndCurrency(
|
||||
tlOption.vamount().v / float64(tlOption.vusers().v),
|
||||
qs(tlOption.vcurrency()),
|
||||
false);
|
||||
options[i].costPerMonth = perUserText
|
||||
+ ' '
|
||||
+ QChar(0x00D7)
|
||||
+ ' '
|
||||
+ QString::number(tlOption.vusers().v);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Premium::Premium(not_null<ApiWrap*> api)
|
||||
: _session(&api->session())
|
||||
@@ -183,8 +221,278 @@ void Premium::reloadCloudSet() {
|
||||
}).send();
|
||||
}
|
||||
|
||||
void Premium::checkGiftCode(
|
||||
const QString &slug,
|
||||
Fn<void(GiftCode)> done) {
|
||||
if (_giftCodeRequestId) {
|
||||
if (_giftCodeSlug == slug) {
|
||||
return;
|
||||
}
|
||||
_api.request(_giftCodeRequestId).cancel();
|
||||
}
|
||||
_giftCodeSlug = slug;
|
||||
_giftCodeRequestId = _api.request(MTPpayments_CheckGiftCode(
|
||||
MTP_string(slug)
|
||||
)).done([=](const MTPpayments_CheckedGiftCode &result) {
|
||||
_giftCodeRequestId = 0;
|
||||
|
||||
const auto &data = result.data();
|
||||
_session->data().processUsers(data.vusers());
|
||||
_session->data().processChats(data.vchats());
|
||||
done(updateGiftCode(slug, Parse(data)));
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_giftCodeRequestId = 0;
|
||||
|
||||
done(updateGiftCode(slug, {}));
|
||||
}).send();
|
||||
}
|
||||
|
||||
GiftCode Premium::updateGiftCode(
|
||||
const QString &slug,
|
||||
const GiftCode &code) {
|
||||
auto &now = _giftCodes[slug];
|
||||
if (now != code) {
|
||||
now = code;
|
||||
_giftCodeUpdated.fire_copy(slug);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
rpl::producer<GiftCode> Premium::giftCodeValue(const QString &slug) const {
|
||||
return _giftCodeUpdated.events_starting_with_copy(
|
||||
slug
|
||||
) | rpl::filter(rpl::mappers::_1 == slug) | rpl::map([=] {
|
||||
const auto i = _giftCodes.find(slug);
|
||||
return (i != end(_giftCodes)) ? i->second : GiftCode();
|
||||
});
|
||||
}
|
||||
|
||||
void Premium::applyGiftCode(const QString &slug, Fn<void(QString)> done) {
|
||||
_api.request(MTPpayments_ApplyGiftCode(
|
||||
MTP_string(slug)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
_session->api().applyUpdates(result);
|
||||
done({});
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
done(error.type());
|
||||
}).send();
|
||||
}
|
||||
|
||||
void Premium::resolveGiveawayInfo(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId messageId,
|
||||
Fn<void(GiveawayInfo)> done) {
|
||||
Expects(done != nullptr);
|
||||
|
||||
_giveawayInfoDone = std::move(done);
|
||||
if (_giveawayInfoRequestId) {
|
||||
if (_giveawayInfoPeer == peer
|
||||
&& _giveawayInfoMessageId == messageId) {
|
||||
return;
|
||||
}
|
||||
_api.request(_giveawayInfoRequestId).cancel();
|
||||
}
|
||||
_giveawayInfoPeer = peer;
|
||||
_giveawayInfoMessageId = messageId;
|
||||
_giveawayInfoRequestId = _api.request(MTPpayments_GetGiveawayInfo(
|
||||
_giveawayInfoPeer->input,
|
||||
MTP_int(_giveawayInfoMessageId.bare)
|
||||
)).done([=](const MTPpayments_GiveawayInfo &result) {
|
||||
_giveawayInfoRequestId = 0;
|
||||
|
||||
auto info = GiveawayInfo();
|
||||
result.match([&](const MTPDpayments_giveawayInfo &data) {
|
||||
info.participating = data.is_participating();
|
||||
info.state = data.is_preparing_results()
|
||||
? GiveawayState::Preparing
|
||||
: GiveawayState::Running;
|
||||
info.adminChannelId = data.vadmin_disallowed_chat_id()
|
||||
? ChannelId(*data.vadmin_disallowed_chat_id())
|
||||
: ChannelId();
|
||||
info.disallowedCountry = qs(
|
||||
data.vdisallowed_country().value_or_empty());
|
||||
info.tooEarlyDate
|
||||
= data.vjoined_too_early_date().value_or_empty();
|
||||
info.startDate = data.vstart_date().v;
|
||||
}, [&](const MTPDpayments_giveawayInfoResults &data) {
|
||||
info.state = data.is_refunded()
|
||||
? GiveawayState::Refunded
|
||||
: GiveawayState::Finished;
|
||||
info.giftCode = qs(data.vgift_code_slug().value_or_empty());
|
||||
info.activatedCount = data.vactivated_count().v;
|
||||
info.finishDate = data.vfinish_date().v;
|
||||
info.startDate = data.vstart_date().v;
|
||||
});
|
||||
_giveawayInfoDone(std::move(info));
|
||||
}).fail([=] {
|
||||
_giveawayInfoRequestId = 0;
|
||||
_giveawayInfoDone({});
|
||||
}).send();
|
||||
}
|
||||
|
||||
const Data::SubscriptionOptions &Premium::subscriptionOptions() const {
|
||||
return _subscriptionOptions;
|
||||
}
|
||||
|
||||
PremiumGiftCodeOptions::PremiumGiftCodeOptions(not_null<PeerData*> peer)
|
||||
: _peer(peer)
|
||||
, _api(&peer->session().api().instance()) {
|
||||
}
|
||||
|
||||
rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::request() {
|
||||
return [=](auto consumer) {
|
||||
auto lifetime = rpl::lifetime();
|
||||
const auto channel = _peer->asChannel();
|
||||
if (!channel) {
|
||||
return lifetime;
|
||||
}
|
||||
|
||||
using TLOption = MTPPremiumGiftCodeOption;
|
||||
_api.request(MTPpayments_GetPremiumGiftCodeOptions(
|
||||
MTP_flags(
|
||||
MTPpayments_GetPremiumGiftCodeOptions::Flag::f_boost_peer),
|
||||
_peer->input
|
||||
)).done([=](const MTPVector<TLOption> &result) {
|
||||
auto tlMapOptions = base::flat_map<Amount, QVector<TLOption>>();
|
||||
for (const auto &tlOption : result.v) {
|
||||
const auto &data = tlOption.data();
|
||||
tlMapOptions[data.vusers().v].push_back(tlOption);
|
||||
|
||||
const auto token = Token{ data.vusers().v, data.vmonths().v };
|
||||
_stores[token] = Store{
|
||||
.amount = data.vamount().v,
|
||||
.product = qs(data.vstore_product().value_or_empty()),
|
||||
.quantity = data.vstore_quantity().value_or_empty(),
|
||||
};
|
||||
if (!ranges::contains(_availablePresets, data.vusers().v)) {
|
||||
_availablePresets.push_back(data.vusers().v);
|
||||
}
|
||||
}
|
||||
for (const auto &[amount, tlOptions] : tlMapOptions) {
|
||||
if (amount == 1 && _optionsForOnePerson.currency.isEmpty()) {
|
||||
_optionsForOnePerson.currency = qs(
|
||||
tlOptions.front().data().vcurrency());
|
||||
for (const auto &option : tlOptions) {
|
||||
_optionsForOnePerson.months.push_back(
|
||||
option.data().vmonths().v);
|
||||
_optionsForOnePerson.totalCosts.push_back(
|
||||
option.data().vamount().v);
|
||||
}
|
||||
}
|
||||
_subscriptionOptions[amount] = GiftCodesFromTL(tlOptions);
|
||||
}
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
|
||||
return lifetime;
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::applyPrepaid(
|
||||
const Payments::InvoicePremiumGiftCode &invoice,
|
||||
uint64 prepaidId) {
|
||||
return [=](auto consumer) {
|
||||
auto lifetime = rpl::lifetime();
|
||||
const auto channel = _peer->asChannel();
|
||||
if (!channel) {
|
||||
return lifetime;
|
||||
}
|
||||
|
||||
_api.request(MTPpayments_LaunchPrepaidGiveaway(
|
||||
_peer->input,
|
||||
MTP_long(prepaidId),
|
||||
Payments::InvoicePremiumGiftCodeGiveawayToTL(invoice)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
_peer->session().api().applyUpdates(result);
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
|
||||
return lifetime;
|
||||
};
|
||||
}
|
||||
|
||||
const std::vector<int> &PremiumGiftCodeOptions::availablePresets() const {
|
||||
return _availablePresets;
|
||||
}
|
||||
|
||||
[[nodiscard]] int PremiumGiftCodeOptions::monthsFromPreset(int monthsIndex) {
|
||||
return _optionsForOnePerson.months[monthsIndex];
|
||||
}
|
||||
|
||||
Payments::InvoicePremiumGiftCode PremiumGiftCodeOptions::invoice(
|
||||
int users,
|
||||
int months) {
|
||||
const auto randomId = base::RandomValue<uint64>();
|
||||
const auto token = Token{ users, months };
|
||||
const auto &store = _stores[token];
|
||||
return Payments::InvoicePremiumGiftCode{
|
||||
.randomId = randomId,
|
||||
.currency = _optionsForOnePerson.currency,
|
||||
.amount = store.amount,
|
||||
.storeProduct = store.product,
|
||||
.storeQuantity = store.quantity,
|
||||
.users = token.users,
|
||||
.months = token.months,
|
||||
};
|
||||
}
|
||||
|
||||
Data::SubscriptionOptions PremiumGiftCodeOptions::options(int amount) {
|
||||
const auto it = _subscriptionOptions.find(amount);
|
||||
if (it != end(_subscriptionOptions)) {
|
||||
return it->second;
|
||||
} else {
|
||||
auto tlOptions = QVector<MTPPremiumGiftCodeOption>();
|
||||
for (auto i = 0; i < _optionsForOnePerson.months.size(); i++) {
|
||||
tlOptions.push_back(MTP_premiumGiftCodeOption(
|
||||
MTP_flags(MTPDpremiumGiftCodeOption::Flags(0)),
|
||||
MTP_int(amount),
|
||||
MTP_int(_optionsForOnePerson.months[i]),
|
||||
MTPstring(),
|
||||
MTPint(),
|
||||
MTP_string(_optionsForOnePerson.currency),
|
||||
MTP_long(_optionsForOnePerson.totalCosts[i] * amount)));
|
||||
}
|
||||
_subscriptionOptions[amount] = GiftCodesFromTL(tlOptions);
|
||||
return _subscriptionOptions[amount];
|
||||
}
|
||||
}
|
||||
|
||||
int PremiumGiftCodeOptions::giveawayBoostsPerPremium() const {
|
||||
constexpr auto kFallbackCount = 4;
|
||||
return _peer->session().account().appConfig().get<int>(
|
||||
u"giveaway_boosts_per_premium"_q,
|
||||
kFallbackCount);
|
||||
}
|
||||
|
||||
int PremiumGiftCodeOptions::giveawayCountriesMax() const {
|
||||
constexpr auto kFallbackCount = 10;
|
||||
return _peer->session().account().appConfig().get<int>(
|
||||
u"giveaway_countries_max"_q,
|
||||
kFallbackCount);
|
||||
}
|
||||
|
||||
int PremiumGiftCodeOptions::giveawayAddPeersMax() const {
|
||||
constexpr auto kFallbackCount = 10;
|
||||
return _peer->session().account().appConfig().get<int>(
|
||||
u"giveaway_add_peers_max"_q,
|
||||
kFallbackCount);
|
||||
}
|
||||
|
||||
int PremiumGiftCodeOptions::giveawayPeriodMax() const {
|
||||
constexpr auto kFallbackCount = 3600 * 24 * 7;
|
||||
return _peer->session().account().appConfig().get<int>(
|
||||
u"giveaway_period_max"_q,
|
||||
kFallbackCount);
|
||||
}
|
||||
|
||||
bool PremiumGiftCodeOptions::giveawayGiftsPurchaseAvailable() const {
|
||||
return _peer->session().account().appConfig().get<bool>(
|
||||
u"giveaway_gifts_purchase_available"_q,
|
||||
false);
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
||||
@@ -16,8 +16,55 @@ namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
||||
namespace Payments {
|
||||
struct InvoicePremiumGiftCode;
|
||||
} // namespace Payments
|
||||
|
||||
namespace Api {
|
||||
|
||||
struct GiftCode {
|
||||
PeerId from = 0;
|
||||
PeerId to = 0;
|
||||
MsgId giveawayId = 0;
|
||||
TimeId date = 0;
|
||||
TimeId used = 0; // 0 if not used.
|
||||
int months = 0;
|
||||
bool giveaway = false;
|
||||
|
||||
explicit operator bool() const {
|
||||
return months != 0;
|
||||
}
|
||||
|
||||
friend inline bool operator==(
|
||||
const GiftCode&,
|
||||
const GiftCode&) = default;
|
||||
};
|
||||
|
||||
enum class GiveawayState {
|
||||
Invalid,
|
||||
Running,
|
||||
Preparing,
|
||||
Finished,
|
||||
Refunded,
|
||||
};
|
||||
|
||||
struct GiveawayInfo {
|
||||
QString giftCode;
|
||||
QString disallowedCountry;
|
||||
ChannelId adminChannelId = 0;
|
||||
GiveawayState state = GiveawayState::Invalid;
|
||||
TimeId tooEarlyDate = 0;
|
||||
TimeId finishDate = 0;
|
||||
TimeId startDate = 0;
|
||||
int winnersCount = 0;
|
||||
int activatedCount = 0;
|
||||
bool participating = false;
|
||||
|
||||
explicit operator bool() const {
|
||||
return state != GiveawayState::Invalid;
|
||||
}
|
||||
};
|
||||
|
||||
class Premium final {
|
||||
public:
|
||||
explicit Premium(not_null<ApiWrap*> api);
|
||||
@@ -40,6 +87,19 @@ public:
|
||||
[[nodiscard]] int64 monthlyAmount() const;
|
||||
[[nodiscard]] QString monthlyCurrency() const;
|
||||
|
||||
void checkGiftCode(
|
||||
const QString &slug,
|
||||
Fn<void(GiftCode)> done);
|
||||
GiftCode updateGiftCode(const QString &slug, const GiftCode &code);
|
||||
[[nodiscard]] rpl::producer<GiftCode> giftCodeValue(
|
||||
const QString &slug) const;
|
||||
void applyGiftCode(const QString &slug, Fn<void(QString)> done);
|
||||
|
||||
void resolveGiveawayInfo(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId messageId,
|
||||
Fn<void(GiveawayInfo)> done);
|
||||
|
||||
[[nodiscard]] auto subscriptionOptions() const
|
||||
-> const Data::SubscriptionOptions &;
|
||||
|
||||
@@ -71,8 +131,69 @@ private:
|
||||
int64 _monthlyAmount = 0;
|
||||
QString _monthlyCurrency;
|
||||
|
||||
mtpRequestId _giftCodeRequestId = 0;
|
||||
QString _giftCodeSlug;
|
||||
base::flat_map<QString, GiftCode> _giftCodes;
|
||||
rpl::event_stream<QString> _giftCodeUpdated;
|
||||
|
||||
mtpRequestId _giveawayInfoRequestId = 0;
|
||||
PeerData *_giveawayInfoPeer = nullptr;
|
||||
MsgId _giveawayInfoMessageId = 0;
|
||||
Fn<void(GiveawayInfo)> _giveawayInfoDone;
|
||||
|
||||
Data::SubscriptionOptions _subscriptionOptions;
|
||||
|
||||
};
|
||||
|
||||
class PremiumGiftCodeOptions final {
|
||||
public:
|
||||
PremiumGiftCodeOptions(not_null<PeerData*> peer);
|
||||
|
||||
[[nodiscard]] rpl::producer<rpl::no_value, QString> request();
|
||||
[[nodiscard]] Data::SubscriptionOptions options(int amount);
|
||||
[[nodiscard]] const std::vector<int> &availablePresets() const;
|
||||
[[nodiscard]] int monthsFromPreset(int monthsIndex);
|
||||
[[nodiscard]] Payments::InvoicePremiumGiftCode invoice(
|
||||
int users,
|
||||
int months);
|
||||
[[nodiscard]] rpl::producer<rpl::no_value, QString> applyPrepaid(
|
||||
const Payments::InvoicePremiumGiftCode &invoice,
|
||||
uint64 prepaidId);
|
||||
|
||||
[[nodiscard]] int giveawayBoostsPerPremium() const;
|
||||
[[nodiscard]] int giveawayCountriesMax() const;
|
||||
[[nodiscard]] int giveawayAddPeersMax() const;
|
||||
[[nodiscard]] int giveawayPeriodMax() const;
|
||||
[[nodiscard]] bool giveawayGiftsPurchaseAvailable() const;
|
||||
|
||||
private:
|
||||
struct Token final {
|
||||
int users = 0;
|
||||
int months = 0;
|
||||
|
||||
friend inline constexpr auto operator<=>(Token, Token) = default;
|
||||
|
||||
};
|
||||
struct Store final {
|
||||
uint64 amount = 0;
|
||||
QString product;
|
||||
int quantity = 0;
|
||||
};
|
||||
using Amount = int;
|
||||
const not_null<PeerData*> _peer;
|
||||
base::flat_map<Amount, Data::SubscriptionOptions> _subscriptionOptions;
|
||||
struct {
|
||||
std::vector<int> months;
|
||||
std::vector<float64> totalCosts;
|
||||
QString currency;
|
||||
} _optionsForOnePerson;
|
||||
|
||||
std::vector<int> _availablePresets;
|
||||
|
||||
base::flat_map<Token, Store> _stores;
|
||||
|
||||
MTP::Sender _api;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Api
|
||||
|
||||
@@ -36,7 +36,10 @@ template<typename Option>
|
||||
result.reserve(tlOptions.size());
|
||||
for (const auto &tlOption : tlOptions) {
|
||||
const auto &option = tlOption.data();
|
||||
const auto botUrl = qs(option.vbot_url());
|
||||
auto botUrl = QString();
|
||||
if constexpr (!std::is_same_v<Option, MTPPremiumGiftCodeOption>) {
|
||||
botUrl = qs(option.vbot_url());
|
||||
}
|
||||
const auto months = option.vmonths().v;
|
||||
const auto amount = option.vamount().v;
|
||||
const auto currency = qs(option.vcurrency());
|
||||
|
||||
@@ -270,7 +270,6 @@ bool SendDice(MessageToSend &message) {
|
||||
flags |= MessageFlag::HasReplyInfo;
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
|
||||
}
|
||||
const auto replyHeader = NewMessageReplyHeader(message.action);
|
||||
const auto anonymousPost = peer->amAnonymous();
|
||||
const auto silentPost = ShouldSendSilent(peer, message.action.options);
|
||||
InnerFillMessagePostFlags(message.action.options, peer, flags);
|
||||
@@ -368,9 +367,9 @@ void SendConfirmedFile(
|
||||
|
||||
if (!isEditing) {
|
||||
const auto histories = &session->data().histories();
|
||||
file->to.replyTo.msgId = histories->convertTopicReplyToId(
|
||||
file->to.replyTo.messageId = histories->convertTopicReplyToId(
|
||||
history,
|
||||
file->to.replyTo.msgId);
|
||||
file->to.replyTo.messageId);
|
||||
file->to.replyTo.topicRootId = histories->convertTopicReplyToId(
|
||||
history,
|
||||
file->to.replyTo.topicRootId);
|
||||
@@ -399,7 +398,6 @@ void SendConfirmedFile(
|
||||
if (file->to.replyTo) {
|
||||
flags |= MessageFlag::HasReplyInfo;
|
||||
}
|
||||
const auto replyHeader = NewMessageReplyHeader(action);
|
||||
const auto anonymousPost = peer->amAnonymous();
|
||||
const auto silentPost = ShouldSendSilent(peer, file->to.options);
|
||||
FillMessagePostFlags(action, peer, flags);
|
||||
|
||||
@@ -0,0 +1,640 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "api/api_statistics.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "history/history.h"
|
||||
#include "main/main_session.h"
|
||||
#include "statistics/statistics_data_deserialize.h"
|
||||
|
||||
namespace Api {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] Data::StatisticalGraph StatisticalGraphFromTL(
|
||||
const MTPStatsGraph &tl) {
|
||||
return tl.match([&](const MTPDstatsGraph &d) {
|
||||
using namespace Statistic;
|
||||
const auto zoomToken = d.vzoom_token().has_value()
|
||||
? qs(*d.vzoom_token()).toUtf8()
|
||||
: QByteArray();
|
||||
return Data::StatisticalGraph{
|
||||
StatisticalChartFromJSON(qs(d.vjson().data().vdata()).toUtf8()),
|
||||
zoomToken,
|
||||
};
|
||||
}, [&](const MTPDstatsGraphAsync &data) {
|
||||
return Data::StatisticalGraph{
|
||||
.zoomToken = qs(data.vtoken()).toUtf8(),
|
||||
};
|
||||
}, [&](const MTPDstatsGraphError &data) {
|
||||
return Data::StatisticalGraph{ .error = qs(data.verror()) };
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] Data::StatisticalValue StatisticalValueFromTL(
|
||||
const MTPStatsAbsValueAndPrev &tl) {
|
||||
const auto current = tl.data().vcurrent().v;
|
||||
const auto previous = tl.data().vprevious().v;
|
||||
return Data::StatisticalValue{
|
||||
.value = current,
|
||||
.previousValue = previous,
|
||||
.growthRatePercentage = previous
|
||||
? std::abs((current - previous) / float64(previous) * 100.)
|
||||
: 0,
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] Data::ChannelStatistics ChannelStatisticsFromTL(
|
||||
const MTPDstats_broadcastStats &data) {
|
||||
const auto &tlUnmuted = data.venabled_notifications().data();
|
||||
const auto unmuted = (!tlUnmuted.vtotal().v)
|
||||
? 0.
|
||||
: std::clamp(
|
||||
tlUnmuted.vpart().v / tlUnmuted.vtotal().v * 100.,
|
||||
0.,
|
||||
100.);
|
||||
using Recent = MTPMessageInteractionCounters;
|
||||
auto recentMessages = ranges::views::all(
|
||||
data.vrecent_message_interactions().v
|
||||
) | ranges::views::transform([&](const Recent &tl) {
|
||||
return Data::StatisticsMessageInteractionInfo{
|
||||
.messageId = tl.data().vmsg_id().v,
|
||||
.viewsCount = tl.data().vviews().v,
|
||||
.forwardsCount = tl.data().vforwards().v,
|
||||
};
|
||||
}) | ranges::to_vector;
|
||||
|
||||
return {
|
||||
.startDate = data.vperiod().data().vmin_date().v,
|
||||
.endDate = data.vperiod().data().vmax_date().v,
|
||||
|
||||
.memberCount = StatisticalValueFromTL(data.vfollowers()),
|
||||
.meanViewCount = StatisticalValueFromTL(data.vviews_per_post()),
|
||||
.meanShareCount = StatisticalValueFromTL(data.vshares_per_post()),
|
||||
|
||||
.enabledNotificationsPercentage = unmuted,
|
||||
|
||||
.memberCountGraph = StatisticalGraphFromTL(
|
||||
data.vgrowth_graph()),
|
||||
|
||||
.joinGraph = StatisticalGraphFromTL(
|
||||
data.vfollowers_graph()),
|
||||
|
||||
.muteGraph = StatisticalGraphFromTL(
|
||||
data.vmute_graph()),
|
||||
|
||||
.viewCountByHourGraph = StatisticalGraphFromTL(
|
||||
data.vtop_hours_graph()),
|
||||
|
||||
.viewCountBySourceGraph = StatisticalGraphFromTL(
|
||||
data.vviews_by_source_graph()),
|
||||
|
||||
.joinBySourceGraph = StatisticalGraphFromTL(
|
||||
data.vnew_followers_by_source_graph()),
|
||||
|
||||
.languageGraph = StatisticalGraphFromTL(
|
||||
data.vlanguages_graph()),
|
||||
|
||||
.messageInteractionGraph = StatisticalGraphFromTL(
|
||||
data.vinteractions_graph()),
|
||||
|
||||
.instantViewInteractionGraph = StatisticalGraphFromTL(
|
||||
data.viv_interactions_graph()),
|
||||
|
||||
.recentMessageInteractions = std::move(recentMessages),
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] Data::SupergroupStatistics SupergroupStatisticsFromTL(
|
||||
const MTPDstats_megagroupStats &data) {
|
||||
using Senders = MTPStatsGroupTopPoster;
|
||||
using Administrators = MTPStatsGroupTopAdmin;
|
||||
using Inviters = MTPStatsGroupTopInviter;
|
||||
|
||||
auto topSenders = ranges::views::all(
|
||||
data.vtop_posters().v
|
||||
) | ranges::views::transform([&](const Senders &tl) {
|
||||
return Data::StatisticsMessageSenderInfo{
|
||||
.userId = UserId(tl.data().vuser_id().v),
|
||||
.sentMessageCount = tl.data().vmessages().v,
|
||||
.averageCharacterCount = tl.data().vavg_chars().v,
|
||||
};
|
||||
}) | ranges::to_vector;
|
||||
auto topAdministrators = ranges::views::all(
|
||||
data.vtop_admins().v
|
||||
) | ranges::views::transform([&](const Administrators &tl) {
|
||||
return Data::StatisticsAdministratorActionsInfo{
|
||||
.userId = UserId(tl.data().vuser_id().v),
|
||||
.deletedMessageCount = tl.data().vdeleted().v,
|
||||
.bannedUserCount = tl.data().vkicked().v,
|
||||
.restrictedUserCount = tl.data().vbanned().v,
|
||||
};
|
||||
}) | ranges::to_vector;
|
||||
auto topInviters = ranges::views::all(
|
||||
data.vtop_inviters().v
|
||||
) | ranges::views::transform([&](const Inviters &tl) {
|
||||
return Data::StatisticsInviterInfo{
|
||||
.userId = UserId(tl.data().vuser_id().v),
|
||||
.addedMemberCount = tl.data().vinvitations().v,
|
||||
};
|
||||
}) | ranges::to_vector;
|
||||
|
||||
return {
|
||||
.startDate = data.vperiod().data().vmin_date().v,
|
||||
.endDate = data.vperiod().data().vmax_date().v,
|
||||
|
||||
.memberCount = StatisticalValueFromTL(data.vmembers()),
|
||||
.messageCount = StatisticalValueFromTL(data.vmessages()),
|
||||
.viewerCount = StatisticalValueFromTL(data.vviewers()),
|
||||
.senderCount = StatisticalValueFromTL(data.vposters()),
|
||||
|
||||
.memberCountGraph = StatisticalGraphFromTL(
|
||||
data.vgrowth_graph()),
|
||||
|
||||
.joinGraph = StatisticalGraphFromTL(
|
||||
data.vmembers_graph()),
|
||||
|
||||
.joinBySourceGraph = StatisticalGraphFromTL(
|
||||
data.vnew_members_by_source_graph()),
|
||||
|
||||
.languageGraph = StatisticalGraphFromTL(
|
||||
data.vlanguages_graph()),
|
||||
|
||||
.messageContentGraph = StatisticalGraphFromTL(
|
||||
data.vmessages_graph()),
|
||||
|
||||
.actionGraph = StatisticalGraphFromTL(
|
||||
data.vactions_graph()),
|
||||
|
||||
.dayGraph = StatisticalGraphFromTL(
|
||||
data.vtop_hours_graph()),
|
||||
|
||||
.weekGraph = StatisticalGraphFromTL(
|
||||
data.vweekdays_graph()),
|
||||
|
||||
.topSenders = std::move(topSenders),
|
||||
.topAdministrators = std::move(topAdministrators),
|
||||
.topInviters = std::move(topInviters),
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Statistics::Statistics(not_null<ApiWrap*> api)
|
||||
: _api(&api->instance()) {
|
||||
}
|
||||
|
||||
rpl::producer<rpl::no_value, QString> Statistics::request(
|
||||
not_null<PeerData*> peer) {
|
||||
return [=](auto consumer) {
|
||||
auto lifetime = rpl::lifetime();
|
||||
const auto channel = peer->asChannel();
|
||||
if (!channel) {
|
||||
return lifetime;
|
||||
}
|
||||
|
||||
if (!channel->isMegagroup()) {
|
||||
_api.request(MTPstats_GetBroadcastStats(
|
||||
MTP_flags(MTPstats_GetBroadcastStats::Flags(0)),
|
||||
channel->inputChannel
|
||||
)).done([=](const MTPstats_BroadcastStats &result) {
|
||||
_channelStats = ChannelStatisticsFromTL(result.data());
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
} else {
|
||||
_api.request(MTPstats_GetMegagroupStats(
|
||||
MTP_flags(MTPstats_GetMegagroupStats::Flags(0)),
|
||||
channel->inputChannel
|
||||
)).done([=](const MTPstats_MegagroupStats &result) {
|
||||
_supergroupStats = SupergroupStatisticsFromTL(result.data());
|
||||
peer->owner().processUsers(result.data().vusers());
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
}
|
||||
|
||||
return lifetime;
|
||||
};
|
||||
}
|
||||
|
||||
Statistics::GraphResult Statistics::requestZoom(
|
||||
not_null<PeerData*> peer,
|
||||
const QString &token,
|
||||
float64 x) {
|
||||
return [=](auto consumer) {
|
||||
auto lifetime = rpl::lifetime();
|
||||
const auto channel = peer->asChannel();
|
||||
if (!channel) {
|
||||
return lifetime;
|
||||
}
|
||||
const auto wasEmpty = _zoomDeque.empty();
|
||||
_zoomDeque.push_back([=] {
|
||||
_api.request(MTPstats_LoadAsyncGraph(
|
||||
MTP_flags(x
|
||||
? MTPstats_LoadAsyncGraph::Flag::f_x
|
||||
: MTPstats_LoadAsyncGraph::Flag(0)),
|
||||
MTP_string(token),
|
||||
MTP_long(x)
|
||||
)).done([=](const MTPStatsGraph &result) {
|
||||
consumer.put_next(StatisticalGraphFromTL(result));
|
||||
consumer.put_done();
|
||||
if (!_zoomDeque.empty()) {
|
||||
_zoomDeque.pop_front();
|
||||
if (!_zoomDeque.empty()) {
|
||||
_zoomDeque.front()();
|
||||
}
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
});
|
||||
if (wasEmpty) {
|
||||
_zoomDeque.front()();
|
||||
}
|
||||
|
||||
return lifetime;
|
||||
};
|
||||
}
|
||||
|
||||
Statistics::GraphResult Statistics::requestMessage(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId msgId) {
|
||||
return [=](auto consumer) {
|
||||
auto lifetime = rpl::lifetime();
|
||||
const auto channel = peer->asChannel();
|
||||
if (!channel) {
|
||||
return lifetime;
|
||||
}
|
||||
|
||||
_api.request(MTPstats_GetMessageStats(
|
||||
MTP_flags(MTPstats_GetMessageStats::Flags(0)),
|
||||
channel->inputChannel,
|
||||
MTP_int(msgId.bare)
|
||||
)).done([=](const MTPstats_MessageStats &result) {
|
||||
consumer.put_next(
|
||||
StatisticalGraphFromTL(result.data().vviews_graph()));
|
||||
consumer.put_done();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
|
||||
return lifetime;
|
||||
};
|
||||
}
|
||||
|
||||
Data::ChannelStatistics Statistics::channelStats() const {
|
||||
return _channelStats;
|
||||
}
|
||||
|
||||
Data::SupergroupStatistics Statistics::supergroupStats() const {
|
||||
return _supergroupStats;
|
||||
}
|
||||
|
||||
PublicForwards::PublicForwards(
|
||||
not_null<ChannelData*> channel,
|
||||
FullMsgId fullId)
|
||||
: _channel(channel)
|
||||
, _fullId(fullId)
|
||||
, _api(&channel->session().api().instance()) {
|
||||
}
|
||||
|
||||
void PublicForwards::request(
|
||||
const Data::PublicForwardsSlice::OffsetToken &token,
|
||||
Fn<void(Data::PublicForwardsSlice)> done) {
|
||||
if (_requestId) {
|
||||
return;
|
||||
}
|
||||
const auto offsetPeer = _channel->owner().peer(token.fullId.peer);
|
||||
const auto tlOffsetPeer = offsetPeer
|
||||
? offsetPeer->input
|
||||
: MTP_inputPeerEmpty();
|
||||
constexpr auto kLimit = tl::make_int(100);
|
||||
_requestId = _api.request(MTPstats_GetMessagePublicForwards(
|
||||
_channel->inputChannel,
|
||||
MTP_int(_fullId.msg),
|
||||
MTP_int(token.rate),
|
||||
tlOffsetPeer,
|
||||
MTP_int(token.fullId.msg),
|
||||
kLimit
|
||||
)).done([=, channel = _channel](const MTPmessages_Messages &result) {
|
||||
using Messages = QVector<FullMsgId>;
|
||||
_requestId = 0;
|
||||
|
||||
auto nextToken = Data::PublicForwardsSlice::OffsetToken();
|
||||
const auto process = [&](const MTPVector<MTPMessage> &messages) {
|
||||
auto result = Messages();
|
||||
for (const auto &message : messages.v) {
|
||||
const auto msgId = IdFromMessage(message);
|
||||
const auto peerId = PeerFromMessage(message);
|
||||
const auto lastDate = DateFromMessage(message);
|
||||
if (const auto peer = channel->owner().peerLoaded(peerId)) {
|
||||
if (lastDate) {
|
||||
channel->owner().addNewMessage(
|
||||
message,
|
||||
MessageFlags(),
|
||||
NewMessageType::Existing);
|
||||
nextToken.fullId = { peerId, msgId };
|
||||
result.push_back(nextToken.fullId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
auto allLoaded = false;
|
||||
auto fullCount = 0;
|
||||
auto messages = result.match([&](const MTPDmessages_messages &data) {
|
||||
channel->owner().processUsers(data.vusers());
|
||||
channel->owner().processChats(data.vchats());
|
||||
auto list = process(data.vmessages());
|
||||
allLoaded = true;
|
||||
fullCount = list.size();
|
||||
return list;
|
||||
}, [&](const MTPDmessages_messagesSlice &data) {
|
||||
channel->owner().processUsers(data.vusers());
|
||||
channel->owner().processChats(data.vchats());
|
||||
auto list = process(data.vmessages());
|
||||
|
||||
if (const auto nextRate = data.vnext_rate()) {
|
||||
const auto rateUpdated = (nextRate->v != token.rate);
|
||||
if (rateUpdated) {
|
||||
nextToken.rate = nextRate->v;
|
||||
} else {
|
||||
allLoaded = true;
|
||||
}
|
||||
}
|
||||
fullCount = data.vcount().v;
|
||||
return list;
|
||||
}, [&](const MTPDmessages_channelMessages &data) {
|
||||
channel->owner().processUsers(data.vusers());
|
||||
channel->owner().processChats(data.vchats());
|
||||
auto list = process(data.vmessages());
|
||||
allLoaded = true;
|
||||
fullCount = data.vcount().v;
|
||||
return list;
|
||||
}, [&](const MTPDmessages_messagesNotModified &) {
|
||||
allLoaded = true;
|
||||
return Messages();
|
||||
});
|
||||
|
||||
_lastTotal = std::max(_lastTotal, fullCount);
|
||||
done({
|
||||
.list = std::move(messages),
|
||||
.total = _lastTotal,
|
||||
.allLoaded = allLoaded,
|
||||
.token = nextToken,
|
||||
});
|
||||
}).fail([=] {
|
||||
_requestId = 0;
|
||||
}).send();
|
||||
}
|
||||
|
||||
MessageStatistics::MessageStatistics(
|
||||
not_null<ChannelData*> channel,
|
||||
FullMsgId fullId)
|
||||
: _publicForwards(channel, fullId)
|
||||
, _channel(channel)
|
||||
, _fullId(fullId)
|
||||
, _api(&channel->session().api().instance()) {
|
||||
}
|
||||
|
||||
Data::PublicForwardsSlice MessageStatistics::firstSlice() const {
|
||||
return _firstSlice;
|
||||
}
|
||||
|
||||
void MessageStatistics::request(Fn<void(Data::MessageStatistics)> done) {
|
||||
if (_channel->isMegagroup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto requestFirstPublicForwards = [=](
|
||||
const Data::StatisticalGraph &messageGraph,
|
||||
const Data::StatisticsMessageInteractionInfo &info) {
|
||||
_publicForwards.request({}, [=](Data::PublicForwardsSlice slice) {
|
||||
const auto total = slice.total;
|
||||
_firstSlice = std::move(slice);
|
||||
done({
|
||||
.messageInteractionGraph = messageGraph,
|
||||
.publicForwards = total,
|
||||
.privateForwards = info.forwardsCount - total,
|
||||
.views = info.viewsCount,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const auto requestPrivateForwards = [=](
|
||||
const Data::StatisticalGraph &messageGraph) {
|
||||
_api.request(MTPchannels_GetMessages(
|
||||
_channel->inputChannel,
|
||||
MTP_vector<MTPInputMessage>(
|
||||
1,
|
||||
MTP_inputMessageID(MTP_int(_fullId.msg))))
|
||||
).done([=](const MTPmessages_Messages &result) {
|
||||
const auto process = [&](const MTPVector<MTPMessage> &messages) {
|
||||
const auto &message = messages.v.front();
|
||||
return message.match([&](const MTPDmessage &data) {
|
||||
return Data::StatisticsMessageInteractionInfo{
|
||||
.messageId = IdFromMessage(message),
|
||||
.viewsCount = data.vviews()
|
||||
? data.vviews()->v
|
||||
: 0,
|
||||
.forwardsCount = data.vforwards()
|
||||
? data.vforwards()->v
|
||||
: 0,
|
||||
};
|
||||
}, [](const MTPDmessageEmpty &) {
|
||||
return Data::StatisticsMessageInteractionInfo();
|
||||
}, [](const MTPDmessageService &) {
|
||||
return Data::StatisticsMessageInteractionInfo();
|
||||
});
|
||||
};
|
||||
|
||||
auto info = result.match([&](const MTPDmessages_messages &data) {
|
||||
return process(data.vmessages());
|
||||
}, [&](const MTPDmessages_messagesSlice &data) {
|
||||
return process(data.vmessages());
|
||||
}, [&](const MTPDmessages_channelMessages &data) {
|
||||
return process(data.vmessages());
|
||||
}, [](const MTPDmessages_messagesNotModified &) {
|
||||
return Data::StatisticsMessageInteractionInfo();
|
||||
});
|
||||
|
||||
requestFirstPublicForwards(messageGraph, std::move(info));
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
requestFirstPublicForwards(messageGraph, {});
|
||||
}).send();
|
||||
};
|
||||
|
||||
_api.request(MTPstats_GetMessageStats(
|
||||
MTP_flags(MTPstats_GetMessageStats::Flags(0)),
|
||||
_channel->inputChannel,
|
||||
MTP_int(_fullId.msg.bare)
|
||||
)).done([=](const MTPstats_MessageStats &result) {
|
||||
requestPrivateForwards(
|
||||
StatisticalGraphFromTL(result.data().vviews_graph()));
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
requestPrivateForwards({});
|
||||
}).send();
|
||||
|
||||
}
|
||||
|
||||
Boosts::Boosts(not_null<PeerData*> peer)
|
||||
: _peer(peer)
|
||||
, _api(&peer->session().api().instance()) {
|
||||
}
|
||||
|
||||
rpl::producer<rpl::no_value, QString> Boosts::request() {
|
||||
return [=](auto consumer) {
|
||||
auto lifetime = rpl::lifetime();
|
||||
const auto channel = _peer->asChannel();
|
||||
if (!channel || channel->isMegagroup()) {
|
||||
return lifetime;
|
||||
}
|
||||
|
||||
_api.request(MTPpremium_GetBoostsStatus(
|
||||
_peer->input
|
||||
)).done([=](const MTPpremium_BoostsStatus &result) {
|
||||
const auto &data = result.data();
|
||||
const auto hasPremium = !!data.vpremium_audience();
|
||||
const auto premiumMemberCount = hasPremium
|
||||
? std::max(0, int(data.vpremium_audience()->data().vpart().v))
|
||||
: 0;
|
||||
const auto participantCount = hasPremium
|
||||
? std::max(
|
||||
int(data.vpremium_audience()->data().vtotal().v),
|
||||
premiumMemberCount)
|
||||
: 0;
|
||||
const auto premiumMemberPercentage = (participantCount > 0)
|
||||
? (100. * premiumMemberCount / participantCount)
|
||||
: 0;
|
||||
|
||||
const auto slots = data.vmy_boost_slots();
|
||||
_boostStatus.overview = Data::BoostsOverview{
|
||||
.mine = slots ? int(slots->v.size()) : 0,
|
||||
.level = std::max(data.vlevel().v, 0),
|
||||
.boostCount = std::max(
|
||||
data.vboosts().v,
|
||||
data.vcurrent_level_boosts().v),
|
||||
.currentLevelBoostCount = data.vcurrent_level_boosts().v,
|
||||
.nextLevelBoostCount = data.vnext_level_boosts()
|
||||
? data.vnext_level_boosts()->v
|
||||
: 0,
|
||||
.premiumMemberCount = premiumMemberCount,
|
||||
.premiumMemberPercentage = premiumMemberPercentage,
|
||||
};
|
||||
_boostStatus.link = qs(data.vboost_url());
|
||||
|
||||
if (data.vprepaid_giveaways()) {
|
||||
_boostStatus.prepaidGiveaway = ranges::views::all(
|
||||
data.vprepaid_giveaways()->v
|
||||
) | ranges::views::transform([](const MTPPrepaidGiveaway &r) {
|
||||
return Data::BoostPrepaidGiveaway{
|
||||
.months = r.data().vmonths().v,
|
||||
.id = r.data().vid().v,
|
||||
.quantity = r.data().vquantity().v,
|
||||
.date = QDateTime::fromSecsSinceEpoch(
|
||||
r.data().vdate().v),
|
||||
};
|
||||
}) | ranges::to_vector;
|
||||
}
|
||||
|
||||
using namespace Data;
|
||||
requestBoosts({ .gifts = false }, [=](BoostsListSlice &&slice) {
|
||||
_boostStatus.firstSliceBoosts = std::move(slice);
|
||||
requestBoosts({ .gifts = true }, [=](BoostsListSlice &&s) {
|
||||
_boostStatus.firstSliceGifts = std::move(s);
|
||||
consumer.put_done();
|
||||
});
|
||||
});
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
consumer.put_error_copy(error.type());
|
||||
}).send();
|
||||
|
||||
return lifetime;
|
||||
};
|
||||
}
|
||||
|
||||
void Boosts::requestBoosts(
|
||||
const Data::BoostsListSlice::OffsetToken &token,
|
||||
Fn<void(Data::BoostsListSlice)> done) {
|
||||
if (_requestId) {
|
||||
return;
|
||||
}
|
||||
constexpr auto kTlFirstSlice = tl::make_int(kFirstSlice);
|
||||
constexpr auto kTlLimit = tl::make_int(kLimit);
|
||||
const auto gifts = token.gifts;
|
||||
_requestId = _api.request(MTPpremium_GetBoostsList(
|
||||
gifts
|
||||
? MTP_flags(MTPpremium_GetBoostsList::Flag::f_gifts)
|
||||
: MTP_flags(0),
|
||||
_peer->input,
|
||||
MTP_string(token.next),
|
||||
token.next.isEmpty() ? kTlFirstSlice : kTlLimit
|
||||
)).done([=](const MTPpremium_BoostsList &result) {
|
||||
_requestId = 0;
|
||||
|
||||
const auto &data = result.data();
|
||||
_peer->owner().processUsers(data.vusers());
|
||||
|
||||
auto list = std::vector<Data::Boost>();
|
||||
list.reserve(data.vboosts().v.size());
|
||||
constexpr auto kMonthsDivider = int(30 * 86400);
|
||||
for (const auto &boost : data.vboosts().v) {
|
||||
const auto &data = boost.data();
|
||||
const auto path = data.vused_gift_slug()
|
||||
? (u"giftcode/"_q + qs(data.vused_gift_slug()->v))
|
||||
: QString();
|
||||
auto giftCodeLink = !path.isEmpty()
|
||||
? Data::GiftCodeLink{
|
||||
_peer->session().createInternalLink(path),
|
||||
_peer->session().createInternalLinkFull(path),
|
||||
qs(data.vused_gift_slug()->v),
|
||||
}
|
||||
: Data::GiftCodeLink();
|
||||
list.push_back({
|
||||
data.is_gift(),
|
||||
data.is_giveaway(),
|
||||
data.is_unclaimed(),
|
||||
qs(data.vid()),
|
||||
data.vuser_id().value_or_empty(),
|
||||
data.vgiveaway_msg_id()
|
||||
? FullMsgId{ _peer->id, data.vgiveaway_msg_id()->v }
|
||||
: FullMsgId(),
|
||||
QDateTime::fromSecsSinceEpoch(data.vdate().v),
|
||||
QDateTime::fromSecsSinceEpoch(data.vexpires().v),
|
||||
(data.vexpires().v - data.vdate().v) / kMonthsDivider,
|
||||
std::move(giftCodeLink),
|
||||
data.vmultiplier().value_or_empty(),
|
||||
});
|
||||
}
|
||||
done(Data::BoostsListSlice{
|
||||
.list = std::move(list),
|
||||
.multipliedTotal = data.vcount().v,
|
||||
.allLoaded = (data.vcount().v == data.vboosts().v.size()),
|
||||
.token = Data::BoostsListSlice::OffsetToken{
|
||||
.next = data.vnext_offset()
|
||||
? qs(*data.vnext_offset())
|
||||
: QString(),
|
||||
.gifts = gifts,
|
||||
},
|
||||
});
|
||||
}).fail([=] {
|
||||
_requestId = 0;
|
||||
}).send();
|
||||
}
|
||||
|
||||
Data::BoostStatus Boosts::boostStatus() const {
|
||||
return _boostStatus;
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "data/data_boosts.h"
|
||||
#include "data/data_statistics.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
class ApiWrap;
|
||||
class ChannelData;
|
||||
class PeerData;
|
||||
|
||||
namespace Api {
|
||||
|
||||
class Statistics final {
|
||||
public:
|
||||
explicit Statistics(not_null<ApiWrap*> api);
|
||||
|
||||
[[nodiscard]] rpl::producer<rpl::no_value, QString> request(
|
||||
not_null<PeerData*> peer);
|
||||
using GraphResult = rpl::producer<Data::StatisticalGraph, QString>;
|
||||
[[nodiscard]] GraphResult requestZoom(
|
||||
not_null<PeerData*> peer,
|
||||
const QString &token,
|
||||
float64 x);
|
||||
[[nodiscard]] GraphResult requestMessage(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId msgId);
|
||||
|
||||
[[nodiscard]] Data::ChannelStatistics channelStats() const;
|
||||
[[nodiscard]] Data::SupergroupStatistics supergroupStats() const;
|
||||
|
||||
private:
|
||||
Data::ChannelStatistics _channelStats;
|
||||
Data::SupergroupStatistics _supergroupStats;
|
||||
MTP::Sender _api;
|
||||
|
||||
std::deque<Fn<void()>> _zoomDeque;
|
||||
|
||||
};
|
||||
|
||||
class PublicForwards final {
|
||||
public:
|
||||
explicit PublicForwards(not_null<ChannelData*> channel, FullMsgId fullId);
|
||||
|
||||
void request(
|
||||
const Data::PublicForwardsSlice::OffsetToken &token,
|
||||
Fn<void(Data::PublicForwardsSlice)> done);
|
||||
|
||||
private:
|
||||
const not_null<ChannelData*> _channel;
|
||||
const FullMsgId _fullId;
|
||||
mtpRequestId _requestId = 0;
|
||||
int _lastTotal = 0;
|
||||
|
||||
MTP::Sender _api;
|
||||
|
||||
};
|
||||
|
||||
class MessageStatistics final {
|
||||
public:
|
||||
explicit MessageStatistics(
|
||||
not_null<ChannelData*> channel,
|
||||
FullMsgId fullId);
|
||||
|
||||
void request(Fn<void(Data::MessageStatistics)> done);
|
||||
|
||||
[[nodiscard]] Data::PublicForwardsSlice firstSlice() const;
|
||||
|
||||
private:
|
||||
PublicForwards _publicForwards;
|
||||
const not_null<ChannelData*> _channel;
|
||||
const FullMsgId _fullId;
|
||||
|
||||
Data::PublicForwardsSlice _firstSlice;
|
||||
|
||||
mtpRequestId _requestId = 0;
|
||||
MTP::Sender _api;
|
||||
|
||||
};
|
||||
|
||||
class Boosts final {
|
||||
public:
|
||||
explicit Boosts(not_null<PeerData*> peer);
|
||||
|
||||
[[nodiscard]] rpl::producer<rpl::no_value, QString> request();
|
||||
void requestBoosts(
|
||||
const Data::BoostsListSlice::OffsetToken &token,
|
||||
Fn<void(Data::BoostsListSlice)> done);
|
||||
|
||||
[[nodiscard]] Data::BoostStatus boostStatus() const;
|
||||
|
||||
static constexpr auto kFirstSlice = int(10);
|
||||
static constexpr auto kLimit = int(40);
|
||||
|
||||
private:
|
||||
const not_null<PeerData*> _peer;
|
||||
Data::BoostStatus _boostStatus;
|
||||
|
||||
MTP::Sender _api;
|
||||
mtpRequestId _requestId = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Api
|
||||
@@ -114,6 +114,7 @@ EntitiesInText EntitiesFromMTP(
|
||||
case mtpc_messageEntityStrike: { auto &d = entity.c_messageEntityStrike(); result.push_back({ EntityType::StrikeOut, d.voffset().v, d.vlength().v }); } break;
|
||||
case mtpc_messageEntityCode: { auto &d = entity.c_messageEntityCode(); result.push_back({ EntityType::Code, d.voffset().v, d.vlength().v }); } break;
|
||||
case mtpc_messageEntityPre: { auto &d = entity.c_messageEntityPre(); result.push_back({ EntityType::Pre, d.voffset().v, d.vlength().v, qs(d.vlanguage()) }); } break;
|
||||
case mtpc_messageEntityBlockquote: { auto &d = entity.c_messageEntityBlockquote(); result.push_back({ EntityType::Blockquote, d.voffset().v, d.vlength().v }); } break;
|
||||
case mtpc_messageEntityBankCard: break; // Skipping cards. // #TODO entities
|
||||
case mtpc_messageEntitySpoiler: { auto &d = entity.c_messageEntitySpoiler(); result.push_back({ EntityType::Spoiler, d.voffset().v, d.vlength().v }); } break;
|
||||
case mtpc_messageEntityCustomEmoji: {
|
||||
@@ -142,6 +143,7 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(
|
||||
&& entity.type() != EntityType::StrikeOut
|
||||
&& entity.type() != EntityType::Code // #TODO entities
|
||||
&& entity.type() != EntityType::Pre
|
||||
&& entity.type() != EntityType::Blockquote
|
||||
&& entity.type() != EntityType::Spoiler
|
||||
&& entity.type() != EntityType::MentionName
|
||||
&& entity.type() != EntityType::CustomUrl
|
||||
@@ -170,6 +172,7 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(
|
||||
case EntityType::StrikeOut: v.push_back(MTP_messageEntityStrike(offset, length)); break;
|
||||
case EntityType::Code: v.push_back(MTP_messageEntityCode(offset, length)); break; // #TODO entities
|
||||
case EntityType::Pre: v.push_back(MTP_messageEntityPre(offset, length, MTP_string(entity.data()))); break;
|
||||
case EntityType::Blockquote: v.push_back(MTP_messageEntityBlockquote(offset, length)); break;
|
||||
case EntityType::Spoiler: v.push_back(MTP_messageEntitySpoiler(offset, length)); break;
|
||||
case EntityType::CustomEmoji: {
|
||||
if (const auto valid = CustomEmojiEntity(offset, length, entity.data())) {
|
||||
|
||||
@@ -2103,7 +2103,10 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
||||
windows.front()->window().show(Ui::MakeInformBox(text));
|
||||
}
|
||||
} else {
|
||||
session().data().serviceNotification(text, d.vmedia());
|
||||
session().data().serviceNotification(
|
||||
text,
|
||||
d.vmedia(),
|
||||
d.is_invert_media());
|
||||
session().api().authorizations().reload();
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -2150,14 +2150,13 @@ void ApiWrap::saveDraftsToCloud() {
|
||||
|
||||
auto flags = MTPmessages_SaveDraft::Flags(0);
|
||||
auto &textWithTags = cloudDraft->textWithTags;
|
||||
if (cloudDraft->previewState != Data::PreviewState::Allowed) {
|
||||
if (cloudDraft->webpage.removed) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_no_webpage;
|
||||
} else if (!cloudDraft->webpage.url.isEmpty()) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_media;
|
||||
}
|
||||
if (cloudDraft->msgId) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_reply_to_msg_id;
|
||||
}
|
||||
if (cloudDraft->topicRootId) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_top_msg_id;
|
||||
if (cloudDraft->reply.messageId || cloudDraft->reply.topicRootId) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_reply_to;
|
||||
}
|
||||
if (!textWithTags.tags.isEmpty()) {
|
||||
flags |= MTPmessages_SaveDraft::Flag::f_entities;
|
||||
@@ -2170,11 +2169,13 @@ void ApiWrap::saveDraftsToCloud() {
|
||||
history->startSavingCloudDraft(topicRootId);
|
||||
cloudDraft->saveRequestId = request(MTPmessages_SaveDraft(
|
||||
MTP_flags(flags),
|
||||
MTP_int(cloudDraft->msgId),
|
||||
MTP_int(cloudDraft->topicRootId),
|
||||
ReplyToForMTP(history, cloudDraft->reply),
|
||||
history->peer->input,
|
||||
MTP_string(textWithTags.text),
|
||||
entities
|
||||
entities,
|
||||
Data::WebPageForMTP(
|
||||
cloudDraft->webpage,
|
||||
textWithTags.text.isEmpty())
|
||||
)).done([=](const MTPBool &result, const MTP::Response &response) {
|
||||
const auto requestId = response.requestId;
|
||||
history->finishSavingCloudDraft(
|
||||
@@ -2261,7 +2262,7 @@ void ApiWrap::gotStickerSet(
|
||||
}
|
||||
|
||||
void ApiWrap::requestWebPageDelayed(not_null<WebPageData*> page) {
|
||||
if (page->pendingTill <= 0) {
|
||||
if (page->failed || !page->pendingTill) {
|
||||
return;
|
||||
}
|
||||
_webPagesPending.emplace(page, 0);
|
||||
@@ -2566,7 +2567,8 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &resu
|
||||
for (auto i = _webPagesPending.begin(); i != _webPagesPending.cend();) {
|
||||
if (i->second == req) {
|
||||
if (i->first->pendingTill > 0) {
|
||||
i->first->pendingTill = -1;
|
||||
i->first->pendingTill = 0;
|
||||
i->first->failed = 1;
|
||||
_session->data().notifyWebPageUpdateDelayed(i->first);
|
||||
}
|
||||
i = _webPagesPending.erase(i);
|
||||
@@ -3389,7 +3391,6 @@ void ApiWrap::sendSharedContact(
|
||||
if (action.replyTo) {
|
||||
flags |= MessageFlag::HasReplyInfo;
|
||||
}
|
||||
const auto replyHeader = NewMessageReplyHeader(action);
|
||||
FillMessagePostFlags(action, peer, flags);
|
||||
if (action.options.scheduled) {
|
||||
flags |= MessageFlag::IsOrWasScheduled;
|
||||
@@ -3612,14 +3613,14 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
action.generateLocal = true;
|
||||
sendAction(action);
|
||||
|
||||
const auto replyToId = action.replyTo.msgId;
|
||||
const auto replyTo = replyToId
|
||||
? peer->owner().message(peer, replyToId)
|
||||
const auto clearCloudDraft = action.clearDraft;
|
||||
const auto replyTo = action.replyTo.messageId
|
||||
? peer->owner().message(action.replyTo.messageId)
|
||||
: nullptr;
|
||||
const auto topicRootId = replyTo
|
||||
? replyTo->topicRootId()
|
||||
: action.replyTo.topicRootId
|
||||
const auto topicRootId = action.replyTo.topicRootId
|
||||
? action.replyTo.topicRootId
|
||||
: replyTo
|
||||
? replyTo->topicRootId()
|
||||
: Data::ForumTopic::kGeneralId;
|
||||
const auto topic = peer->forumTopicFor(topicRootId);
|
||||
if (!(topic ? Data::CanSendTexts(topic) : Data::CanSendTexts(peer))
|
||||
@@ -3642,7 +3643,13 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
|
||||
auto &histories = history->owner().histories();
|
||||
|
||||
while (TextUtilities::CutPart(sending, left, MaxMessageSize)) {
|
||||
const auto exactWebPage = !message.webPage.url.isEmpty();
|
||||
auto isFirst = true;
|
||||
while (TextUtilities::CutPart(sending, left, MaxMessageSize)
|
||||
|| (isFirst && exactWebPage)) {
|
||||
TextUtilities::Trim(left);
|
||||
const auto isLast = left.empty();
|
||||
|
||||
auto newId = FullMsgId(
|
||||
peer->id,
|
||||
_session->data().nextLocalMessageId());
|
||||
@@ -3656,26 +3663,51 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
MTPstring msgText(MTP_string(sending.text));
|
||||
auto flags = NewMessageFlags(peer);
|
||||
auto sendFlags = MTPmessages_SendMessage::Flags(0);
|
||||
auto mediaFlags = MTPmessages_SendMedia::Flags(0);
|
||||
if (action.replyTo) {
|
||||
flags |= MessageFlag::HasReplyInfo;
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_reply_to;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
|
||||
}
|
||||
const auto replyHeader = NewMessageReplyHeader(action);
|
||||
const auto ignoreWebPage = message.webPage.removed
|
||||
|| (exactWebPage && !isLast);
|
||||
const auto manualWebPage = exactWebPage
|
||||
&& !ignoreWebPage
|
||||
&& (message.webPage.manual || (isLast && !isFirst));
|
||||
MTPMessageMedia media = MTP_messageMediaEmpty();
|
||||
if (message.webPageId == CancelledWebPageId) {
|
||||
if (ignoreWebPage) {
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_no_webpage;
|
||||
} else if (message.webPageId) {
|
||||
auto page = _session->data().webpage(message.webPageId);
|
||||
} else if (exactWebPage) {
|
||||
using PageFlag = MTPDmessageMediaWebPage::Flag;
|
||||
using PendingFlag = MTPDwebPagePending::Flag;
|
||||
const auto &fields = message.webPage;
|
||||
const auto page = _session->data().webpage(fields.id);
|
||||
media = MTP_messageMediaWebPage(
|
||||
MTP_flags(PageFlag()
|
||||
| (manualWebPage ? PageFlag::f_manual : PageFlag())
|
||||
| (fields.forceLargeMedia
|
||||
? PageFlag::f_force_large_media
|
||||
: PageFlag())
|
||||
| (fields.forceSmallMedia
|
||||
? PageFlag::f_force_small_media
|
||||
: PageFlag())),
|
||||
MTP_webPagePending(
|
||||
MTP_long(page->id),
|
||||
MTP_flags(PendingFlag::f_url),
|
||||
MTP_long(fields.id),
|
||||
MTP_string(fields.url),
|
||||
MTP_int(page->pendingTill)));
|
||||
}
|
||||
const auto anonymousPost = peer->amAnonymous();
|
||||
const auto silentPost = ShouldSendSilent(peer, action.options);
|
||||
FillMessagePostFlags(action, peer, flags);
|
||||
if (exactWebPage && !ignoreWebPage && message.webPage.invert) {
|
||||
flags |= MessageFlag::InvertMedia;
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_invert_media;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
|
||||
}
|
||||
if (silentPost) {
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_silent;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_silent;
|
||||
}
|
||||
const auto sentEntities = Api::EntitiesToMTP(
|
||||
_session,
|
||||
@@ -3683,11 +3715,11 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
Api::ConvertOption::SkipLocal);
|
||||
if (!sentEntities.v.isEmpty()) {
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_entities;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_entities;
|
||||
}
|
||||
const auto clearCloudDraft = action.clearDraft;
|
||||
const auto topicRootId = action.replyTo.topicRootId;
|
||||
if (clearCloudDraft) {
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_clear_draft;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_clear_draft;
|
||||
history->clearCloudDraft(topicRootId);
|
||||
history->startSavingCloudDraft(topicRootId);
|
||||
}
|
||||
@@ -3699,6 +3731,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
: _session->userPeerId();
|
||||
if (sendAs) {
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_send_as;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_send_as;
|
||||
}
|
||||
const auto messagePostAuthor = peer->isBroadcast()
|
||||
? _session->user()->name()
|
||||
@@ -3706,6 +3739,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
if (action.options.scheduled) {
|
||||
flags |= MessageFlag::IsOrWasScheduled;
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_schedule_date;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
|
||||
}
|
||||
const auto viaBotId = UserId();
|
||||
lastMessage = history->addNewLocalMessage(
|
||||
@@ -3719,27 +3753,18 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
sending,
|
||||
media,
|
||||
HistoryMessageMarkupData());
|
||||
histories.sendPreparedMessage(
|
||||
history,
|
||||
action.replyTo,
|
||||
randomId,
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMessage>(
|
||||
MTP_flags(sendFlags),
|
||||
peer->input,
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
msgText,
|
||||
MTP_long(randomId),
|
||||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
const auto done = [=](
|
||||
const MTPUpdates &result,
|
||||
const MTP::Response &response) {
|
||||
if (clearCloudDraft) {
|
||||
history->finishSavingCloudDraft(
|
||||
topicRootId,
|
||||
UnixtimeFromMsgId(response.outerMsgId));
|
||||
}
|
||||
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
||||
};
|
||||
const auto fail = [=](
|
||||
const MTP::Error &error,
|
||||
const MTP::Response &response) {
|
||||
if (error.type() == u"MESSAGE_EMPTY"_q) {
|
||||
lastMessage->destroy();
|
||||
} else {
|
||||
@@ -3750,7 +3775,44 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
||||
topicRootId,
|
||||
UnixtimeFromMsgId(response.outerMsgId));
|
||||
}
|
||||
});
|
||||
};
|
||||
if (exactWebPage
|
||||
&& !ignoreWebPage
|
||||
&& (manualWebPage || sending.empty())) {
|
||||
histories.sendPreparedMessage(
|
||||
history,
|
||||
action.replyTo,
|
||||
randomId,
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
|
||||
MTP_flags(mediaFlags),
|
||||
peer->input,
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
Data::WebPageForMTP(message.webPage, true),
|
||||
msgText,
|
||||
MTP_long(randomId),
|
||||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(message.action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
), done, fail);
|
||||
} else {
|
||||
histories.sendPreparedMessage(
|
||||
history,
|
||||
action.replyTo,
|
||||
randomId,
|
||||
Data::Histories::PrepareMessage<MTPmessages_SendMessage>(
|
||||
MTP_flags(sendFlags),
|
||||
peer->input,
|
||||
Data::Histories::ReplyToPlaceholder(),
|
||||
msgText,
|
||||
MTP_long(randomId),
|
||||
MTPReplyMarkup(),
|
||||
sentEntities,
|
||||
MTP_int(action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty())
|
||||
), done, fail);
|
||||
}
|
||||
isFirst = false;
|
||||
}
|
||||
|
||||
finishForwarding(action);
|
||||
@@ -3815,7 +3877,7 @@ void ApiWrap::sendInlineResult(
|
||||
? (*localMessageId)
|
||||
: _session->data().nextLocalMessageId());
|
||||
const auto randomId = base::RandomValue<uint64>();
|
||||
const auto topicRootId = action.replyTo.msgId
|
||||
const auto topicRootId = action.replyTo.messageId
|
||||
? action.replyTo.topicRootId
|
||||
: 0;
|
||||
|
||||
|
||||