mirror of
https://github.com/kristoferssolo/School.git
synced 2025-10-21 20:10:38 +00:00
Initial commit
This commit is contained in:
parent
16db763d1b
commit
aea05cae02
@ -0,0 +1 @@
|
||||
pip
|
||||
@ -0,0 +1,29 @@
|
||||
Copyright (c) 2013-2021 by the Babel Team, see AUTHORS for more information.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@ -0,0 +1,31 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: Babel
|
||||
Version: 2.9.1
|
||||
Summary: Internationalization utilities
|
||||
Home-page: http://babel.pocoo.org/
|
||||
Author: Armin Ronacher
|
||||
Author-email: armin.ronacher@active-4.com
|
||||
License: BSD
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
|
||||
Requires-Dist: pytz (>=2015.7)
|
||||
|
||||
A collection of tools for internationalizing Python applications.
|
||||
|
||||
|
||||
@ -0,0 +1,847 @@
|
||||
../../Scripts/pybabel.exe,sha256=F7jkcNvcBFObHlskx1hp8AY7Fx3ngaOiqy-46lYXw8Y,106370
|
||||
Babel-2.9.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
Babel-2.9.1.dist-info/LICENSE,sha256=KMl78z51BuJ3SHvao6abcPFw1q9agnhawKdMhCgELkA,1451
|
||||
Babel-2.9.1.dist-info/METADATA,sha256=mlkWT3NrQ45RhCJaK7b0eaREy0YsZfn0c4qGbvW8PWw,1223
|
||||
Babel-2.9.1.dist-info/RECORD,,
|
||||
Babel-2.9.1.dist-info/WHEEL,sha256=Z-nyYpwrcSqxfdux5Mbn_DQ525iP7J2DG3JgGvOYyTQ,110
|
||||
Babel-2.9.1.dist-info/entry_points.txt,sha256=dyIkorJhQj3IvTvmMylr1wEzW7vfxTw5RTOWa8zoqh0,764
|
||||
Babel-2.9.1.dist-info/top_level.txt,sha256=mQO3vNkqlcYs_xRaL5EpRIy1IRjMp4N9_vdwmiemPXo,6
|
||||
babel/__init__.py,sha256=2isYTKcvIoYWhBj1H7DhXFGIVauRTrA5dbeC0I0px8k,714
|
||||
babel/__pycache__/__init__.cpython-39.pyc,,
|
||||
babel/__pycache__/_compat.cpython-39.pyc,,
|
||||
babel/__pycache__/core.cpython-39.pyc,,
|
||||
babel/__pycache__/dates.cpython-39.pyc,,
|
||||
babel/__pycache__/languages.cpython-39.pyc,,
|
||||
babel/__pycache__/lists.cpython-39.pyc,,
|
||||
babel/__pycache__/localedata.cpython-39.pyc,,
|
||||
babel/__pycache__/numbers.cpython-39.pyc,,
|
||||
babel/__pycache__/plural.cpython-39.pyc,,
|
||||
babel/__pycache__/support.cpython-39.pyc,,
|
||||
babel/__pycache__/units.cpython-39.pyc,,
|
||||
babel/__pycache__/util.cpython-39.pyc,,
|
||||
babel/_compat.py,sha256=DHx6vQR-LazZlNdeBE7wGTOBv1_1HWbRboKOkX76TiY,1685
|
||||
babel/core.py,sha256=5CmHhtC4GV_Nrd6oq63apsEO2nb3ZPdLsA3MYd9lzBI,36907
|
||||
babel/dates.py,sha256=cjONUhc89AMhtSpNk8jrtCGrtqwrPuS6rsXOzHZROpM,67709
|
||||
babel/global.dat,sha256=P2lM1DjyEx9SMpmXlgu4zNeodlF2Qp2hg9yEANLM3ps,254421
|
||||
babel/languages.py,sha256=UmLTj4Nai3kQrwHX6jptehVLeAw-KAdxcmcp2iDlgvI,2743
|
||||
babel/lists.py,sha256=yks1P7CNrIoicIptChdpwtDHN9eKVK1sfeDzhLgPVpM,2719
|
||||
babel/locale-data/af.dat,sha256=jjfQ33ml9BDllSSkfwcIQzzgohE645gzeehkj1KwTMw,171143
|
||||
babel/locale-data/af_NA.dat,sha256=6A8JdTF_O-lRxJZmjI6Lig4Se2aFbqWhdw34Ak4-67g,1407
|
||||
babel/locale-data/af_ZA.dat,sha256=ZaMuNgUHOKLle56lUxFOGAAk8QM-_41nuazbqNu5kgg,608
|
||||
babel/locale-data/agq.dat,sha256=gSE4vg5l5Yze-10YkHjiBaLVqC5fp0xgSr3nMuZB8lw,17339
|
||||
babel/locale-data/agq_CM.dat,sha256=AxBMSZitoHhaa6djMmFbp6iEPM8OUC04G77ZldkuHR8,609
|
||||
babel/locale-data/ak.dat,sha256=fk1o-LXIVWd8kObwIG98ltM0H9W68R1_alFWFl8U_2o,15859
|
||||
babel/locale-data/ak_GH.dat,sha256=tuOpoiGUJqZ_Dlr8xlp9oIqsFL-YQrBQpDUfG5z3YQk,589
|
||||
babel/locale-data/am.dat,sha256=qe-hJ0p-GstMzzmrdamvejKBIVwLBuJRPyfdEdUQLB0,200581
|
||||
babel/locale-data/am_ET.dat,sha256=JHNCRHUTq_8VPokwz2uGwCZPGxUR23nJdDIzi_HFIbA,608
|
||||
babel/locale-data/ar.dat,sha256=aCbEpK5EzE3tG7TDSCPJVF4srTWPDcTF7GIJjr_Z36o,345779
|
||||
babel/locale-data/ar_001.dat,sha256=Y2HUeGZn8VV7DCPv6nXTWmkqTtzGxZxdvXYYiS5mU-o,1680
|
||||
babel/locale-data/ar_AE.dat,sha256=UAOwSgM1tC_mFK1Gr8D1t_2HwylT_wv50l7LyDew6BI,1038
|
||||
babel/locale-data/ar_BH.dat,sha256=f1D15u-5clcZJvrqsnr2XShOLf6hw5hmR587r7hsKEs,651
|
||||
babel/locale-data/ar_DJ.dat,sha256=NWt7QxMxsj1-zAsJ8aXWGT1SwzKayjlbB8TxvY8P-iA,629
|
||||
babel/locale-data/ar_DZ.dat,sha256=1KdQGZH5ePC4W3nwrB1F2msNqVVnK0wYwfU-uqYAhXU,1713
|
||||
babel/locale-data/ar_EG.dat,sha256=EUDxLyjz-znR56wvAE-_IvJX-2ou_ubS3KVU83SHa5Q,688
|
||||
babel/locale-data/ar_EH.dat,sha256=OseNtW_AOGrIkKmxk2ufJXkpwOXsajJ4uyJAwUidL1g,589
|
||||
babel/locale-data/ar_ER.dat,sha256=FK8yF8SloHQoOXNpaKlnEMsS9oG0j9dhDhiSwk7euCw,610
|
||||
babel/locale-data/ar_IL.dat,sha256=TzNjvKnJXxJBRXR55WZ9yVxpHnN-2subVXqjeS7CX4I,1195
|
||||
babel/locale-data/ar_IQ.dat,sha256=G4JR6ue3O7NNz7Hy2WKKiHg9lqhaHGjZA-UFq8N9TKs,2336
|
||||
babel/locale-data/ar_JO.dat,sha256=K9WKy9urKZA7k6MIuprjN2Yu-VgySZVzK46jui9NYnY,2335
|
||||
babel/locale-data/ar_KM.dat,sha256=e0ER6Yw-J2DOL7R8JKuTBpU0_46WK0jLBKpsG56UHgk,1161
|
||||
babel/locale-data/ar_KW.dat,sha256=hsa41dETEsjs8XPCZkryiCFbPBLrv6aF5ya-ImPAT3g,651
|
||||
babel/locale-data/ar_LB.dat,sha256=b4DWnwWjHST9MvfKnu6YaGhP2ghxjpZP5TQy7w_OGtU,2336
|
||||
babel/locale-data/ar_LY.dat,sha256=QyNUUgeaUdsvLQtwRLPQed-PRiDez_ekokUwpxT9jRw,1652
|
||||
babel/locale-data/ar_MA.dat,sha256=ufYSdBIy96F6zJND6kKZuilh00Lpu-z3txPDPhsgAIk,2007
|
||||
babel/locale-data/ar_MR.dat,sha256=wjI22LINnrT_HVHqm1ZmJ9Ndb6bFBKvAFkeyvQ8tBi8,2173
|
||||
babel/locale-data/ar_OM.dat,sha256=gsBDBEK35j4M3ualnSdL6tFD4-u3dSbJX1NtS7znQ_E,651
|
||||
babel/locale-data/ar_PS.dat,sha256=tTTcOqje-rppgz46-DrkawXtoc9jIQ2vwyA8rRU2uDM,2273
|
||||
babel/locale-data/ar_QA.dat,sha256=QI6pzsVjeY_nxkk8iKhy_DUzfBJrZFWoL9uYKM3L9CM,651
|
||||
babel/locale-data/ar_SA.dat,sha256=T6x2_p8wVOfcUx9RZMwa5yM1qxVnDoJCxXPzUcsQXuM,30599
|
||||
babel/locale-data/ar_SD.dat,sha256=gUbUGVDm-V2a9ViTVska833oAys0b6Au-IJcoMo5leM,651
|
||||
babel/locale-data/ar_SO.dat,sha256=fSiIj3lwo0FJU0dXbnFUNLPDvV_jejp86mHcLiGtiJ4,608
|
||||
babel/locale-data/ar_SS.dat,sha256=eAaVq86grUAnWNST_u32IrhbryyjRvUo27UG0js6zS8,631
|
||||
babel/locale-data/ar_SY.dat,sha256=4ge-CrqdFYfvu3VOdrvd7lRqhGDf2rPfTYkaNBaO4Ks,2335
|
||||
babel/locale-data/ar_TD.dat,sha256=yVONNY9PuoKVCLjT0w0qp0NLO4kShNT9j9eM_uKtQYY,589
|
||||
babel/locale-data/ar_TN.dat,sha256=J3SolHTZQ9_7HZGluj2jFu4odczgSZlOYU7spA670XY,1651
|
||||
babel/locale-data/ar_YE.dat,sha256=tsYZG7eRROrZJyzc_jUbyxbMRT157S3ocGMh7eIiqsI,651
|
||||
babel/locale-data/as.dat,sha256=sEo9KNUT_mxPE43dnY2qd5x5PS0YptFdgQB33rCj108,234427
|
||||
babel/locale-data/as_IN.dat,sha256=BfzVFooc90N8ufCwaNAuKzefwYLUen0-o4wUafoLYc0,631
|
||||
babel/locale-data/asa.dat,sha256=RTNazZw6IqoA6jO4o2v0jUI-x6rKsBHeCEEi9_eWGto,16187
|
||||
babel/locale-data/asa_TZ.dat,sha256=aSECPcjC7UM3Bb4Cy16Et-RHtNrhlzGM_v4zNMGsreU,590
|
||||
babel/locale-data/ast.dat,sha256=7s8-hdazQXPAA8cPPc2AymyA1vAI2P6MoHOjtcuDXaM,209617
|
||||
babel/locale-data/ast_ES.dat,sha256=x4OX34OA3ztvfnETdf49lKg6Gz2q6Lv17Lrf0G4EZ1Y,627
|
||||
babel/locale-data/az.dat,sha256=2FAR_E0DODOjfyi82cqli4S484eNi8IWcGOJdvaUMXA,194898
|
||||
babel/locale-data/az_Cyrl.dat,sha256=1AcCgkkW-Oz7hXWJVoUqe1BRwdirpoY32Ub53YIUJDQ,38880
|
||||
babel/locale-data/az_Cyrl_AZ.dat,sha256=yhmkFuYZLbGzV8Q155t3UrHn-rEqAR9LVmz1sQkKcSI,608
|
||||
babel/locale-data/az_Latn.dat,sha256=EkZYNfi4vipZ7wH0cvvd1yvqOJxwCNtYADX0SgJMnAE,2225
|
||||
babel/locale-data/az_Latn_AZ.dat,sha256=yhmkFuYZLbGzV8Q155t3UrHn-rEqAR9LVmz1sQkKcSI,608
|
||||
babel/locale-data/bas.dat,sha256=SkyEjzAws6O1b_g_mtVKcLFvR_00Z8HK1ubf7X_NRIk,17128
|
||||
babel/locale-data/bas_CM.dat,sha256=NlquEbS-6vOPdnyIC4r5KRnEbj4Y0oaO56i3IeH2MmI,609
|
||||
babel/locale-data/be.dat,sha256=R4OLJNVpSSFRz34CGEFpWedQosrBKf227FweNgrhQvU,271438
|
||||
babel/locale-data/be_BY.dat,sha256=0uCaBRRcbIS46dyiHK85UMi-k3b1b_uspOzBHMos2jM,608
|
||||
babel/locale-data/bem.dat,sha256=pqGkFsWL-tAPVJfouEiYifYERtShK-WpoABWUzJP0vA,6534
|
||||
babel/locale-data/bem_ZM.dat,sha256=VbAesm4_2wMn2EmWOW7etCOWlleqpkSAjjMOtKBlEcQ,590
|
||||
babel/locale-data/bez.dat,sha256=lOnVgx-EVzJ-TL9G6tbvC5qckxtoPwIG9UEQR8RLthY,16977
|
||||
babel/locale-data/bez_TZ.dat,sha256=PHbB6bmtC5Wn46cFkmE8mjwuSUTr3gCxXkmFzqpiDRQ,590
|
||||
babel/locale-data/bg.dat,sha256=pUVekrzzgzY-8cecdX7rcvQ9-LNteX4V3yzZJyGu_qM,232833
|
||||
babel/locale-data/bg_BG.dat,sha256=rHaVmPZT-2n7w37ORQM31-InIsuCBYpv6xWIAc0akkk,626
|
||||
babel/locale-data/bm.dat,sha256=-E8armVyVSCPOqdRGc55rFLFYJcPPkvMUw5fCzRYAj8,15886
|
||||
babel/locale-data/bm_ML.dat,sha256=uOp8g5jSZ0dtvQRJ_GmriD3hafnqKpY-D8VhCY0lctk,589
|
||||
babel/locale-data/bn.dat,sha256=mLx95u-bxnHGpQ3f07-gBC6RYW658gmJzImHukcigK4,263365
|
||||
babel/locale-data/bn_BD.dat,sha256=J15p67iXhfwwTscvbnmaYH1jxiMf8n7kvXoaYiMDgCI,608
|
||||
babel/locale-data/bn_IN.dat,sha256=D5aBzoxDMmKe7Bnz25b_MTbqxm3ofuOqA73An-bd0Ic,866
|
||||
babel/locale-data/bo.dat,sha256=fG5-yWBu0eudG5gbVC5xJQF-C99BVk0zIgiYr-4Q4e4,22525
|
||||
babel/locale-data/bo_CN.dat,sha256=9gsaOvK_bYpPFDNXZ9lOj3Y-jgDTZlD6JHhlPLJ2Te4,608
|
||||
babel/locale-data/bo_IN.dat,sha256=EWXLEVA3oaBtJFiwQVxREJbR4fjpyaqQ1P1xVNsMowc,704
|
||||
babel/locale-data/br.dat,sha256=S6Rh6pNfXOlOKbqW0dpbTc05PfGfvWgfeL3eBZwk4hs,290897
|
||||
babel/locale-data/br_FR.dat,sha256=ioO-nP2x2c5STVkiH-RvhNxxq6giVfDejh4T-FoSjF8,626
|
||||
babel/locale-data/brx.dat,sha256=pQJJBfYcX8pxrFlEkfkwwprNf6c6AG3Bkvh-tNpp1YU,124289
|
||||
babel/locale-data/brx_IN.dat,sha256=9pIIjxmY4jmGi9LDci2mDhdHADN2oD3U53pBIRNNRc4,632
|
||||
babel/locale-data/bs.dat,sha256=wHmiOLJ8MBJyaM2xpKiuIrIDSn3KHu6kz33rYpzDJjQ,239326
|
||||
babel/locale-data/bs_Cyrl.dat,sha256=MBDuEafwSU1vWRHHor26JViQTwYsoyR_imtvVlp6N78,213685
|
||||
babel/locale-data/bs_Cyrl_BA.dat,sha256=49_6kE_iGTwxlkieBZvxsXvVPAUrQ3hlavg2hMkUzFQ,608
|
||||
babel/locale-data/bs_Latn.dat,sha256=jWzwo3YbhqMRkMWFgGPJ1SoBrHBL5OKB6yqVoJw3cKo,1957
|
||||
babel/locale-data/bs_Latn_BA.dat,sha256=49_6kE_iGTwxlkieBZvxsXvVPAUrQ3hlavg2hMkUzFQ,608
|
||||
babel/locale-data/ca.dat,sha256=mWNiuT8Rt5CV1YnXpjqiZP1HlvftCMz-DbaPLLbzEe4,208790
|
||||
babel/locale-data/ca_AD.dat,sha256=c0uaIsSk6XuXizMkzNYZcMzFcC9ItvvDTh9byxpdYV4,626
|
||||
babel/locale-data/ca_ES.dat,sha256=xAbDhTv0TIq0M66QrfejjMsbIIthq2CCXMr00ojFzoA,626
|
||||
babel/locale-data/ca_ES_VALENCIA.dat,sha256=i6YyGQHkRnxTuJLvjemc0tm1Iqqfm0v0dNZnLk_v7R8,3644
|
||||
babel/locale-data/ca_FR.dat,sha256=bm288L4_PW-Wgb5Ty-9jcQns0i9iVy4zQY8PV3IETHE,645
|
||||
babel/locale-data/ca_IT.dat,sha256=t21q_Bu_bo2FVP609O53DGAXPbAUGv5yZ-_m71S1bWU,626
|
||||
babel/locale-data/ccp.dat,sha256=nyA_rk-dZ4U4ATCfcCEQeAj4Df6igjI4XD7HP0j045w,275655
|
||||
babel/locale-data/ccp_BD.dat,sha256=Lns8llZesFHOnqgmiYntJhMufHDSmzHOL-sYczkVxCs,609
|
||||
babel/locale-data/ccp_IN.dat,sha256=zRmYBrG8ABv6_4YB7puTs2jsWSBBgqo0yBpvsBVHxZQ,632
|
||||
babel/locale-data/ce.dat,sha256=XtFwtrhjaJGFgmegHYgoVSqmZs_5o8S85XspljVTzSo,138778
|
||||
babel/locale-data/ce_RU.dat,sha256=rAfBzB42xX9qOXWNu1kMJ278N99ohijJoWO2XAskSkc,626
|
||||
babel/locale-data/ceb.dat,sha256=h8hImvVlmbhxs4ufAMKi_C3DExHORd8hrbdd2hQrXx8,103518
|
||||
babel/locale-data/ceb_PH.dat,sha256=nQM5vO0qo0sARNlhLIXlzxBCevhReUtYPios-RIcw8c,609
|
||||
babel/locale-data/cgg.dat,sha256=VfxK9EKS6ocduf7D3FKKHIXahll75kOwDuT6jrI6d-o,16228
|
||||
babel/locale-data/cgg_UG.dat,sha256=87p4kuJQ3R_CLR3yPT-oMPAT9idvdPVElVxpZC5A69s,613
|
||||
babel/locale-data/chr.dat,sha256=Nk70q12-m-cVNXDVMBrT1YTRtyS9t949i3oDVo6SyKk,200072
|
||||
babel/locale-data/chr_US.dat,sha256=BS6w-X9I6FuixJ2upUTEdFstYRKU7FCok38SRWahHWc,627
|
||||
babel/locale-data/ckb.dat,sha256=VfHXHCrZYFQJ0NxHji-px_rJ7gD15bVeVHEQDkjtrIc,41606
|
||||
babel/locale-data/ckb_IQ.dat,sha256=8qfAOdEjoncef0lQt6zsXiW0Nn9uY4Fb2jQMpgJSxd0,652
|
||||
babel/locale-data/ckb_IR.dat,sha256=cNWVEpmuwNkAyJm8qdtOho5FEIB-UF2dOHSXoDIdWj0,1204
|
||||
babel/locale-data/cs.dat,sha256=PzETNpoA6kgHESjeT01YFgtQd31qRnCbrfdWbZ8M7sM,297675
|
||||
babel/locale-data/cs_CZ.dat,sha256=IG8kxPUf2L53IheXDOJcGUHV5XPaEvrWlhznlScsZAw,626
|
||||
babel/locale-data/cu.dat,sha256=Ak6g9Gsf7fAe3EsC4ORWtTDTqfGjoHanPHd2VU7uqhY,20265
|
||||
babel/locale-data/cu_RU.dat,sha256=NHfB25KQf80ELweLH7Qe5OHUIC21BjJZsZvPUZ8wlN8,626
|
||||
babel/locale-data/cy.dat,sha256=wy7mLRchz59usL93zfp-wZ3iyalLaEO6QHwW7c1L2Pg,315824
|
||||
babel/locale-data/cy_GB.dat,sha256=ZHRJBfOpeOVn8rfsdEhIF5mY01XFhStFmTVeOmklOAk,626
|
||||
babel/locale-data/da.dat,sha256=2sCrVwkFfF2RHbLoon79r_JwKXCqZ0oj1dbpe6hBDSY,199867
|
||||
babel/locale-data/da_DK.dat,sha256=OZkvaI7AQcocAo2rtHtZq3d6-P4mzR0MWWOQ8EJXjSo,626
|
||||
babel/locale-data/da_GL.dat,sha256=uyqYUJOO4nd3vn92yPsEVm6mYGXWCqSUTG4DtImKc0M,589
|
||||
babel/locale-data/dav.dat,sha256=nRUgF6cL7_RI2vbdVR407MYHpJ5ALeZtY4lrGcRlVSc,16271
|
||||
babel/locale-data/dav_KE.dat,sha256=FP78PK3asgspsW7QIhV0jrOHFmDG4iZiGjFBvPQF-6o,609
|
||||
babel/locale-data/de.dat,sha256=bcoZmi61_dSmFuJN9YA6n_llVQCfbeRtVlkYm8QWpvM,206762
|
||||
babel/locale-data/de_AT.dat,sha256=-UMZ_o8YNkI3mlluBgFiSXc6ttnqo_adzxsPffafPDw,2563
|
||||
babel/locale-data/de_BE.dat,sha256=cAHuCiE_b6CoIRItE8FQIpr7fR-gSsF66MtRGhU3xyk,626
|
||||
babel/locale-data/de_CH.dat,sha256=x8MlguM2lvZtFSB8R-BWNJ2wgy8vjGNRDUPcYO7YGRA,3938
|
||||
babel/locale-data/de_DE.dat,sha256=uGWbXF2bkaVQcgna0h59yJQJctOj88om0v2NVVCJvPw,626
|
||||
babel/locale-data/de_IT.dat,sha256=y1GIOM88fIEDhz5M_Seiy5sk47wTF2X5nRspsQJRWXc,1619
|
||||
babel/locale-data/de_LI.dat,sha256=bggRqr8i9UGeDEA1tqBgRv_lWAGGbb4voVc152sl8js,1321
|
||||
babel/locale-data/de_LU.dat,sha256=rMtYa8P0yOF9Asg8mMIiBaeFzg1imA6BOFB_1AV0H9g,1065
|
||||
babel/locale-data/dje.dat,sha256=0lCk_5ABMX3iiY0QcB6N6R1JH1B5db3KFxiu-eS2Umw,16192
|
||||
babel/locale-data/dje_NE.dat,sha256=YRn5qozp8AlljDhoIVdw1KfDjTwJuQSR1O6zcfh6Z54,590
|
||||
babel/locale-data/dsb.dat,sha256=GVknAiKWopJw22chqjBGEvoq7GN201Sw64vnh-kqPeA,179644
|
||||
babel/locale-data/dsb_DE.dat,sha256=UEem7x_iq5-p3Tpzjtja0ONC1qtHvG2MCsQMx8KvTmo,627
|
||||
babel/locale-data/dua.dat,sha256=GSB_OYiEmeJM7B9QAdgr2IV06ehJUpVdy-ffO5j9SDo,5355
|
||||
babel/locale-data/dua_CM.dat,sha256=fOhCBrVImDeIe_5GZrgYvvdY70mSsENjcTEzSld5FYs,609
|
||||
babel/locale-data/dyo.dat,sha256=KJhfyqJEf8mhA9wV3xbD0VOcUm2JT0LQ8xJtHgqMVPM,10541
|
||||
babel/locale-data/dyo_SN.dat,sha256=coM-rzzSZhBVSz9gchqxki0QnX4zhOD-Lk1nt6sPCxE,590
|
||||
babel/locale-data/dz.dat,sha256=DG9YNNdDUCJkqwNdcstRrO8BgU9zqe1PTD4Em3dSOak,89908
|
||||
babel/locale-data/dz_BT.dat,sha256=__K3dx97Ynlcn2gcV40OXMmd-G1YchvffwSv4old74k,608
|
||||
babel/locale-data/ebu.dat,sha256=j6vvoYG_wPxra74yw8ldqZp_oD25AJFbUvysJkUtClY,16243
|
||||
babel/locale-data/ebu_KE.dat,sha256=8py7zy73R_NJUahomYGMJF7at0vD_TMjbQy8AT7OgO8,609
|
||||
babel/locale-data/ee.dat,sha256=EG6FqmRvtVrJdzN3p8QxU35xqBQzvhB2lbaLz-NKN-U,142527
|
||||
babel/locale-data/ee_GH.dat,sha256=B_aqQhHklFcblsk2BJmIZgwpAX17_pZENzO1Xoo1LpU,589
|
||||
babel/locale-data/ee_TG.dat,sha256=MG63DGqUVcZLwabu4o_BezzGovDY8g30wKLHkrbEU8o,1141
|
||||
babel/locale-data/el.dat,sha256=M-uy_xte0SOlEQtwdOMM92GLjpvx09PgWGO3bYsBMI0,244752
|
||||
babel/locale-data/el_CY.dat,sha256=07pyrGXJzOGhfxhX--19MAVJlDzuBGe1AfsnkOiHBeA,608
|
||||
babel/locale-data/el_GR.dat,sha256=WqPmX-_0xIHS9A8kTDJbVCJXhqr52NEiW0CyLdGm6yo,626
|
||||
babel/locale-data/en.dat,sha256=WFZgaqLZ9ZYKZdU8A5K2ZMepmtkc8-ve3vC0VA1dzqM,194682
|
||||
babel/locale-data/en_001.dat,sha256=Wsq2--QwmhqwjXx3jpyXs4SNShvNFtnQfH74-9RmU5M,27063
|
||||
babel/locale-data/en_150.dat,sha256=rbNu79tGtS6MsRHloWtHrmdPuZCmwWRThAQ8M7C_5sU,1765
|
||||
babel/locale-data/en_AE.dat,sha256=EhFOQNZpti_Z7dPcFMbQbuFA5r4LwCwGKigJgowZ5Is,4111
|
||||
babel/locale-data/en_AG.dat,sha256=AKSzhMbGCUU-P3phlu6HupABdKSEys-M96wBGbNwgBc,627
|
||||
babel/locale-data/en_AI.dat,sha256=6ihO9cDogLMcSHgmWHgJDTg0OCTfEC4fVftMAbv3-zo,1179
|
||||
babel/locale-data/en_AS.dat,sha256=XkSzLYRfcXzQ5S8kaps6cLh8lVLcEtpS7v5GVYJ0oxA,608
|
||||
babel/locale-data/en_AT.dat,sha256=jKCuj9au7zT3QiZd6mRgjRutjPTd3rW7k_aSCopd3lU,1200
|
||||
babel/locale-data/en_AU.dat,sha256=GgFVbFesUa_9FbZYqtHtgW3fDyUvQCxBMO1KPcH3wl0,23385
|
||||
babel/locale-data/en_BB.dat,sha256=qYW0ov3TXlP5U49PsDwBoGuNqydFwIDvAzb9g_PU4BQ,608
|
||||
babel/locale-data/en_BE.dat,sha256=sLyuId-scSREYGWTIRr-jmU6cuaSkgQbNc_jd5ij3Rc,1493
|
||||
babel/locale-data/en_BI.dat,sha256=FPbgGK-AHgRjz__MFHCzzOUIGhAmhx662sqL-CZWyXk,1162
|
||||
babel/locale-data/en_BM.dat,sha256=xkpTQIMT4L5hhYXe9ANWZkxgyS2H6wsMdG1qtacDJH8,627
|
||||
babel/locale-data/en_BS.dat,sha256=zHTFOmXUvagki_mtGdj0lht3V82InuI8-9cTPhvQ8UA,811
|
||||
babel/locale-data/en_BW.dat,sha256=R88jGKkwpex2QzxjAVOj-tu5HreJy6DlO3ZqqcD7sKw,2771
|
||||
babel/locale-data/en_BZ.dat,sha256=0gOIW5WU8lL15-_mWj9Xg0uDjtQiQHsWAl34U2sN3lI,2950
|
||||
babel/locale-data/en_CA.dat,sha256=QiSNMW4tsb8v4mvvKSJ0fjYx9wKvFyOnqZv6G3ih9xQ,25449
|
||||
babel/locale-data/en_CC.dat,sha256=n1D9R3tb0Kbc3Umv3cS_2IfDv6gXJDkauUmLRQ85stk,1160
|
||||
babel/locale-data/en_CH.dat,sha256=hU3jzJbghrq6qpPAcRCsN3_UzYw2XNJCvnC0KScoOMk,1100
|
||||
babel/locale-data/en_CK.dat,sha256=Te6ZAYFDOE6v9domOnOXCxMrCpBSt4y8i6xxX8zplZM,1160
|
||||
babel/locale-data/en_CM.dat,sha256=vogNfPzFKhhNfFR3TzWWE-P8wKdkeGujj--c757Iy-M,1410
|
||||
babel/locale-data/en_CX.dat,sha256=CkFYiGUksAivYRZlmH-sfvwQ8HUgJ5Iqx1LD0UXbcCg,1160
|
||||
babel/locale-data/en_CY.dat,sha256=Vl4Oa2RNsxbDmyq7cJaN9UbtK3KSvSpBQZ3ouieaDXc,608
|
||||
babel/locale-data/en_DE.dat,sha256=yW9FX1tuZCAANFhM095trr-p-k39XN6VwN5wYMEDS6A,952
|
||||
babel/locale-data/en_DG.dat,sha256=db0CYrcJAtcIl9MFAGUuzVUfUS4x-I0ppd4nNP_igGs,1141
|
||||
babel/locale-data/en_DK.dat,sha256=YFMkEHF_fAzY7w7CsIFe7eDhRuw31mfH-oLlniAkqhc,2350
|
||||
babel/locale-data/en_DM.dat,sha256=d1muNBxiDWlN78TXhEJiANVe_0UxZGjJ96NoIzmPQH0,627
|
||||
babel/locale-data/en_ER.dat,sha256=ZCZFGjPQWwc95TKwRCihywYh1yj-TaRmnmJqj26-dqE,860
|
||||
babel/locale-data/en_FI.dat,sha256=D8c6wssToJyrWdn61FXBz0h35HW3BZC_iGA0_MF4npA,2282
|
||||
babel/locale-data/en_FJ.dat,sha256=4dotX9Otp56WxZz2vqeHMl-FVcBKiT8BlqGktxoWKFM,645
|
||||
babel/locale-data/en_FK.dat,sha256=VC91FNLl2QBhA5qkxhodFR6TWRlIus-UHJ4dzJNtebk,1183
|
||||
babel/locale-data/en_FM.dat,sha256=kwQ5xP5wBGKlO-Mb2iqvsStkTC2JfMc46gBnlFTiI3M,589
|
||||
babel/locale-data/en_GB.dat,sha256=1rovCqWVd8rHtaNZiudq9tj9j1ZSdQpj85HcXMXRCNM,25821
|
||||
babel/locale-data/en_GD.dat,sha256=MbV-yK2BeGhQSajMlcL9TvEWWmch0zGbfBFcKj5eBzs,608
|
||||
babel/locale-data/en_GG.dat,sha256=qW--gYp58HZQysSEvEs2e-PzujR6nxJw76OKtml_R9g,1246
|
||||
babel/locale-data/en_GH.dat,sha256=WfV3h6HkT4PhJVSqNqIcrYOA-eWWywIMUCk6GX2DGkc,862
|
||||
babel/locale-data/en_GI.dat,sha256=Pcy6njgp-RTvil94c1DoD8gPEJfDqJxSa6Ap3hz4hLQ,1201
|
||||
babel/locale-data/en_GM.dat,sha256=1-9El_7BaSwYnE2NvFGES1XWvUOA3h31FOz48SyWhGw,858
|
||||
babel/locale-data/en_GU.dat,sha256=Msmmrz-7nw0Mm50eo0Df8mPsJFRBBbbDtCgjNN8K4Do,688
|
||||
babel/locale-data/en_GY.dat,sha256=U8FjrK6RICyHeGXrXRziQ-x5MYJv-67aiNk870rRU3U,667
|
||||
babel/locale-data/en_HK.dat,sha256=-or_oYC7dQt4KP_QTE8085lo6lNr9Sxd15MGoKBpMOg,2008
|
||||
babel/locale-data/en_IE.dat,sha256=N2NXGWi7XPi2TcOw4lC3Q7YVGESIhF3LoxX2WPor8e4,2043
|
||||
babel/locale-data/en_IL.dat,sha256=KmYFTJlvN4yPA1h81uPevqnBJbEMySjB6BwcgvtARKY,1397
|
||||
babel/locale-data/en_IM.dat,sha256=PYHp1IMNWDea7-pfiNMq0lMSwlw6jrd1W8PijFVp_-c,1246
|
||||
babel/locale-data/en_IN.dat,sha256=coaqyAiTCcprH5Un1jvvgWZCylIgGkVoKVWryR-RtiU,3767
|
||||
babel/locale-data/en_IO.dat,sha256=KdFDEZ-ATOiBnVWa2p-QJovncI2Voygei_GH8ole4vM,1141
|
||||
babel/locale-data/en_JE.dat,sha256=7Cmj2eNyJOMB2YSUAkna9CGLn9cHuAMoQedkWzTJtZ8,1246
|
||||
babel/locale-data/en_JM.dat,sha256=4EK16ZNGL65bz9xtQrucMOxSITM8wVwqhdKEG04s154,1599
|
||||
babel/locale-data/en_KE.dat,sha256=KFU4dptHt5iSqN9zSPGv5_HkLkN8tcXdMoZZlSaK3OE,1431
|
||||
babel/locale-data/en_KI.dat,sha256=O13XFTeRaltrxnCjO4PA2NvM_dw-ye0xpJZeEnF0UAI,608
|
||||
babel/locale-data/en_KN.dat,sha256=G3xPxRBLVKbANLsnKR7b_rFGy6gYCC4YLzRI5gT8i4Y,608
|
||||
babel/locale-data/en_KY.dat,sha256=TV5QaWQr32vWrQWyBUskv1f3oq2TJVYqQPGEGJyh5lQ,792
|
||||
babel/locale-data/en_LC.dat,sha256=C_KqmNUBK_9-uE4_kYbUwNIOBeO9VJ9fpLOcaWwWDjM,608
|
||||
babel/locale-data/en_LR.dat,sha256=768u6chWYyWCDWWpSWkm8CFsSskf4e4-aayUrLDppFI,858
|
||||
babel/locale-data/en_LS.dat,sha256=K_G56Rgw6R7d6pMU5_KfwOAUvJk_hwdZe9GqU3NNfCI,858
|
||||
babel/locale-data/en_MG.dat,sha256=HA_OJPZu4eEyZP07J0MtTm8dAz4c5cXns2d5EjLArwc,1411
|
||||
babel/locale-data/en_MH.dat,sha256=lWjdFRFi5Cw9EBkpRifvGV93XeQke2MudP1tv7MXV6I,1341
|
||||
babel/locale-data/en_MO.dat,sha256=oal8-XgFkxo3F77Z5wKqP16pocMuo77-Ac9v6doamvY,803
|
||||
babel/locale-data/en_MP.dat,sha256=4ES9-ArZ1PI5CbAQ3LLDb8sLM6LVHhAnX6KgAz0VSoQ,1322
|
||||
babel/locale-data/en_MS.dat,sha256=HMWyIEh0-s1zUWHDC6XnKM8inpIDA36BSA_bN2spR0w,1160
|
||||
babel/locale-data/en_MT.dat,sha256=4LAEeC9KAdPb17kLcMe_p6U1bBuiySoOGQpdVphMNv0,1927
|
||||
babel/locale-data/en_MU.dat,sha256=Bq5ftR9nbRzJOacnOFQ7qluvifHCFAU81X4SsWWMHVM,1411
|
||||
babel/locale-data/en_MW.dat,sha256=1-D7UAzwljnuUlgPKs2HNP0ubNQ9HGEKgIUdpkxwc4Y,859
|
||||
babel/locale-data/en_MY.dat,sha256=koZHcYmaYIjYT6OANOlHdFfPuF-RmF5iyjVbkbtb1pg,689
|
||||
babel/locale-data/en_NA.dat,sha256=384TeL01HX5bShF-vJgFfy5m65jRjC_SfITw9K852BI,858
|
||||
babel/locale-data/en_NF.dat,sha256=rEdi2JCWTfieeeS2G0OCnKMblzSSc6NsoiEg0-JO-3c,1160
|
||||
babel/locale-data/en_NG.dat,sha256=KnyRrrpnzpV97teswZmDpq3eolhm_geKohcIrryBZEA,1412
|
||||
babel/locale-data/en_NL.dat,sha256=nWoZ94n1gMwXFwzvMAFraJLYNjiXkZMx5vzAM029PRI,1097
|
||||
babel/locale-data/en_NR.dat,sha256=SVPL_wXvdKEYdWqUYhkRrgwOMc-f0YP1Uaznxqv4NP4,1160
|
||||
babel/locale-data/en_NU.dat,sha256=0cg8LGLPIboWlBVxtmd4c10rEjqPvUUz2tyyi7kUksY,1160
|
||||
babel/locale-data/en_NZ.dat,sha256=x-zR1SoiPc9fpAvtblZLyzHZXrW-Np6ydJdqyXQrPnQ,2234
|
||||
babel/locale-data/en_PG.dat,sha256=Cq0NrSqmEseFhwCIo6noFliCfKnx3wAOenRn3VkED_Y,608
|
||||
babel/locale-data/en_PH.dat,sha256=W7ezPkuNS7JqciskJ3G25Ic0SbHZTmmmmenv0a39NgI,629
|
||||
babel/locale-data/en_PK.dat,sha256=0AD-WPif80PqSYV67bzVTvlj_h074ham3WETqh3NoDk,1959
|
||||
babel/locale-data/en_PN.dat,sha256=zxKpA6olu6dMYMtZpzaq35mSoMKh6AttZc6wSprPtxM,1160
|
||||
babel/locale-data/en_PR.dat,sha256=GbsBjcumdJ8L-rzRYD1cXU2uzmIUYHQX4chTgkJw02Q,608
|
||||
babel/locale-data/en_PW.dat,sha256=LH6T7NOgz_1iwCBhMne8ZH2hjPh-JHL2MOY3xktPyho,773
|
||||
babel/locale-data/en_RW.dat,sha256=RdqSwsBE4s_LG92OJvPPTxK3BoC-qzltS8PFWM2xogQ,1411
|
||||
babel/locale-data/en_SB.dat,sha256=cW7aw5w5Wos4_O_aRX1Xj4IXuEIq7eQpF50vnCEHKjw,608
|
||||
babel/locale-data/en_SC.dat,sha256=uVgNnrmBfJL7Jlv_wpfDtbdk5yFjpsTeyCTBKhiSmig,1161
|
||||
babel/locale-data/en_SD.dat,sha256=5JQaakikEVwEQ0YJm2AdZ2Zgg44mDPfl3ZKEatwChCI,901
|
||||
babel/locale-data/en_SE.dat,sha256=gpyVY45RU4nB4BKswErRq6UvnyFU6mQqzxzEBR0tDfQ,1427
|
||||
babel/locale-data/en_SG.dat,sha256=Yky7Bpen7HGGG4IpzKRb3folOUIfQ9nh0YiPqj2THv8,2017
|
||||
babel/locale-data/en_SH.dat,sha256=slAAeHdppQ8lHrVY8Pat5VFVwP-imbX9RbClTrFJkbE,1183
|
||||
babel/locale-data/en_SI.dat,sha256=TJey3lYp_l99RHcPcbxFkJ1u4tyP0Yb7TcY-JYAdehw,968
|
||||
babel/locale-data/en_SL.dat,sha256=daqNUYE7AgFpgo8PjtGYKm1YKqW8WgVQE4ViUnvh-_g,859
|
||||
babel/locale-data/en_SS.dat,sha256=2e53Ov3bAoJClI2KxnghO_q68wsvBYm5y69cFpvZpGM,881
|
||||
babel/locale-data/en_SX.dat,sha256=Ldsv42f1G7kgTFRcGdbyL_RnXUj2_whkfivt9xCS9oQ,1163
|
||||
babel/locale-data/en_SZ.dat,sha256=qidm3zACYSmI6TgdvkJ-URbDk7BdHg1JmENh3jFUsm8,858
|
||||
babel/locale-data/en_TC.dat,sha256=BqCmasVKStg1Mia681u6ZqtglR5TxC0QgCD2j1XqAwM,589
|
||||
babel/locale-data/en_TK.dat,sha256=KmgyiXJLdOlswDEemXHOLEuZb5de5ZM0YmdDxNnAHog,1160
|
||||
babel/locale-data/en_TO.dat,sha256=wOZyazP1wVbQhv9Y_H_NDHb0ldHsMPdZPN8O-O1c5ZE,609
|
||||
babel/locale-data/en_TT.dat,sha256=UwplYXlbOs4hLPyDovdYDv6yz8KGChSZ6ufJ5htjfQo,627
|
||||
babel/locale-data/en_TV.dat,sha256=Z_vPwZ0HZB4aDDibrbzesmYFzgKRqk22hS2ZKqhq3_E,1160
|
||||
babel/locale-data/en_TZ.dat,sha256=syqDYFfemhw375IYXAM-F03S4gxAe7EbaJcYVbjt834,1412
|
||||
babel/locale-data/en_UG.dat,sha256=yczBoonl1zmDZpeNyAHAKvQ_OArvhP7AWVLOtKv9Jkg,1435
|
||||
babel/locale-data/en_UM.dat,sha256=QpePixV3RZ9RiqrYuz49bkN6Xeg-UG2y0Po_yaLbSOQ,626
|
||||
babel/locale-data/en_US.dat,sha256=JU7XRlKyRBNlDNbGDabuIBWP_tfuFahFBUNDL16cE8I,626
|
||||
babel/locale-data/en_US_POSIX.dat,sha256=22rJAk0xIO2lY6r_nfKPBUtruaYmgtYeTjq9nz4RN0g,1204
|
||||
babel/locale-data/en_VC.dat,sha256=udrNbZKYSjk5vRAlIMd_k7255C5GUjBmQjOVm_GSshk,608
|
||||
babel/locale-data/en_VG.dat,sha256=_MFcYRjyNuFMVYGYjGBQMC3C2_IZjcSXGLxNFUt15z4,589
|
||||
babel/locale-data/en_VI.dat,sha256=ptodXPLBh9jA4d91bhhHarqlw8t0BuiigzyLPxAX3Vw,626
|
||||
babel/locale-data/en_VU.dat,sha256=OKNpgxA_p9zCpKhmDA-r2qAUHQmeEY-ITSvz6Hqlp8U,609
|
||||
babel/locale-data/en_WS.dat,sha256=_qLMqdSB0O18FukP062U6fiMk7uFaNUp-u8qjJXB3SU,629
|
||||
babel/locale-data/en_ZA.dat,sha256=MYqHr53tM6t70LgMH7_wdkltFYoUWLEG-u9T8PK8bbU,3269
|
||||
babel/locale-data/en_ZM.dat,sha256=Zphtlz3AeWJ4xZaeDtX29_xuSN-aHrmFX8-dg4j9ePs,858
|
||||
babel/locale-data/en_ZW.dat,sha256=cgE3J3Wk8y0K6uki7a377LFVPQFmDFPCCn5dngZQxMI,3199
|
||||
babel/locale-data/eo.dat,sha256=8RBQNNdJRH9CcD1IPXEl4pl9Z8U2OBio9vmJg8Z6f2E,40689
|
||||
babel/locale-data/eo_001.dat,sha256=Mlc_rMI2tpO1RL6ZJcuMDcO5ou3NuFOxZ16TomDvwrs,823
|
||||
babel/locale-data/es.dat,sha256=Xj1wyewmRlgXf3qDEsDQpFFAovauJMn7tL9VLlOoOFg,199638
|
||||
babel/locale-data/es_419.dat,sha256=dtalpa188kCJUE70v4IywI7YGXtRKWv61kCBoyEd0gQ,23299
|
||||
babel/locale-data/es_AR.dat,sha256=fHbtdPaXDRqdHGGB7NNOn_e2aNSX7OZQ1BiysR9PZo0,8828
|
||||
babel/locale-data/es_BO.dat,sha256=Ks0Vs-LYS9eSPux9FeV6HZnhdWDgSzPB8RWuDLglzkM,1888
|
||||
babel/locale-data/es_BR.dat,sha256=CQBretr3RreqaOiCUo5-cmR3EIlSUiQVJMd_fhPktIw,628
|
||||
babel/locale-data/es_BZ.dat,sha256=whnvRybQayDyZH7OFfVQHMR3aHYLZhpDU2gY-j_PbYo,627
|
||||
babel/locale-data/es_CL.dat,sha256=HPawCg0SjTK7JIBSvE0JJY7gxeirRz5DdkcXUgY9eH8,5128
|
||||
babel/locale-data/es_CO.dat,sha256=B7TtJd_eH_7KNClQGfsFbFNwwLmL72t305awqTOMIK8,8665
|
||||
babel/locale-data/es_CR.dat,sha256=Vh36FfFDvJeTDnmjYlOTd2ruW-5I2Wkv34BqALvJHyc,1719
|
||||
babel/locale-data/es_CU.dat,sha256=hjouuq52dJG7NJR3ypl_nAHpBIOYgV88AYWnR_i0378,629
|
||||
babel/locale-data/es_DO.dat,sha256=q_tRNydo2SG6AsDS0CJb7FPQvPHuIYi6hjJpBbGmWk4,4020
|
||||
babel/locale-data/es_EA.dat,sha256=vYi5_0kkB6gIqCXTdtHnD755-gzO2y_Gd-lAy8ahpMU,589
|
||||
babel/locale-data/es_EC.dat,sha256=VBBKHoCazqVryt0jzkeu2RadhDAityjxxkSXfsBYIq8,3294
|
||||
babel/locale-data/es_ES.dat,sha256=VCWxAz9w1EHetI06vwya_gkk7vDXGGSXJumViKKb4Ww,626
|
||||
babel/locale-data/es_GQ.dat,sha256=v1NY_AGhDyOAq1jIFJIQ9FWosDL_RHNvIIufvaEYdWM,872
|
||||
babel/locale-data/es_GT.dat,sha256=VjbMTOJSdaBbIhZfbeLcF5KTNtCDNN5Q-Y8mYIrICTM,4896
|
||||
babel/locale-data/es_HN.dat,sha256=_cSRFPkE1DrBlZFmQFO415ymztO6xQo7zZxHaixq9CU,3476
|
||||
babel/locale-data/es_IC.dat,sha256=ap4rHt9hZKqaWzlIZXgs92V3EWTmkCULMIY6Hf91T3k,589
|
||||
babel/locale-data/es_MX.dat,sha256=QGf8oLoSurcTEe41nR0B6mFVMQyfqEXttL-tLL0dsPg,24708
|
||||
babel/locale-data/es_NI.dat,sha256=2C0CW32DPFe5bwQFn0-yGXup7iVdYncLI7ByU-yGSVY,1653
|
||||
babel/locale-data/es_PA.dat,sha256=TvrAZFMO0Auv5Et41DcMNQKASC3ZrGCalqbxyqVEReA,3884
|
||||
babel/locale-data/es_PE.dat,sha256=dYZY6-VdFeUIYLzm9wyWQ7fpDc2_prQh_Nm5UsOoOC8,4848
|
||||
babel/locale-data/es_PH.dat,sha256=az00tcCjyCZo-DL4wkdCwFGwuue6M3KwlrCvT6UJCI4,1205
|
||||
babel/locale-data/es_PR.dat,sha256=D-Qc8ImING-Wu5LZpSvgfb5tTgKdqtLE6B-IyvJnXck,3798
|
||||
babel/locale-data/es_PY.dat,sha256=UCgFkmRSNtsFZAZ1QbauP8511OKtbj0OAOdkJJ-0N3M,5319
|
||||
babel/locale-data/es_SV.dat,sha256=DZ5zGJp04BA99FVtOQIpROt0Mei6Esua2Nw0m48rViI,1402
|
||||
babel/locale-data/es_US.dat,sha256=8_RWSFk2Vj3v0dHc7iX6Ge20ZWX-M7_wYxH1BtTfv9c,25343
|
||||
babel/locale-data/es_UY.dat,sha256=-Jw0bOdLf3LWpBykOF6dZ0nIy0I4alpSH5oTo1AXAWM,2540
|
||||
babel/locale-data/es_VE.dat,sha256=DuMDeGoUvTE_qUGtOUnS7eIpbImIP5x2YeR5KxFRmnA,3752
|
||||
babel/locale-data/et.dat,sha256=pGdCv2OqghUpVp6vOMfldspch91G98i6kIm6eji2FKE,200192
|
||||
babel/locale-data/et_EE.dat,sha256=xpoZTzSn447SsQklqYnKUUL27DkZuNsRpQxTn87Tmlc,626
|
||||
babel/locale-data/eu.dat,sha256=gq-LZDCqk_bt-R29APS4rVYl-K_D3d5sIb5nhjzdZnE,176850
|
||||
babel/locale-data/eu_ES.dat,sha256=xvTtCQUjEml-wPLAZR4kU_hhXZ-j5oIE5MO577tCdFg,626
|
||||
babel/locale-data/ewo.dat,sha256=kZQmUNXQ8t64WMf8lNY9_i03WVdbmJA92_wAMK8p1jc,17595
|
||||
babel/locale-data/ewo_CM.dat,sha256=NirWcwhJ0SSdkIex0afT1IDuwyfJBBcfX7CGnJNIOAQ,609
|
||||
babel/locale-data/fa.dat,sha256=qX7byceg8QHSgGdOQuJlOPvw1G7B1V7Ge5d_cieSwnI,217724
|
||||
babel/locale-data/fa_AF.dat,sha256=donKj3WGTXbFV1upg-DOI-7fZgrLoUZjL9mQrj58NDo,11247
|
||||
babel/locale-data/fa_IR.dat,sha256=ZnDClkeVc1IPiEGa63b7BhvnhklUhgige3sTjeEK6mU,651
|
||||
babel/locale-data/ff.dat,sha256=fFDGP7W7WqzDGCEe5jMrIWsD9ODm2h_4iZobPVhcRRc,16084
|
||||
babel/locale-data/ff_Adlm.dat,sha256=ZuHELP4Qnng1f83guWn-4zQ2QsIvvJJfQh_yT-VDgv8,174659
|
||||
babel/locale-data/ff_Adlm_BF.dat,sha256=7b8PdK1LA0V-odNH3iwuNDDR1vQYQhXvHp-5bB5ZwLc,610
|
||||
babel/locale-data/ff_Adlm_CM.dat,sha256=32kFf1KDw82I2SKzaVB4P8dBfmkw_mmG6fYAuThS99g,629
|
||||
babel/locale-data/ff_Adlm_GH.dat,sha256=90UIh5AUwO8eqvY2d7MzCmPwJ2XNFfAMfHqqEr-QZio,1209
|
||||
babel/locale-data/ff_Adlm_GM.dat,sha256=NqlOMO7KDanw-Z-dnG4jSX1SUESFQrNG1MVCMutQs0w,1205
|
||||
babel/locale-data/ff_Adlm_GN.dat,sha256=VAK9og8mz1WVXD9RnykNOiKkC69nIF_gGgkwKensMX0,589
|
||||
babel/locale-data/ff_Adlm_GW.dat,sha256=_BVL7y6irTvBSRhVMmICwv4uNllP5nxIqPGpU5i9sCs,610
|
||||
babel/locale-data/ff_Adlm_LR.dat,sha256=UYThYdKlKFe4XX52x7WO2xmkiHA9heV9E3K2Mg0RP6o,1205
|
||||
babel/locale-data/ff_Adlm_MR.dat,sha256=anYa5CmU8BiiYRz2nL12UDCwLJIsUIbZqajTFSYmvd8,1206
|
||||
babel/locale-data/ff_Adlm_NE.dat,sha256=EmZR_KWVdW7b5TxkRsivHLoYKwHU029v-R0k7zieWQs,610
|
||||
babel/locale-data/ff_Adlm_NG.dat,sha256=OLPxRiTM2InmMtH2gCRJRhbmwhawtdSR--6001ckT5k,631
|
||||
babel/locale-data/ff_Adlm_SL.dat,sha256=DE0siwIkfETd-Pd5nvDRWK5F3_55bSYpJFBZfYKHquE,1206
|
||||
babel/locale-data/ff_Adlm_SN.dat,sha256=9USLkiIrnIVKikQHcPqyF0bwUqc4OiAm9vDisk9boyA,610
|
||||
babel/locale-data/ff_Latn.dat,sha256=byAYS1KDI0NXZf0r5uEtjiW_dvH3S7nniynJX6jR30w,839
|
||||
babel/locale-data/ff_Latn_BF.dat,sha256=NNCmS9PhIhnRzZlE6Zn7Sjt560T_zY0oAGvs-wkJQjo,589
|
||||
babel/locale-data/ff_Latn_CM.dat,sha256=-vhCSM41OmNfJwpW2ArLlVSOBAmbxI4qkdGrOuG7jxw,608
|
||||
babel/locale-data/ff_Latn_GH.dat,sha256=rAV1pDUEzSqrxYJi7c_bB9eVweCRaIzw1qGZkBw9HB4,1188
|
||||
babel/locale-data/ff_Latn_GM.dat,sha256=_xfcaqyGrO0UdRy19lGMjo3X_jk_MGCMSvgQjfyL0p4,1184
|
||||
babel/locale-data/ff_Latn_GN.dat,sha256=cdoXME19UJX1H7WkepaiJEiUql4zOY7h5uO8GKQoZ_4,609
|
||||
babel/locale-data/ff_Latn_GW.dat,sha256=lIrg2frFHCvM8guhuR5OmGU9Np_yUTIcORKQITZSFYs,589
|
||||
babel/locale-data/ff_Latn_LR.dat,sha256=Lg_t_ANpKoAXV_TeCGXpGFZOnmMmYIdS9GfylT6Y6h8,1184
|
||||
babel/locale-data/ff_Latn_MR.dat,sha256=qhCUin06n7Ow841YyfQ_aYJnDB1gCwbh3A-pozV-75s,1185
|
||||
babel/locale-data/ff_Latn_NE.dat,sha256=vYqMUR9LCykf0H_rTE_oeS9fYK7t-ajKpbK1IpF9-Cs,589
|
||||
babel/locale-data/ff_Latn_NG.dat,sha256=NAMpFyNWE3dSzIwJTRBwH2SUhoJlu_AzinAtCByfyJA,610
|
||||
babel/locale-data/ff_Latn_SL.dat,sha256=AMk0G4KKcrT9Yh1902tRDC8JBwXHRDqRgOcw6W8Ne4o,1185
|
||||
babel/locale-data/ff_Latn_SN.dat,sha256=Idf9JfDjAfWlKouD9gYB6m6_qg9P9xUIRAgMQ5O1-Lg,589
|
||||
babel/locale-data/fi.dat,sha256=mQkPOSvYmGw1T0FjSrtJ0vgGOZYYTV9Ixz8oTvfFoPQ,227195
|
||||
babel/locale-data/fi_FI.dat,sha256=CqHzlsNe9s14gZWMaUn9abl4FmLAZknXRX1lP5Pdrc4,626
|
||||
babel/locale-data/fil.dat,sha256=xZADFjoyLySL2eXDQqLicMAFPoaRfdLo6KX-DGk69hY,179405
|
||||
babel/locale-data/fil_PH.dat,sha256=U-tLxLn0lDKKpUqEQPLTumOuJOIYi80HvPnUk2SsObY,609
|
||||
babel/locale-data/fo.dat,sha256=c3gHwJxgpzyEo5QTL_VGVE14Ledk5QJdkedX9a2LIIk,165657
|
||||
babel/locale-data/fo_DK.dat,sha256=V7Kq03gQkns2EDztSyIiRLr80EtZsGZnmoYPsChW__w,647
|
||||
babel/locale-data/fo_FO.dat,sha256=WZJB7n6uQpGsPNWVXqP851OGZd5RmfSMbQ-s_C-00tQ,626
|
||||
babel/locale-data/fr.dat,sha256=PuqjeWNTBK-3hLx2xl3WMzDRjOsHSvq3s9pi9OVRYPk,225342
|
||||
babel/locale-data/fr_BE.dat,sha256=QW5XQfg_MDjZQazIkAJTp19ZeRRYLEwTP2Q6ix3W3C0,1254
|
||||
babel/locale-data/fr_BF.dat,sha256=gVdej2f-lrFMVDjQNCma1-odtbYzezlFw8YR16ZuMas,589
|
||||
babel/locale-data/fr_BI.dat,sha256=hCmnp8GizMpXqkYPSnRFUMb1ltL9xT1aIHUOt8uzR5s,610
|
||||
babel/locale-data/fr_BJ.dat,sha256=CZgeRt0F7zcnCbuwouXBxTg1Ht6M4UpS1JYNgdnGZOk,589
|
||||
babel/locale-data/fr_BL.dat,sha256=mN3e240_oM-t97i3jZ33ptBFR3XJFtq2519QXQskeDw,589
|
||||
babel/locale-data/fr_CA.dat,sha256=hUfSdAwXBvfuhc3dFBmHdmgllVG8dmH62gsD5jYn80U,65858
|
||||
babel/locale-data/fr_CD.dat,sha256=KqBJ-62QyyMteiPxaihTP7AZAbjuoZothXcV7YBv9cA,1106
|
||||
babel/locale-data/fr_CF.dat,sha256=zElh_1aCiSapkL83eytl19hKu0R6lrE3xmb_a2lf_cM,589
|
||||
babel/locale-data/fr_CG.dat,sha256=XqZxi9XodrhYnQqagiCv8zc51Aqv8S_E3AKgZxPO6QA,589
|
||||
babel/locale-data/fr_CH.dat,sha256=MHWdTsv0DY1KNjVQCSHuEOa1PQ_Mtbm0b3mThVRXkzg,2970
|
||||
babel/locale-data/fr_CI.dat,sha256=PULA-d30mWwNN2Zsg_58tbUde8ljeA7ej6_bQSvyngM,589
|
||||
babel/locale-data/fr_CM.dat,sha256=sA21F_q-PMRWez-fKSoxNz8yyaTtxBg78qRRukmbMR0,2083
|
||||
babel/locale-data/fr_DJ.dat,sha256=retYu_VKqCAemcxMH2ieVzYXLQDnM6-FkxJLfRksBMg,1205
|
||||
babel/locale-data/fr_DZ.dat,sha256=lT9Bd_4OA78pLByWz-ub9pRT4pfKANUsAG9Gk2NhTtU,1247
|
||||
babel/locale-data/fr_FR.dat,sha256=oucSQVTi8gnvWNQ07WJPnYh1YQRxbYR6afhy8Wd2YgI,626
|
||||
babel/locale-data/fr_GA.dat,sha256=hjGGeVpmPCTxP7LEMxE_iUUS-uSfRnY3unJ-800ilGk,589
|
||||
babel/locale-data/fr_GF.dat,sha256=FwIBhmnYvA-VIAgc_n9JLiENGTZMXFANqyFFpeNjNYc,692
|
||||
babel/locale-data/fr_GN.dat,sha256=BIJ_Gl1Yp5fVwQNISO_f4o5U3vgOWPKB-4UWMjp_SMw,609
|
||||
babel/locale-data/fr_GP.dat,sha256=7IjXNU_xYD73C0EaZ2IWMxZ8kzIFRLWgrE07-xHFB8s,626
|
||||
babel/locale-data/fr_GQ.dat,sha256=zMNFOsgv_5JFDvnqB6AovINlxEdr_QYBGw2Rl6LsdGM,589
|
||||
babel/locale-data/fr_HT.dat,sha256=FIn4weL4_b_phmnIIQFDdwhqY3UFaLITSGKAZh_sIJw,1873
|
||||
babel/locale-data/fr_KM.dat,sha256=SaUGzyArQSXa_pwsb9hw0_fs1TjcZq7o2CFW1mAfvQk,609
|
||||
babel/locale-data/fr_LU.dat,sha256=OZ6lHBdT7fHpiMgMaIEJhNB4ohZVMZRQiJQT98n2gLE,687
|
||||
babel/locale-data/fr_MA.dat,sha256=7-FeaIFIZGfbunjR-M-lTr0WkTGljmC354Iadk3_S-I,1277
|
||||
babel/locale-data/fr_MC.dat,sha256=se81gvlIKgey2DgfCYayuXiwV0Wykw-QM4otwduegCQ,626
|
||||
babel/locale-data/fr_MF.dat,sha256=asOP0aSNk9sx2Jx3R5QigjvOQmgEzRP0atpznWTZEII,589
|
||||
babel/locale-data/fr_MG.dat,sha256=GL58hdcr_DZePturTSmv-8WScEg60WajuKuijeBs5hQ,609
|
||||
babel/locale-data/fr_ML.dat,sha256=x_UkTI0saDvoYCiYdNF9CWoyc1VvMAQFBw8APjCEL78,1126
|
||||
babel/locale-data/fr_MQ.dat,sha256=v3tmYxQ45BkuVen2er9vMsxTceL196E98XYPsGWKXTM,626
|
||||
babel/locale-data/fr_MR.dat,sha256=0qY-kxib1lGMlxGNcyjEZwj7BV8Da3CZq8DGyiRbcrM,1185
|
||||
babel/locale-data/fr_MU.dat,sha256=UVc2y4RDe6Jy6_48f043AXBUqWLvktTjnj2osTeAJO0,609
|
||||
babel/locale-data/fr_NC.dat,sha256=Liy4q5CQx43KEep69njgxfUENHEJRfXaZJlsK_UcIbw,589
|
||||
babel/locale-data/fr_NE.dat,sha256=beqoAaHiYhcvUeABHOBD_9cJQ01DQzo5nbAZb5JZb88,589
|
||||
babel/locale-data/fr_PF.dat,sha256=mSlv8dzrvNyo9XfC8yczKIKGaEPGTIpf71Oi1IH_f78,589
|
||||
babel/locale-data/fr_PM.dat,sha256=yukgtaee7ROFoFHM7dUO9CSYlCmipm1i5ZEIsbvvP0o,589
|
||||
babel/locale-data/fr_RE.dat,sha256=IN73Uw9cZdifS4rK4SfWiecLcAX0R2F4j1aV_DusCUQ,1142
|
||||
babel/locale-data/fr_RW.dat,sha256=b6cY_0EAjkJjlLAjdYr7o8vkdzB0sQbIgwgWsFlaO1M,609
|
||||
babel/locale-data/fr_SC.dat,sha256=ejzZtxh5_XDx1B0oZFQx7oDpuuxAsmNp1mYxGtnRs34,609
|
||||
babel/locale-data/fr_SN.dat,sha256=AzbXwg-QV0b_-M08HrFFVoi0CvQSW9tK-rNHQ-N-9d0,1277
|
||||
babel/locale-data/fr_SY.dat,sha256=nc1VVE9d1H23_Kppl-NQLCOyQHhUc3hVpFvIHKFwZ1Q,1247
|
||||
babel/locale-data/fr_TD.dat,sha256=sUvrTreI6gzMwlLxXI-uLQmmO3bSFSa7zgdrxQqH1_w,1165
|
||||
babel/locale-data/fr_TG.dat,sha256=GWo6BaOsi8-YZfuWYIEDMyodmtktbkK54R3fNEwvsNY,589
|
||||
babel/locale-data/fr_TN.dat,sha256=0OMk3LdpZvhd0ZFbYRh2ioViNakNsBe8DQIbGnkCeQo,1185
|
||||
babel/locale-data/fr_VU.dat,sha256=yly1_BvKQwMXPMXZSc-ZRbAZ04qjatwiNPrglkTge_M,1185
|
||||
babel/locale-data/fr_WF.dat,sha256=_LOp9Pd-uVPzUqTOLmdKAVmqdhJSc9TQxN-q0AvFZMA,589
|
||||
babel/locale-data/fr_YT.dat,sha256=M-OawlEGCEqzxMFehDb_3Ofb76HA6nwXEBFBKEi4qMw,589
|
||||
babel/locale-data/fur.dat,sha256=kBxHiHga0PnTMJY38zYNV29C6Y1hw44T2qazrXRDBQE,35027
|
||||
babel/locale-data/fur_IT.dat,sha256=-jYgvCMGoV9qmo1lNuPbfFhw2RiwM9-XrMAaisqk3ck,627
|
||||
babel/locale-data/fy.dat,sha256=cNAuTsUGZ03hww_0oz20axWibvGvrSc_qtjNwX6qT30,110221
|
||||
babel/locale-data/fy_NL.dat,sha256=6kDdfEWgZuA0BeiB9BM8qhtPVPqUB4zBkpQBmEulOpU,626
|
||||
babel/locale-data/ga.dat,sha256=BWeLf2Ib-AwjhXVaP8Tj1Np23kyKwpOBuNTOIjueIAg,316865
|
||||
babel/locale-data/ga_GB.dat,sha256=DVKT5Ub0mvXWADwJua35XUCwxPrRj8olUR-xGv9x07A,626
|
||||
babel/locale-data/ga_IE.dat,sha256=cCW_n5mlSTNu6JzFj5bZMiJbEXFiOHH8BrCB4MnAi5Y,626
|
||||
babel/locale-data/gd.dat,sha256=11GEkGyo2nBzMBCd7vfzaif9d_xgR8KIEvJmPrAZ_Lw,302010
|
||||
babel/locale-data/gd_GB.dat,sha256=6VHHQkNfDnsLrshZ5VM0AvbuOmAkVWFf6KIBK6dXxhk,626
|
||||
babel/locale-data/gl.dat,sha256=VdJBH1gVlN8SYNhZOZ8-h6svbEAMapF4HVOtgqFXQ44,176367
|
||||
babel/locale-data/gl_ES.dat,sha256=taQiFoK4jse9XR19xt95xT_BXnzftMPMJgKk_ZIh1xg,626
|
||||
babel/locale-data/gsw.dat,sha256=BZgIpYmp-FUl1rjUf0EG_pUQERu1aQb9kvqIOG_LD-k,108049
|
||||
babel/locale-data/gsw_CH.dat,sha256=oNDsu5FZKmaMx0q94MsggWUHYobgGv6lNNwqRbm6mes,627
|
||||
babel/locale-data/gsw_FR.dat,sha256=4rf2w5Q1j3qezQ5Jf1-0qkY3K2Yk-ArQBBFCciWNfiU,627
|
||||
babel/locale-data/gsw_LI.dat,sha256=4aFdXjXWs0W3IE-cqe06PKFdB1l1MbQre8NY2sm3lWM,627
|
||||
babel/locale-data/gu.dat,sha256=Bn86qx8SplDJcC2V5jLIOeAavwh7EWkDZEAKz2nY92Y,246649
|
||||
babel/locale-data/gu_IN.dat,sha256=4mup-pKABihWun3Ougbz8HiGoXtPDPdAqAKMBma7Gvg,631
|
||||
babel/locale-data/guz.dat,sha256=bzP0aY17_xjZaiVCMTACE8ThMfl9HcD-ICcMFLjN7B8,16016
|
||||
babel/locale-data/guz_KE.dat,sha256=S-xrYnojrbkIXv_AMMaLR-0Et8CtW6Ty3FDkikLYqS0,609
|
||||
babel/locale-data/gv.dat,sha256=lWBEcD66RJTHCg0L0uUEk3twf9iApg0VHCUvCmUGNjw,4146
|
||||
babel/locale-data/gv_IM.dat,sha256=32eF8Qm1U-NzDs6CsC1a5G40zereETci2vy066Dq9m8,607
|
||||
babel/locale-data/ha.dat,sha256=YZzU6hOiWG1eQjBfS8xKzG8FLFYroDh0wMIQnp1xnV8,78016
|
||||
babel/locale-data/ha_GH.dat,sha256=WAVJ2CogGv-7o3KHNfd9YIThisXhPcKkOCStIkCJYOo,1188
|
||||
babel/locale-data/ha_NE.dat,sha256=4LR2guLb66Q9ptMpxPP1o9RoCbMUvWh0xdbfOtOg92Y,1248
|
||||
babel/locale-data/ha_NG.dat,sha256=7ArPguvlMmsMd_KuhyAy5K0PTuvdzDgbCrmY5c3hyKk,589
|
||||
babel/locale-data/haw.dat,sha256=daT0jGNbH-c8-byXW8Ev8k7x6FxWzWzM4kwyGowZrgY,16106
|
||||
babel/locale-data/haw_US.dat,sha256=0npKxik41EG4w134GeOKBCqQiyn4W_4RU9Xol9An9vI,627
|
||||
babel/locale-data/he.dat,sha256=B0Bypmykcuj6aTi6m1EOjpPExBZ_wQewVW3AYFRYaiY,271008
|
||||
babel/locale-data/he_IL.dat,sha256=tv1zu6LbE2qFr5KkxegGM6sl5YjsHeOohznihTWqul4,651
|
||||
babel/locale-data/hi.dat,sha256=R8gru5lLOJotWFqfLJm7RLkQ9F_k82wCa4KWk0XRnXo,244568
|
||||
babel/locale-data/hi_IN.dat,sha256=laF8SEGi7j2jIwdbvx9jumoN_ZSlsmM2qct5Qpdzy8g,631
|
||||
babel/locale-data/hr.dat,sha256=_Bnj62FHBemVoPsm6v2atZTwG_4RgIvKCN-UOxpyMj4,247517
|
||||
babel/locale-data/hr_BA.dat,sha256=cb0WcMYeSmL0iyadbeYGokENF3IdPgPG8Ir3pt2QWhI,1161
|
||||
babel/locale-data/hr_HR.dat,sha256=FBTFejY7tzVjCu1TCX5PtUIXfhL2iN0DukagJf7dS6E,608
|
||||
babel/locale-data/hsb.dat,sha256=7JQcT8q6VIK3yOG2Jx41ksSJj2G_oqcrZH3UXHS0jvo,179178
|
||||
babel/locale-data/hsb_DE.dat,sha256=mJpofwRoSQoD4uMNdi0xcLP0qyq0IysbE2VkXNYniug,627
|
||||
babel/locale-data/hu.dat,sha256=0Gvk8Gl8uJtKpPezPTWfR3XX2wkDKIRQsPuTTAYcahg,192963
|
||||
babel/locale-data/hu_HU.dat,sha256=KndrzgNop55GlUso27Dfpf6rW3RA7YhQibwBFTzufk4,626
|
||||
babel/locale-data/hy.dat,sha256=cx7Ap0eLvzTGjVGdK30x_8TLZ5QLsFgbCnbqrYu4s8I,214313
|
||||
babel/locale-data/hy_AM.dat,sha256=4HM865GP-TvuBp3XjB41rgc1QuXLLITSt3skVtB0QHA,608
|
||||
babel/locale-data/ia.dat,sha256=kIIuryj5kmGxdG2NWtOdPOezBSO3NQGbCVI7dl1Bndk,112822
|
||||
babel/locale-data/ia_001.dat,sha256=onWUTi-JeTzCyFGYj9VWyvYFnE-0w59rnsDeP3WZfCY,914
|
||||
babel/locale-data/id.dat,sha256=_jTwyiD3gWQWvaU0Re3tJ6nQI0BEmeQzc6AL2PTBZXg,163265
|
||||
babel/locale-data/id_ID.dat,sha256=Q10Fz7etpCtqpGmEOzhzIAluNUViuPV6fJ8Ibp4TMDw,608
|
||||
babel/locale-data/ig.dat,sha256=-aYZuS7od7VW9iec3iOwyWRKdHtdxhISdJIIkeLLgB8,52036
|
||||
babel/locale-data/ig_NG.dat,sha256=qvl7ZtJLFgRf6Jbys3rPutuwKL0nImrLIyI2KxDJNMY,589
|
||||
babel/locale-data/ii.dat,sha256=crBpYsdPGu1KoOSjCWHUy67ssD13AfvmK261h-VRMhk,12588
|
||||
babel/locale-data/ii_CN.dat,sha256=NptEx8Tehw_ZnxhDc7qbpFsDxF_2Dxjx403D2fg2kKA,608
|
||||
babel/locale-data/is.dat,sha256=ltT4Iwckwve2QSs3Z0MzA1x4KXXK66cFUOcRnlLDG_g,188046
|
||||
babel/locale-data/is_IS.dat,sha256=vkGTcivdc7UMK2uv1QCKnJkoGh1cFUyK877xmLKNWfQ,626
|
||||
babel/locale-data/it.dat,sha256=7JMCTHE2jVXjGEkfgmmFdwlQbKCwRo1PfTecsagqfVg,188460
|
||||
babel/locale-data/it_CH.dat,sha256=aBS-dqAT_jYf8DFLYCQJ4A4MfLi9u_rAekJ5fU8eTLs,2776
|
||||
babel/locale-data/it_IT.dat,sha256=EPq-ZuC7fD9sVQNf7K7dGReI7pvxix55SFteRJlEheo,626
|
||||
babel/locale-data/it_SM.dat,sha256=gpwEWv5kVspUSBElJAoge82X76LK1lsgxShdk_BdxwY,626
|
||||
babel/locale-data/it_VA.dat,sha256=drgEDlw3k2saTMXzEz5-BkkHgCCdnXVQ-aiCHUMYAUk,626
|
||||
babel/locale-data/ja.dat,sha256=m8MJqRkZ-VMiUTOqi0zTmQe7CMDT5pT_Vj8Ek5nbyG0,200287
|
||||
babel/locale-data/ja_JP.dat,sha256=fqV-tzCjVKeIhB1TH9R2vsz_kpEwD2KSdYUMOL2zVQY,608
|
||||
babel/locale-data/jgo.dat,sha256=eEw-8GRRYT4SB36fdEfaLJX76RKeEhJomcYa7wl3WvA,12628
|
||||
babel/locale-data/jgo_CM.dat,sha256=4EKGSIDydn6xezIwTpMhOZFnheOhhMWfwadqa9rRRpg,609
|
||||
babel/locale-data/jmc.dat,sha256=q2xbrOlR1h4dKkAb5f-FFeG1yY1zAO6vZ2PqN9tgTLs,16068
|
||||
babel/locale-data/jmc_TZ.dat,sha256=bpvlP-1bAXEnvIRsPxFHel5X-8eLxF8dUOlkJctN78k,590
|
||||
babel/locale-data/jv.dat,sha256=LaOeOox55UzDPRCZzpKBtS91S8visMnBQiwFsKvcuYE,129461
|
||||
babel/locale-data/jv_ID.dat,sha256=H5wi4GL8eID9c2QUxpz6qpFn5ORgdpE2mjYxdkozJiQ,608
|
||||
babel/locale-data/ka.dat,sha256=isStz_8QWtbWBJidLjlvr1wqrm3DJHYSLoeZkpzJAy4,260705
|
||||
babel/locale-data/ka_GE.dat,sha256=4G3wWIQOIZM5Z8r1Px0d4DvTOMwbR4Ubvq4expe_gY0,608
|
||||
babel/locale-data/kab.dat,sha256=-rQbUS5U939yjCgkQd9aA4PFolU4h3cZnP1brEqMLRA,135263
|
||||
babel/locale-data/kab_DZ.dat,sha256=KbrMqfLO_TlWJlCQVmK5IjqCwVppZUryATx2Rq5YTaE,652
|
||||
babel/locale-data/kam.dat,sha256=lr-AmdEqLfe0Asb3wwfFYGjzMMqobCr9-ZyDb8Cg-YQ,16175
|
||||
babel/locale-data/kam_KE.dat,sha256=vfQX-o-otm5WDwv2qrHY1lesX-AQ9cX_2HW-nO820AM,609
|
||||
babel/locale-data/kde.dat,sha256=iV4F5CHX9rYrt0R_iioeDnTv21snL0t8hZ95QNcGMBE,16475
|
||||
babel/locale-data/kde_TZ.dat,sha256=RdJ-ovdj55xBfaOc5mE41fqsNdLN_7oSIOcyq7-aApQ,590
|
||||
babel/locale-data/kea.dat,sha256=Wf1pAdN0uMYvlUpOiQdLgMvvS03rkpkdDwU-P8XzvWA,85757
|
||||
babel/locale-data/kea_CV.dat,sha256=7lbONkE-y9_doiZJxjyGYM50Yz41JNGwy7dV53vvhEs,590
|
||||
babel/locale-data/khq.dat,sha256=jmjjC1r6-Cxur_0Uh_WXk92MBgw4fR41PzwlhVnr3qc,15939
|
||||
babel/locale-data/khq_ML.dat,sha256=CbrIcKwmxw5THhW-nZ-sPFZjsfgpHZUDl-hhWH2toDQ,590
|
||||
babel/locale-data/ki.dat,sha256=abQFXbMy9mdR96-Nebj3PL4_frRUGAEcsk3_-DQ0TYM,16123
|
||||
babel/locale-data/ki_KE.dat,sha256=-fcVNnw6zrxr3Bw7mi-vpkzP0v4v9t2hkj5ZEuG_5Zw,608
|
||||
babel/locale-data/kk.dat,sha256=V4lqjiOozZQv3Zwukg1UlrXhsuDx5u2aA_k--eEsVAM,210242
|
||||
babel/locale-data/kk_KZ.dat,sha256=DhjfmmZRmr-w8q98Mqr8h_v2hosJAjTtTFo53E3QGQY,608
|
||||
babel/locale-data/kkj.dat,sha256=466fsXBV_YSBSPGZx0z2FYvYrU8Ql_QIIZjXfNGv4KM,4888
|
||||
babel/locale-data/kkj_CM.dat,sha256=KY8LZH7ZqifH7BTxFz4ylu4d1LAAxMAD8W-a0gYsjZo,609
|
||||
babel/locale-data/kl.dat,sha256=gHhmdk-As6QszK0V703UfVG9XcDZo-zA-AKfX3YboWs,58200
|
||||
babel/locale-data/kl_GL.dat,sha256=RojeiBiofKUHvk9f_ITt44uxy9gGhxz-sVy6sBn4Zcg,589
|
||||
babel/locale-data/kln.dat,sha256=RvTuZqeDDB_BKquwaUuXRjL89K0d8kcpj5rvD8oaIpc,18003
|
||||
babel/locale-data/kln_KE.dat,sha256=RydM7LQVL9u4kqeFACUbNwf4M8vQQhP0qkKM_oL2oGM,609
|
||||
babel/locale-data/km.dat,sha256=wMIgFZSCkKBp1QkkhFPVEgAof5LuMFxz0jEzIWRdMQY,202267
|
||||
babel/locale-data/km_KH.dat,sha256=xVjkyVxn_hrWpEp6JOzSZKxZFDZ_3UQjRQsVPvBy0CM,608
|
||||
babel/locale-data/kn.dat,sha256=ZnwTJdH60MjTwgKjjgLR_vEUIHFRreimD4eMv1rAA7A,263580
|
||||
babel/locale-data/kn_IN.dat,sha256=Kzg5Bayf-ACbA0Nun8rTGYcbi5r2PmghFxlbyQIiKV8,631
|
||||
babel/locale-data/ko.dat,sha256=5disPatHT9WJa6UOmZXl6iuL0PWplfHyQMjlNzFqki8,175158
|
||||
babel/locale-data/ko_KP.dat,sha256=2Z1Rbojo6MHJGQdInFOjfZHbpRdwvZfM-FU_08oFGng,789
|
||||
babel/locale-data/ko_KR.dat,sha256=y-3hO1aBM61NXG2L4o41zAPNlUvfA3RE14q_8SdarcM,608
|
||||
babel/locale-data/kok.dat,sha256=Ot2FE1ar2aHOhP6L29tqcxHSYoTc46KoQffIDHGkNQM,182871
|
||||
babel/locale-data/kok_IN.dat,sha256=e5cBMZY7kU_9H69kTorB93cUe7xFASM-2hUfGY3A-ec,632
|
||||
babel/locale-data/ks.dat,sha256=0DI2B4YMdtXgQZMQKTKL7FrEH8ntI8NMZuK0wMP35x4,102570
|
||||
babel/locale-data/ks_Arab.dat,sha256=kfXVFhHX_NrcA7tZO6yYXym5wsDvpjma53urJPVeGJg,823
|
||||
babel/locale-data/ks_Arab_IN.dat,sha256=_fjJMmIU0OJMR66po8yq9ByOzZZ3tomRqVt6RM4BJFw,631
|
||||
babel/locale-data/ksb.dat,sha256=SxZYlQUncKnA8ljqLb7k84GzFoGzaV1mhC9b8y03mEs,16043
|
||||
babel/locale-data/ksb_TZ.dat,sha256=2Wzocj-_i0wMu7oi3-8ynqirioha6nG9PPI1-5EMbnY,590
|
||||
babel/locale-data/ksf.dat,sha256=fE1YgWMw1RpxNYkJyieh2Cwm4NCE9FQbM9P4he1cviw,16515
|
||||
babel/locale-data/ksf_CM.dat,sha256=1CFxJU8F4NverN5cPa9xvVI-we8x7wbZgP3UfXVnL0o,609
|
||||
babel/locale-data/ksh.dat,sha256=6ttxGMPLhYNiad_7avsUIF2B7rFuLLxKw3Bv3nB1rsI,88937
|
||||
babel/locale-data/ksh_DE.dat,sha256=vTdZCAi8MAGFb4wE_zjnNTREloPZHNGc38eXQ0uwtPE,627
|
||||
babel/locale-data/ku.dat,sha256=s-_gQdcuJLmxKWYuUftIvv4TSjViNOeLQWiQp4Q38zk,28771
|
||||
babel/locale-data/ku_TR.dat,sha256=EsO9U5XN30PqoR6A-7q72uLJ6An2BMuGbrh6sYrZoFU,608
|
||||
babel/locale-data/kw.dat,sha256=A-aMyXGee3cHKH3Vrd1rP11oz8Mzvrm05B6DB_c7E9s,7242
|
||||
babel/locale-data/kw_GB.dat,sha256=nvzq6ku288buMZIPacs8IGm5rrD0LdzYFZQxBe9a_jw,626
|
||||
babel/locale-data/ky.dat,sha256=5xH7IcsPFiBp80H8j6Se0o2imNAELzqORSyNHqGrm3k,202058
|
||||
babel/locale-data/ky_KG.dat,sha256=I9WGUgCDXB09jIycutdV0trTbhHFKvbM8Cr4_eTvHmk,608
|
||||
babel/locale-data/lag.dat,sha256=r2Ms6wyrXqZ_u1eGycN4gIHvoDmq3LHisiMzAVvoLP4,17141
|
||||
babel/locale-data/lag_TZ.dat,sha256=gB3iS13Egu-2TLYBYwM2xbve9HxMHCQwgoxELuIuxTI,590
|
||||
babel/locale-data/lb.dat,sha256=4jKUN0pdyWrEMhXiWo8iLEKsx_NQppk41f_21Asp7IA,164597
|
||||
babel/locale-data/lb_LU.dat,sha256=oksbNG3kkuxhnrv6goNlYcBj0Oejpr9-ptrmWHF6EW4,626
|
||||
babel/locale-data/lg.dat,sha256=vV3xAg1xWrx9LbkPFxvjeZgQ0w26fXZFPhf6lwBDM00,16434
|
||||
babel/locale-data/lg_UG.dat,sha256=1HeWA7IllosO0gp2T_nevwD0f2CSAx9lMfQYK-JpafA,612
|
||||
babel/locale-data/lkt.dat,sha256=NdUx996UtMv1MiuP3iqWSl8T5QDZV8cfVGxpfgzc41s,12766
|
||||
babel/locale-data/lkt_US.dat,sha256=KoED03rqibBCmXUUHPR12gR0xc9ox489Wxavkf3hJl4,627
|
||||
babel/locale-data/ln.dat,sha256=hXo1sqtv_f1zrGVd9DAyMJPChHy4oxSAxN2yM8WOeiU,25891
|
||||
babel/locale-data/ln_AO.dat,sha256=Df8fip-BEQDkkdNenJMZYVEwNEFpJU3e7TBDFk1GCFw,609
|
||||
babel/locale-data/ln_CD.dat,sha256=cya8q___2YF--XiQKag0Z2j67S_3MXvGMkqjjvao8Js,589
|
||||
babel/locale-data/ln_CF.dat,sha256=GI1_WE8tFKny1XT5c7Vdr1xpgTYtA20qoi-LbfXcNmA,589
|
||||
babel/locale-data/ln_CG.dat,sha256=gR1qJakj6apKRWJfeXchgBbbmOYiZJs-sWBiOVC4giI,589
|
||||
babel/locale-data/lo.dat,sha256=wFheTwOpB9qwdWoEHy0qyUpEPf8zMbKw8tvCc2zpLK8,220343
|
||||
babel/locale-data/lo_LA.dat,sha256=Le3oiQxOdMmSpTmRje_U-gYUmJIgsRuIrll3v9Gvn9U,608
|
||||
babel/locale-data/lrc.dat,sha256=FxK5wDraPcV82EnRK7L8Lc6pOpd9DlOz93hqbBlvp4Q,19021
|
||||
babel/locale-data/lrc_IQ.dat,sha256=IulRzfQLGQNFx-m2GA1E-996l3AmXam6Kb2yxEU7Pzs,1228
|
||||
babel/locale-data/lrc_IR.dat,sha256=Xwe6srYtOSobQ5_3dgtaFUJPpdCzPfqdMdFw5u3h7iE,652
|
||||
babel/locale-data/lt.dat,sha256=eQLIpUDmVcOlDL3RWzcvVlUdsaquYCLxuxbJ8MjTWEA,284211
|
||||
babel/locale-data/lt_LT.dat,sha256=xpcc0-LW9jbhEMcG4_YJ_1Zh8gjMuO_pFWRRl71WVUI,626
|
||||
babel/locale-data/lu.dat,sha256=39-6RP_EimDpNfh7e9Rfh24evWwSEnaSoXTxU4Xus0g,15888
|
||||
babel/locale-data/lu_CD.dat,sha256=NLQ9XNdydBzo-3BIWY7FrESS7yLG1BFyU8wsX_QclOw,589
|
||||
babel/locale-data/luo.dat,sha256=dmxwIb10UL-N2Gx5ymbXU55MakSpMFCGneBfBu5k6f4,15885
|
||||
babel/locale-data/luo_KE.dat,sha256=NEKNpjQX9ul04z2QZGvlKaYQEpG7qpLnz0fraetUD2w,609
|
||||
babel/locale-data/luy.dat,sha256=zIdy-rfqrSkpjJVvZEWb5Eh-kvFHltSyVR4Rr_d-jHk,15859
|
||||
babel/locale-data/luy_KE.dat,sha256=3uCT5nrrTWh8Qcd2-x0vAMbsqdBfLbVNllWdTBPXVk0,609
|
||||
babel/locale-data/lv.dat,sha256=AxTgcKRkQs4L0G18VPpwyKW2f0pgFl1aB3e0AAIBVDM,214988
|
||||
babel/locale-data/lv_LV.dat,sha256=DVQGeBkn2bfyW4oBFSk-FG5YDgYoPrcy4P1i2msqbKw,608
|
||||
babel/locale-data/mai.dat,sha256=TGGQKi7YoVCYMbQcgUkYvWVeHeqPda-wkHv1tdh9ElY,14710
|
||||
babel/locale-data/mai_IN.dat,sha256=lZ93VuH0KWuLZAwFYQOlGidLcq19FwAh5FcTkbmWHIQ,632
|
||||
babel/locale-data/mas.dat,sha256=VAYNJuZSIHxhdo-sjuiIa8lLzVywzE6Pt8WnKsmkjmw,17297
|
||||
babel/locale-data/mas_KE.dat,sha256=H37wvJs04-E8bNfKwZQhqeDajPo6SvpdVwuo3PyJ1AY,609
|
||||
babel/locale-data/mas_TZ.dat,sha256=9JwDj_IR1VKGVgWxstev2mrAXxIodBYOH4UDM6Q3q1o,611
|
||||
babel/locale-data/mer.dat,sha256=OLCqftXJD2C30EM8YVyuLO6qPnMb1PSzlwTYmmpc6wM,16088
|
||||
babel/locale-data/mer_KE.dat,sha256=99Q8eh6kJb1wkSHx_J0OroOC7WZ23Gp5IGAFc-NBQpc,609
|
||||
babel/locale-data/mfe.dat,sha256=W4iO82UorOHb30ajoWPGnDjhjIWUIIr6HEbcWAlg8yo,15117
|
||||
babel/locale-data/mfe_MU.dat,sha256=TFnNwSIFyDkJUAVbw4Y2RyGH5uG4nvbKg8uNubPWXpA,590
|
||||
babel/locale-data/mg.dat,sha256=N388wocbzVzKtwYxGmUZRQ_Xfqdl_8pfhN2EVs191kU,23550
|
||||
babel/locale-data/mg_MG.dat,sha256=cwl6h3aaMkDtvF9Ei8qvlnO4N1FTSI_VOEVa54g3eHs,589
|
||||
babel/locale-data/mgh.dat,sha256=rXDO2pNXJITPslfwWEAO_8eTuME2YyKX7EBsBAIVBb8,10479
|
||||
babel/locale-data/mgh_MZ.dat,sha256=uJyr7jkKxWqYOJ7CmhjAs8AKMOz_cWlojWjFXRj_jPc,609
|
||||
babel/locale-data/mgo.dat,sha256=C512Q78AJ4yDUul2Wf0liRWjQh-GNv3XDENtmeCq58M,8206
|
||||
babel/locale-data/mgo_CM.dat,sha256=T5kZuEQ7hzI616QF05Grrv-RZb59B86medbIafdhrtU,609
|
||||
babel/locale-data/mi.dat,sha256=Nr8tmNRL5KurZuLLC9lojHHjScK_s2V-gCNZINEYmtY,20727
|
||||
babel/locale-data/mi_NZ.dat,sha256=7o2jTlC9sR5dX2mxLI4qjVIr897Xd5keBTxs7a-_DYU,608
|
||||
babel/locale-data/mk.dat,sha256=GIgzd7ykCmMFSFI0nEWeXGuQQYf-0CWvfI8cnLSgAQk,234490
|
||||
babel/locale-data/mk_MK.dat,sha256=DtPgHruh_KrDRllM_vDipwCsbMWzk2bua0lfFsstTus,608
|
||||
babel/locale-data/ml.dat,sha256=YRd4HGpa2b-k6G8EETwwIc_-klPwXhu5MIc9odvPtqg,285214
|
||||
babel/locale-data/ml_IN.dat,sha256=_vPZnTZA2VgZoDi31tfu-tR4uRzfj-cFFVMmcB8XZgI,631
|
||||
babel/locale-data/mn.dat,sha256=Iw1P5tKBu0KAl2JgsbS72Vq99Ye-t9_c5d2oZcoD3Bg,202642
|
||||
babel/locale-data/mn_MN.dat,sha256=gne5zuFemBThyeemcmnNvI751-rsRwCrCBUQ6uvuK4c,608
|
||||
babel/locale-data/mni.dat,sha256=GvLzWZHUo046TkH_05BSwDHFtkPTeSJVEaLG_nvWhUE,14622
|
||||
babel/locale-data/mni_Beng.dat,sha256=NiCHewI8Yl4k7ylwMAZVB7mtk6TZboLcvZl22n9uG9M,666
|
||||
babel/locale-data/mni_Beng_IN.dat,sha256=Lx0qjRdIKxv05uZIp8e9W-Onti_kqLE-bZiu4yEgCOU,632
|
||||
babel/locale-data/mr.dat,sha256=CCiBBjuwlhte5k72NPs7U_fpEqRMcI5PPOZDoO6BedM,246797
|
||||
babel/locale-data/mr_IN.dat,sha256=RkYd5HIWUeP8yK3zFCRWvxvu3FzaK0ta7H1HTQQMUdY,631
|
||||
babel/locale-data/ms.dat,sha256=KFfk5lBMcmtQcWGOBAyTMqEo4Ghf5S8wg3f1MbZt-W8,152238
|
||||
babel/locale-data/ms_BN.dat,sha256=CecewZU-8cYw5zaaIteTNbPOE7FqS_IGj6emNKzy3TM,1257
|
||||
babel/locale-data/ms_ID.dat,sha256=WcRbSIc4fsZMR56iv_9PE24j_rQLUCYPwU7NdEDO7gw,3272
|
||||
babel/locale-data/ms_MY.dat,sha256=8RsVjifl5WL8sXV_aNTdgjqquxny2SsSBXc4KqJuqlY,608
|
||||
babel/locale-data/ms_SG.dat,sha256=_nfWkz663QdJKVxb2AQQQUt_Hhl9bMk7hIQcqpVSPbU,627
|
||||
babel/locale-data/mt.dat,sha256=tnI8T6enmDliuHbzDfAq7Z97GDcdQ1MOfprVbqHVbRQ,78243
|
||||
babel/locale-data/mt_MT.dat,sha256=2vQihLOtB1H_Ca6e9ZvGCgZ73gVlB_RBsBMFOw22cDs,608
|
||||
babel/locale-data/mua.dat,sha256=k5P4AS4jugmg9aNeL2jUK6xoTlRW1DvPz2XMtumjFT0,16547
|
||||
babel/locale-data/mua_CM.dat,sha256=fQm0rv5p23ity5H_pu8jhbHVdaWDpqITuEPRev9q44I,609
|
||||
babel/locale-data/my.dat,sha256=M0Y81MUWIrt-aQVRHA04KZ73wPMvhd7DihayFm9pVmY,210242
|
||||
babel/locale-data/my_MM.dat,sha256=9DsxnFuIB4ImQJmOXpJ0Ujt1zMSUin-KV_a7R-irE-w,608
|
||||
babel/locale-data/mzn.dat,sha256=op9NwjJ4msszz0JO60nljP2t8pWh1jidWAAr9yONCrE,65499
|
||||
babel/locale-data/mzn_IR.dat,sha256=nw-iEKlN_b_C0VzjCY1SCElyqMgg3jQDZ4whD-lJrpg,652
|
||||
babel/locale-data/naq.dat,sha256=sfE12PpbssOaqdt_XWnykuk7rTArRVzg2DHBcAdHblY,16617
|
||||
babel/locale-data/naq_NA.dat,sha256=1Mh98XoWsJgytl-IvQuMXYJlLkYQvvoQ5_rptyu5ZME,590
|
||||
babel/locale-data/nb.dat,sha256=QaUKfFqj6AfimZOOiGI9DOxReUm-Jv6RysMhTdQ6XV0,210593
|
||||
babel/locale-data/nb_NO.dat,sha256=bXb8K_1FTSDsqIXeZu2C0oYPCrTUpX0Y5GxKs3vXwBc,626
|
||||
babel/locale-data/nb_SJ.dat,sha256=kCfUzsB6JilDQnWsVF1CFyg-7Ewq5VOdM-EWC7PJKP4,607
|
||||
babel/locale-data/nd.dat,sha256=_qfCNG-XGpi-qBzGvXKmKHxVu2WspuqdH_8ECspD1xY,16312
|
||||
babel/locale-data/nd_ZW.dat,sha256=szM5GcRhUeN0V1SGix3RkcgDkRNJF7D3BWJMYMOkNlY,608
|
||||
babel/locale-data/nds.dat,sha256=yjSK-CUxMes8T-cNuxynP6Av2MYxnNmn23PsGguUTA0,50632
|
||||
babel/locale-data/nds_DE.dat,sha256=wQlAFyMOkjMYQd9LVFTqLFt5GuntavA1RWhBf6E3DpM,627
|
||||
babel/locale-data/nds_NL.dat,sha256=VPodVrFivmTiPf4v5OZ3Foc0_FaQwgRBuK7QiD8xmhU,627
|
||||
babel/locale-data/ne.dat,sha256=oha7M56GETdAdz6rLbS65qD1oo_w8ab60lDltNGouec,248497
|
||||
babel/locale-data/ne_IN.dat,sha256=Pc3G-flVbWniVZRu4RzMVYB099rVPhUvxUC1TiTCr8U,1265
|
||||
babel/locale-data/ne_NP.dat,sha256=lhhB2jPqSBwBrxK6piIkUD0YHwGUNYdlmqlPBOJhb0o,608
|
||||
babel/locale-data/nl.dat,sha256=Cz1A8HnVqxHnoUgZIy8Ob0Kb_R8a8RbA5jfgO5oLleI,215801
|
||||
babel/locale-data/nl_AW.dat,sha256=6gmsswLqSrJ0XRfJJguCU0QFSU_dTpUOlPanbq5KGpM,611
|
||||
babel/locale-data/nl_BE.dat,sha256=IZZy26NCmKbOgbU-ZHHeviTctmUMFxmBeOmloDOCN6c,1835
|
||||
babel/locale-data/nl_BQ.dat,sha256=E39EYJYegrYGpAdLuSfkizgwgoBtfyRp-1Crb_I5PkI,608
|
||||
babel/locale-data/nl_CW.dat,sha256=Ho1si5eWdnrkT1_OA7ZWxarnzgfNdUmTlJLUkynzNck,611
|
||||
babel/locale-data/nl_NL.dat,sha256=kLT_7mliQl_5XhGi5lU_guTBSD6V-DUK92xhdWQxzjk,626
|
||||
babel/locale-data/nl_SR.dat,sha256=VVLYKCz48vdDn000ZzlokZnD1Qr1T7Tmn47j2wPG9fQ,669
|
||||
babel/locale-data/nl_SX.dat,sha256=FTjEPrmwtpu8IQVixzrdl0dEyAH524Ml8cWUxd0pvjE,611
|
||||
babel/locale-data/nmg.dat,sha256=CTnRxMH09auUbe_gky2WT9aYX7OiS_3FEXvxzVDH2-U,16189
|
||||
babel/locale-data/nmg_CM.dat,sha256=4wv7ftQl9xu_DkfdjxoJ97gcm-pMhM51OCXYX3CQ6gU,609
|
||||
babel/locale-data/nn.dat,sha256=5rU8EBZu8-b1HBGXSeaeEiPItaYqKWupiG06aTbIBgE,179884
|
||||
babel/locale-data/nn_NO.dat,sha256=yc4l2fwSD9fD1-sCQirXzrAkfxIqD_garBegapCzWs8,626
|
||||
babel/locale-data/nnh.dat,sha256=jO3oG64qBHal9MpjumyI90ETg9LoNJ8CuKliElSLnHk,6766
|
||||
babel/locale-data/nnh_CM.dat,sha256=azweVaEFbSCMHLptoZQ46yKcr_antYfr2pRmxIuZQCk,609
|
||||
babel/locale-data/nus.dat,sha256=x_agBjiW-ZVuFQenH9AT5Rdn4TbFCJoL8n_N1AbmXBE,9153
|
||||
babel/locale-data/nus_SS.dat,sha256=XQQtE8pKShDclBfN4yU1Rh_zEqrYFVndB-t2ScdGGUs,590
|
||||
babel/locale-data/nyn.dat,sha256=PIizZE2pabGtsXhhg6TFiv0OlM352lMKqO2Fb-Wrizo,16275
|
||||
babel/locale-data/nyn_UG.dat,sha256=i2Qcu0KO73WK35o2BvnFV9yd6dLK_p69_LtbVTMkCJA,613
|
||||
babel/locale-data/om.dat,sha256=agj_n2fMWPhqLD3cZ3Pkux0y6b9r64pXXBQcl1nB5Bs,16588
|
||||
babel/locale-data/om_ET.dat,sha256=MhyQf6WK9JWcW9TuiTrQwo2C8tKIELtGKBiJ5Scrt1A,608
|
||||
babel/locale-data/om_KE.dat,sha256=A-EqNdXkq-j_TZK182yI6rnZYaFGGgAMyM76Q68FdG0,1566
|
||||
babel/locale-data/or.dat,sha256=-VmSkqqCokDThjp6Jhc0ENRKPAU1Gp3W0NkZfbiOwUA,241213
|
||||
babel/locale-data/or_IN.dat,sha256=tUmTnuoY49gDDU8WbdUCLyhv_2Yo-JJc_iTZlOJrH2Q,631
|
||||
babel/locale-data/os.dat,sha256=VRCyHyBI0alMKelyuYpaQw5Z3WEEZxkN0-GC039oqf8,17627
|
||||
babel/locale-data/os_GE.dat,sha256=bGm3R8Bz7k8wmb2GK_Ol83ud254rlJMbs26c1zN0w4Y,608
|
||||
babel/locale-data/os_RU.dat,sha256=A2armkX5bdC0hKe6ie0WxB1IB0exTMHAZWk_0PNjFD4,668
|
||||
babel/locale-data/pa.dat,sha256=oKoR7WJ7Ii8MNYowoXnZ8Lsgbgw25NPBbDYkgVEMPkc,244684
|
||||
babel/locale-data/pa_Arab.dat,sha256=T7-060vg7GELKQvqGl2tfZSn5_eN4dqGS_gBwymurvE,3984
|
||||
babel/locale-data/pa_Arab_PK.dat,sha256=-x9ycmOmzJ0ZIzy8J1ryO7nhRuBceY7ravgHBLEgyDY,608
|
||||
babel/locale-data/pa_Guru.dat,sha256=risWFebHubet9zREjGQ-AIrrtBdOtKXo0yafgX6FhJU,1249
|
||||
babel/locale-data/pa_Guru_IN.dat,sha256=tyUJVyrhCWckcBP10pfvLg2Xgv9shPpvWBaSiXg-G9c,631
|
||||
babel/locale-data/pcm.dat,sha256=e7YrXsfssCZkE5qlRy1BRYA4CPZOUiWsrSoYchqqpYE,174311
|
||||
babel/locale-data/pcm_NG.dat,sha256=E8wPtqkOJFSjTkU6T9V4RCZcer0Vc52PBvZ_LioI3S4,590
|
||||
babel/locale-data/pl.dat,sha256=OP4mD1-bddsjgwLV2FSJgpTAnlX-2rATEv4qHqdxnQA,236139
|
||||
babel/locale-data/pl_PL.dat,sha256=V62k9TTJ4FpN6KYLXzlsBBAMjHXnlNFuBnGoY9TBdDc,626
|
||||
babel/locale-data/prg.dat,sha256=1lqaf6Rcgbak-QLb0gFocafAWd3MXC8rM6Zcgn5ct00,20167
|
||||
babel/locale-data/prg_001.dat,sha256=m1nhpZ2Lh8TiVNCuKOVyBElL3M0Q9YIRZSC19jqZymE,1567
|
||||
babel/locale-data/ps.dat,sha256=ln_T0uNZqoPpDfA0obDhJAG6L6YADt_o66ZyFxdx4l0,180248
|
||||
babel/locale-data/ps_AF.dat,sha256=goJChlJTUKnh7pZiMUkZiRMMth5lshKHVDZFwKq3Iwg,651
|
||||
babel/locale-data/ps_PK.dat,sha256=_MSs-UxrpD1DJvl72MouRRhRmYbE8F6-MQ6q7ansCVw,7954
|
||||
babel/locale-data/pt.dat,sha256=xNKXRfbr-VRWZ1xT_p_gx99OW9I16x9Wgf2NyvP7RXk,195079
|
||||
babel/locale-data/pt_AO.dat,sha256=cTQSDeLXeH4NvRK6Kydc1LB3QyQO9qOSwh4UE7Ngga0,995
|
||||
babel/locale-data/pt_BR.dat,sha256=PoV5yebMbOhPwgtPQJ4qoKxOhQd3E5NCYcjjgOsvqu4,608
|
||||
babel/locale-data/pt_CH.dat,sha256=aFs_w4Xa1ZxFfw0GnV7IAj92XFa0xpK9mN4uY4ynDho,626
|
||||
babel/locale-data/pt_CV.dat,sha256=G5LMZLQqplotaUIvlv1iR3hgaIkwsYhMK0TXzjrmIzI,1015
|
||||
babel/locale-data/pt_GQ.dat,sha256=mQbJaJxvrVnC7MaTHD8r36VIe7vTfJfudKJc5XjzFg0,589
|
||||
babel/locale-data/pt_GW.dat,sha256=DTJrtZaU3wXwYHJvKkJK8BAZCcT9fSnsspJ25xuM4Po,975
|
||||
babel/locale-data/pt_LU.dat,sha256=rgoGwpHgeahu8nLnT-uyVsrkD4CrWWwTCqDct0NBJmw,645
|
||||
babel/locale-data/pt_MO.dat,sha256=gkvSsQQWHZFLT7SALzaYT0inBlWKH2tTt3R1KDMXc5g,1592
|
||||
babel/locale-data/pt_MZ.dat,sha256=hmhU3Y7HgDXrsyTUootEEdjCO4dy8wxGRvZRezeWq_Y,1015
|
||||
babel/locale-data/pt_PT.dat,sha256=C7vXAMw_2sCavBd1R62VD0n3r08CZAA49hFMT_ti9cY,99144
|
||||
babel/locale-data/pt_ST.dat,sha256=YBm07Nws76viG-9eMRgf3fn-n2B0jCptD5N5s6OWySA,995
|
||||
babel/locale-data/pt_TL.dat,sha256=qG2kU_auBSaMJNnYn6fYwxspLJ3OK0EpL6Qd9-Qtzi4,975
|
||||
babel/locale-data/qu.dat,sha256=ghWjIAkE8YxHAfaLXgXiAKedoohrLikSTsUBiM3MnYU,107964
|
||||
babel/locale-data/qu_BO.dat,sha256=CGWYNs1_AuQG3T-fYwe-q2AwDl9LAEITGRRYzc_MdKQ,836
|
||||
babel/locale-data/qu_EC.dat,sha256=WewzwnSQA5llc9gb5UYy2ue5Y8_HRb1HnddOVIXcf6Q,810
|
||||
babel/locale-data/qu_PE.dat,sha256=gT0fXlP3-rFSzIy6SdYVt-6viGPP79ukYHbBynqU4Bk,608
|
||||
babel/locale-data/rm.dat,sha256=V12vyZyv0wD6Nu84Gl5V33yohhcm-dpGSJ2I9Ot1GwY,67934
|
||||
babel/locale-data/rm_CH.dat,sha256=atueKnCga8bqm2GrXOwBjQf1ypER1IAjcv4RX6Oz0Sk,626
|
||||
babel/locale-data/rn.dat,sha256=Dk-PN1zn4fjGlXZXwhEOfUmpJBu_2DlHZaDI_ins0Q0,16781
|
||||
babel/locale-data/rn_BI.dat,sha256=II-eZWKAf73Hh0aGZifK2NLJvvXWws8a7Uv_2TUZ2VA,589
|
||||
babel/locale-data/ro.dat,sha256=4B1VWnRbEV3KkNT3hbnkbtq2bAZdNqZIDV4DdD2AEZE,225782
|
||||
babel/locale-data/ro_MD.dat,sha256=tkVS0RiHpOA2ZjCZbufnznw8aVIFj-XLoWr8whLVN3w,3215
|
||||
babel/locale-data/ro_RO.dat,sha256=rFeMpPnG0zRek72AxhPuZAuJFKAuA-UL5fAyLAnPiQ8,608
|
||||
babel/locale-data/rof.dat,sha256=jx81EEsVRwsEnaROsGiG4vQ1jm1wFW_V3yNpPsYZwmM,16170
|
||||
babel/locale-data/rof_TZ.dat,sha256=6mZ6eFqNAqwuWCZuT7oZClLSv9eWSdGH0efVoQqxj40,590
|
||||
babel/locale-data/root.dat,sha256=W5zvjlEJQD3MWdvhMHuW72ERorcD51LDhqtyXmmYARk,42432
|
||||
babel/locale-data/ru.dat,sha256=TM12Pev9K3Ccwr5Z_Wj6hClv_qY_Hqk91f9nD6YSt8k,305212
|
||||
babel/locale-data/ru_BY.dat,sha256=Pb4BHcT6RF6ONtgLhPcGQXQHVGj9dPrrodoI4ihsTSk,649
|
||||
babel/locale-data/ru_KG.dat,sha256=iQapNW3xr7lH-HEbM7CIbdQwmUjm2Tgq3iJAMFUC7zc,632
|
||||
babel/locale-data/ru_KZ.dat,sha256=OnFw_fadGFUzN0KL3WKvL0ekAwCCv5NOIhz2IFbHK0g,629
|
||||
babel/locale-data/ru_MD.dat,sha256=vZr7Dz0UZlMeWWSisvdMuyOcLyreeihFbILXdQemOXM,627
|
||||
babel/locale-data/ru_RU.dat,sha256=QhIIdAW2iPQ6LcErVIuxwvaBi1ku8V5-zsy1MZV1YU8,626
|
||||
babel/locale-data/ru_UA.dat,sha256=ZALhQpV7aWxa78cxM54zedaE6-0YNGkB7NeL5BAeHOs,1747
|
||||
babel/locale-data/rw.dat,sha256=OJ5hT_uLwSOdlkjZkrP5WmriCJTqE48b2bJTS4cRV6g,16215
|
||||
babel/locale-data/rw_RW.dat,sha256=G6ta2DtZdiILzTdyZlXTCzoL-oRoF1gekRFCmN_dEyg,589
|
||||
babel/locale-data/rwk.dat,sha256=uZEibGF11hKUyRFeC3IcSTrxMuWJsK9Z0c2VtykOGu0,16057
|
||||
babel/locale-data/rwk_TZ.dat,sha256=RtQRCyT2DbqRtc4uzP8Nna10O8KouCqtbtSxCJ-PukI,590
|
||||
babel/locale-data/sah.dat,sha256=eXy9sdtMoVJcQM3C1-m9w8iGOzgqVguyHD1b_J_Xg78,48180
|
||||
babel/locale-data/sah_RU.dat,sha256=-Hi7VNsxTYaC-4G8qYQsnSPVMc5jXBYQJBvd5UeC-lo,627
|
||||
babel/locale-data/saq.dat,sha256=T_ODjjLim-CJKf2XIGBOfuEGtEqeN4I4VbyY6N_Rcl8,16455
|
||||
babel/locale-data/saq_KE.dat,sha256=uHKDZR4LUK5CGvcVC-dIpdYM3uY1KXVh6vkAOnOrc-w,609
|
||||
babel/locale-data/sat.dat,sha256=FRyhxW7p0BSz3oG0GLb96hg4e49rufWbNgOX5HifceM,12597
|
||||
babel/locale-data/sat_Olck.dat,sha256=XNqbalNvgWolPY1M9vZXPpLzFkzYzjSAvKtoP1x5oBs,878
|
||||
babel/locale-data/sat_Olck_IN.dat,sha256=Rx6KNBVSK2m0PvmKzotwxqBIp30-b5dCQU5-hqSB8tQ,632
|
||||
babel/locale-data/sbp.dat,sha256=N_zsOwROvCa1Nd1geNViDAkUsWkkPLDrpfXFmjJBwII,16479
|
||||
babel/locale-data/sbp_TZ.dat,sha256=myr2BmLmSpSCCyRFCjm70nQfdeUAopZ29zxfemg6F8c,590
|
||||
babel/locale-data/sd.dat,sha256=QoU7MJunjYKrj_TjLuMS6x0BuFxAsE4UcXnJw5XCrXk,194219
|
||||
babel/locale-data/sd_Arab.dat,sha256=EOWPc5-ACgE6NQEHILMBA_BP6mK35sTdUEEuEFCv748,852
|
||||
babel/locale-data/sd_Arab_PK.dat,sha256=pNtPPmwu0jQK9V31EOv-lVoFiYwf1iHDxJmB5NNIZzU,608
|
||||
babel/locale-data/sd_Deva.dat,sha256=0Imih19CK7Tq6YdIazJNgJJMZPwPjKXSo0xFXWnliTA,15216
|
||||
babel/locale-data/sd_Deva_IN.dat,sha256=Uei2PSaYXixwn6VPwb7xeFMXt8I_jyM_myr-8lADGVs,631
|
||||
babel/locale-data/se.dat,sha256=cGes_DRLmVtVV0bjj37-QC9s_zALE7zEfrseAwvUhU4,72353
|
||||
babel/locale-data/se_FI.dat,sha256=klpIv_TDIAH88KnWG6g9AUWvdhmwMSKaSfCC0qPu0tY,46574
|
||||
babel/locale-data/se_NO.dat,sha256=k-BEm9_tnVXbt-H7pAtUU78dZfuiq7-cTcbsgsqISlg,626
|
||||
babel/locale-data/se_SE.dat,sha256=BxFV9gNTLfUF3ibsRvgeuRnuDo99396qMA-89tpdEFY,667
|
||||
babel/locale-data/seh.dat,sha256=0qAVFIAc1GZkYBCp4DP5DM1G2QfcfI0EvPQeP7Uci7c,15910
|
||||
babel/locale-data/seh_MZ.dat,sha256=feukobIWsGC_o5s_qb0UgFI7gzVCrNSydoRaXs0NUZ0,609
|
||||
babel/locale-data/ses.dat,sha256=X5NMBmnvudU3XqhKZWH8l36b4RFIf1vXuhLSIqUbgfI,15998
|
||||
babel/locale-data/ses_ML.dat,sha256=O7stcUKOw8ZkGmgnPqSWBCxPFA3_aDIcHZGAT9yRrtw,590
|
||||
babel/locale-data/sg.dat,sha256=GQNOEIiWV9wnrISbr5uFtFK9gvWoNNF6G5gUta9V1Io,16635
|
||||
babel/locale-data/sg_CF.dat,sha256=dDZMdfhJBfy2ShSVhAopU2nIEEBnTssu3Vji2v9SpHg,589
|
||||
babel/locale-data/shi.dat,sha256=yI6ilP0U3O4u2IGEJcHnEpFxPPqVIuZJRSAOyr-axtA,22036
|
||||
babel/locale-data/shi_Latn.dat,sha256=rqL_ruNuCpetsrf_JIL02XNbqkoBDDZCC-VjchfA8mY,15618
|
||||
babel/locale-data/shi_Latn_MA.dat,sha256=blTyj-JXuFz7wgjLjUC19rH4Emj7_-TOtMvBKb7qAus,590
|
||||
babel/locale-data/shi_Tfng.dat,sha256=PmToPVEqibydgF2nxMw21pujbbqf4odWn7GlEqQL2u0,947
|
||||
babel/locale-data/shi_Tfng_MA.dat,sha256=blTyj-JXuFz7wgjLjUC19rH4Emj7_-TOtMvBKb7qAus,590
|
||||
babel/locale-data/si.dat,sha256=zxzkUZZtc4uVe-G1jMp1pAtkW726ZJ872nLo6ZTSaZE,244850
|
||||
babel/locale-data/si_LK.dat,sha256=2k1GulXssuQkuKMmj4J74iAYHlfh507gp6l75lKDJwg,608
|
||||
babel/locale-data/sk.dat,sha256=BrxSaUkE6hCEqX1etX6_C6dfuCmSNAJvtH8IFqGzHAE,256860
|
||||
babel/locale-data/sk_SK.dat,sha256=b8ugTdqk71Ge03FdSEhnOmH0wP5XeDSI40ys2hGovNQ,626
|
||||
babel/locale-data/sl.dat,sha256=n8vsb9jixRFE_J7WJYW4w1GehxoGJnNHgGjFZFlmpEM,241874
|
||||
babel/locale-data/sl_SI.dat,sha256=V1oy5BlaUDjrX8b0jv9LK7Mgg4Yx84u-Iry4j3M8LYc,608
|
||||
babel/locale-data/smn.dat,sha256=iTOwk1p0Y-9jOGDIEuTz3-jwEbC3neN1n4xTKSIfyyY,42674
|
||||
babel/locale-data/smn_FI.dat,sha256=3FaHTO42uw4LsL2o9CnKHuk86tRNGaorVeYh7SPONWY,627
|
||||
babel/locale-data/sn.dat,sha256=pfT3kmp47TnfQGNvcsWF43YQaoHOtkXbRFvt3leN80Q,23252
|
||||
babel/locale-data/sn_ZW.dat,sha256=R48ZM21PI5bjz154uuK-wccs9d-M9YMdiQLtX-rbG5k,608
|
||||
babel/locale-data/so.dat,sha256=6KnXbRvPY84Ag4eBiPzLfjRvHuuuiu-ZJo5bA7qL7cU,153105
|
||||
babel/locale-data/so_DJ.dat,sha256=CWxbbQZ8iogPci77q4bpbWHOFBOKISwLOkqixb-TqRA,629
|
||||
babel/locale-data/so_ET.dat,sha256=JKebALALzWT58gltRAjWVKl3LqFGiy1iD-nbFFsvfZ8,628
|
||||
babel/locale-data/so_KE.dat,sha256=Ooas5zUI6mtrajAybdc2YQyFlS4RFNUxeXqT0pUQ2fo,1181
|
||||
babel/locale-data/so_SO.dat,sha256=WtbiqTAukA-EouWNpajrPLIyRqUNmh0A6bcbXQywwqc,589
|
||||
babel/locale-data/sq.dat,sha256=Gj2LUjCjKeRcNUF86vv8cbX1j_VPUmSBjQxHP8HETHQ,175659
|
||||
babel/locale-data/sq_AL.dat,sha256=061xsDws549-glqPY5No20svTFqs0pO6Cn9oUtwquVA,608
|
||||
babel/locale-data/sq_MK.dat,sha256=8D6OAIV9T29UVST-ZD0zjtgYgrScEKaeZDaf8fJBk4E,1181
|
||||
babel/locale-data/sq_XK.dat,sha256=nFWTBnEjpW6ux-oMbSov3ta96NrvwhjtQ80viYXFfKY,1160
|
||||
babel/locale-data/sr.dat,sha256=PtgWUhY4n2x_GzfWOjZbYvPrliijqBNBO0KBJmk5v0s,277763
|
||||
babel/locale-data/sr_Cyrl.dat,sha256=PqtXXFd7yu1Bweljv2UkBHFUYVPlIFY2abO3lfl8t4Y,1957
|
||||
babel/locale-data/sr_Cyrl_BA.dat,sha256=dShsmp6LRaSkv8ASEvrPf6KeovR0BHLg7DUu-CJp8_8,4710
|
||||
babel/locale-data/sr_Cyrl_ME.dat,sha256=kT_iSmJ3fWaM4XDKSSCWgfT-zdxMxm8Mg3hISHZC9m8,3873
|
||||
babel/locale-data/sr_Cyrl_RS.dat,sha256=AAJ6aaa8D73J6na-RIjuqhEfLWKReHLwzYavdFaobhs,608
|
||||
babel/locale-data/sr_Cyrl_XK.dat,sha256=hXdgzDWE5gDdWBbiNBaEHTl1hjEqqtd9dmnFXPFRkfc,2756
|
||||
babel/locale-data/sr_Latn.dat,sha256=uGrDTKlSnMMQg7XORMw8Lg5v17HB-mNAFlD0Kczta1I,230252
|
||||
babel/locale-data/sr_Latn_BA.dat,sha256=ohHi1ZC9VzvqIIRkemStv_FVS9U5CPiLr8I2QUCt0ag,3994
|
||||
babel/locale-data/sr_Latn_ME.dat,sha256=gPaIdFD34NWU-69gmIOuCw6b8klXWs6RJUeU8ihcSqQ,3074
|
||||
babel/locale-data/sr_Latn_RS.dat,sha256=AAJ6aaa8D73J6na-RIjuqhEfLWKReHLwzYavdFaobhs,608
|
||||
babel/locale-data/sr_Latn_XK.dat,sha256=_BATf9SVmbg1Knn5nGG5srTFj0suBkMuTG5gcF46MO8,2194
|
||||
babel/locale-data/su.dat,sha256=tjQYu8CY2Y_Hz12pRczCaxX7LrRJK4xOvYthqwFgVBg,12452
|
||||
babel/locale-data/su_Latn.dat,sha256=AoqRqUqiJYE1G-ZRCIIhkYSRQ8s71qDefLwv70XrgZA,718
|
||||
babel/locale-data/su_Latn_ID.dat,sha256=Hi1QalxGc49vElzHunyzz1Mfc6_1KgzXkGjcj04mq8c,608
|
||||
babel/locale-data/sv.dat,sha256=DLFxWbJiUU2870aLFBVVDW3_OEWpE2yL8p-Q1h0J9aw,221078
|
||||
babel/locale-data/sv_AX.dat,sha256=4LqqSZFfMV2iRBS5TyTdWWKfdoN_ahxotRUbyuoaX8g,626
|
||||
babel/locale-data/sv_FI.dat,sha256=WDEfn4f8iqbtpxYsGA_6mDW_jk4gFolp7gU58aRKt1w,2584
|
||||
babel/locale-data/sv_SE.dat,sha256=OtNxgFxUFAH5mYJ4yGqp_wLMmnMu9mwVnvJ57BKUOKs,626
|
||||
babel/locale-data/sw.dat,sha256=LxA1OYCK0j4dbhSCT8KgSwrsF_wA94vHs30XAP-vQ5A,179207
|
||||
babel/locale-data/sw_CD.dat,sha256=6HlO0ltwzAj1j8ns4jxCI0P36r7MauG7h5EQqpQhFkY,2660
|
||||
babel/locale-data/sw_KE.dat,sha256=GKdU3qzg_MR2lQE7gRkAZqHA8gD0nBUhgSqNOkS0fbY,35934
|
||||
babel/locale-data/sw_TZ.dat,sha256=rRGQVQ_Vp0bQ6_KnZTZDn7YDY5HDNiIsUMFLSnKD6nA,589
|
||||
babel/locale-data/sw_UG.dat,sha256=GN6zqbWL7dor3RJWaJ7EwhMX8BIA6HVUzN7xWswPgbU,633
|
||||
babel/locale-data/ta.dat,sha256=ytGi4rbhhefQHdKzbgWOCheyBDU6H6JJGOYHWJvuMxE,263466
|
||||
babel/locale-data/ta_IN.dat,sha256=1D_ISTGx78nHVtYBoccQpH04o6CCL5dIIGRm4RWkMDg,631
|
||||
babel/locale-data/ta_LK.dat,sha256=sHPH1bp1O7mbhnp0WgIyHfKckEIATHbtNtSGQPdbVSU,1181
|
||||
babel/locale-data/ta_MY.dat,sha256=SVPpzoaW_lDTyUaLLP05lUjx5bnkv5G0QFrnMC3WRGs,1238
|
||||
babel/locale-data/ta_SG.dat,sha256=9e057sNK17LS7GQfZ74fzkPmHndampHvierKZNX6vT4,1257
|
||||
babel/locale-data/te.dat,sha256=QZ7c7f3RbUpaJfZ7fr4tWqrUowkXNnCBOlGGAfH9y4I,262280
|
||||
babel/locale-data/te_IN.dat,sha256=uRakP3CRkBJKNlCxMpMDOGOi5aeiq5OiLxBbUWn2NZk,631
|
||||
babel/locale-data/teo.dat,sha256=67b09CdiUgLq-6n63Ox1CvkkxExMIWAJh82HVSoyah8,16671
|
||||
babel/locale-data/teo_KE.dat,sha256=yZVnSmYqZ77jAPlyuyY_yivRqbj4dwbb99MW52EJNvU,630
|
||||
babel/locale-data/teo_UG.dat,sha256=o5PkAO5zi67Lxbh5vKaOJF6qerkAFvJu3RrQ0iHlmwA,613
|
||||
babel/locale-data/tg.dat,sha256=D0Rhojw2aiooD1a0COKgtkD3nvxhPwkvOaBJuqoQgRQ,36303
|
||||
babel/locale-data/tg_TJ.dat,sha256=ge5GlIElwu5VzdLeWCCEz5A2-F9ihtOH9Ic9k5ii4wY,608
|
||||
babel/locale-data/th.dat,sha256=qvpR1DSefc-FR-cvQXpDw_sADav-_oRt0RLnBBZd_eU,235280
|
||||
babel/locale-data/th_TH.dat,sha256=aQd6NJ_y5ObTF2koe4cI_s_mVdG0c7JfaiivpLN8M50,608
|
||||
babel/locale-data/ti.dat,sha256=wLPieG3yJtUVM8VrrwEjhqnO8El_xTQaTlgsTL2qFP4,73036
|
||||
babel/locale-data/ti_ER.dat,sha256=c0K7KojJP6dMJAGn1SRfi6lmNy8BvijIUNC4m9gqc2I,958
|
||||
babel/locale-data/ti_ET.dat,sha256=vT6Tl0BBaMupoRD4fb3kmM_Mufx2EGuqP460HO_Bh7Q,608
|
||||
babel/locale-data/tk.dat,sha256=CJVPDLCt8C3T8GhrgEsnnWTnwoWm2RcNDfvQ4bjDZSE,167927
|
||||
babel/locale-data/tk_TM.dat,sha256=06szpphDghkTBac9nMge32AzZKeQdxXeZjsXF0X1-Nk,608
|
||||
babel/locale-data/to.dat,sha256=ZSHEXy-JD4xKehjprq07mYbMgXKEy0j3kA0P6RKiClw,166458
|
||||
babel/locale-data/to_TO.dat,sha256=UaceT8b6KsoNoQd68finqhXDLVr_4GtcGFsgTwJaYTc,589
|
||||
babel/locale-data/tr.dat,sha256=xeuwfXivD-H9zszsBigvaEqV57cp7jkngzv8es_trSQ,209226
|
||||
babel/locale-data/tr_CY.dat,sha256=sHH4XyRX7XNKfRzQPuDEVNlfBCdyg7jy-bvyP7yPTBw,1184
|
||||
babel/locale-data/tr_TR.dat,sha256=lUyZY1ya9qqjmhdYhAkP6j4V953QWx_cC16GrVZCaYM,608
|
||||
babel/locale-data/tt.dat,sha256=szBjiq0ZOV4gwKairWY_axw1_Q2WuV9CO9XotiJtI9A,33588
|
||||
babel/locale-data/tt_RU.dat,sha256=MqxY1dPvSLsO7huGCYIhaTqwfGw9qHzq-oUt3VwVPyU,626
|
||||
babel/locale-data/twq.dat,sha256=AW_qiBsx_oBOrFVQ9yvnHEms3jqkxNFRY0hYF8ErVrs,16171
|
||||
babel/locale-data/twq_NE.dat,sha256=yv89EP--ZBgtvC_Vfy7UN37T7OktzntjGpRKfo89AW4,590
|
||||
babel/locale-data/tzm.dat,sha256=oVsKo32vfNoupn0mwkP0QmlYCh0irKQvAoIhauxhD1c,16149
|
||||
babel/locale-data/tzm_MA.dat,sha256=jOAK87vFm-WpZK130vSvCLE8fWxfjeyPs_G1elc5TMk,590
|
||||
babel/locale-data/ug.dat,sha256=N05TG_7CnVabGWTTHoVWlxPQ6MseNb_y3_YI2_pLiRw,128534
|
||||
babel/locale-data/ug_CN.dat,sha256=EMQBXnc07gL0zsdKDerIo0Sl6DtZVJaapUCoOL9V22k,608
|
||||
babel/locale-data/uk.dat,sha256=GfQIacOGkBh-WmYgbPOlmiu6mLYADuzVi919Lk2p9Ig,315834
|
||||
babel/locale-data/uk_UA.dat,sha256=YE9ivxv_h3qwHTeFyWTV4gt5JaYgYdKQTLHHadAQQT8,608
|
||||
babel/locale-data/ur.dat,sha256=q4apEHeXrfxzm0HJrKkdHJd6Y54ZUwFC_6lZzzkxvjU,197918
|
||||
babel/locale-data/ur_IN.dat,sha256=YSaoN2o4C1InByihAFCDOBE_HlCt7xkRl9lyOrfoCTk,12595
|
||||
babel/locale-data/ur_PK.dat,sha256=VXzQfSYJAIlzcDjPva4UM67jhqIwDUqAVNRGB2YPcfI,608
|
||||
babel/locale-data/uz.dat,sha256=KvGhlHDdpSZtTcqMENPN-zCjmsIIIwu8o1Oc2MTHjDA,173590
|
||||
babel/locale-data/uz_Arab.dat,sha256=WrXXAaoKSVPU_PeGQIGU0jmdaVzPtkZQxzhtOlH7VjM,4111
|
||||
babel/locale-data/uz_Arab_AF.dat,sha256=ONnsHyim0Q-GRD6BAHPTj2Ri4aR41EB5HWhJQrKKXAU,651
|
||||
babel/locale-data/uz_Cyrl.dat,sha256=_q-bVsz4aZwG1LVqQC5rN_aCn5o-ocAJ1zD8eqVOMj8,98924
|
||||
babel/locale-data/uz_Cyrl_UZ.dat,sha256=D2g0Iy4gME1-ZrXDPgcs1VlFNW1FWKRD607VKgUsFwA,608
|
||||
babel/locale-data/uz_Latn.dat,sha256=wkn_uCtrZQx7Ut7_pTVXVU9X956I30Nr4seILvPnZ_o,1265
|
||||
babel/locale-data/uz_Latn_UZ.dat,sha256=D2g0Iy4gME1-ZrXDPgcs1VlFNW1FWKRD607VKgUsFwA,608
|
||||
babel/locale-data/vai.dat,sha256=Y2F73JC5rT_LyIvVXYCJEMwnLE0YwmOTiEh-ZsUhx9A,18988
|
||||
babel/locale-data/vai_Latn.dat,sha256=qys9gT6Krcg_09r52_SMMrAEyI2XzngIuKlPKWpZnhg,14989
|
||||
babel/locale-data/vai_Latn_LR.dat,sha256=mFG8a5AB_Cnv2lwGAVg5SxhF0lgkrS4vB3UdqB1L8Y4,590
|
||||
babel/locale-data/vai_Vaii.dat,sha256=rZi5j11eMQeE9MzTRK4Gl5EhqEy_X6o3V06k_E4ioOY,666
|
||||
babel/locale-data/vai_Vaii_LR.dat,sha256=mFG8a5AB_Cnv2lwGAVg5SxhF0lgkrS4vB3UdqB1L8Y4,590
|
||||
babel/locale-data/vi.dat,sha256=pfW__H9jiCPiorXwYFxodzP4CjbHhGh6AwCye8RznAQ,162325
|
||||
babel/locale-data/vi_VN.dat,sha256=hn8-pr09TFtQwAvAau15ETGT4bmPay2o_LGOvLA6Bsk,608
|
||||
babel/locale-data/vo.dat,sha256=nmu1bYpYLcTQzd5w4nGKygzPddIlbRfHZIJCYPT8bIM,5225
|
||||
babel/locale-data/vo_001.dat,sha256=sQnDTedm-Ec9H8JaIqP3ZLpsAvJOr8GRr1BADz4lNRc,823
|
||||
babel/locale-data/vun.dat,sha256=_9UYsm8lOz6Q0DNjRQDTaZU8wR5sv5PS4y-oDn7siqE,16067
|
||||
babel/locale-data/vun_TZ.dat,sha256=1lrpmdkRCqdDzX4Cel249MWWRGVDmubt9OiMf6Qsrnk,590
|
||||
babel/locale-data/wae.dat,sha256=hLrXzFfFW-jPsSrA0ZFzjZdhV60X1etEZOKlb6f0Dbw,28660
|
||||
babel/locale-data/wae_CH.dat,sha256=5fOXgR-rrWoIYbf230jds8iOj1dsbvNW2Qv2XBNaCto,627
|
||||
babel/locale-data/wo.dat,sha256=btSGt-pyMUGCK1wCUkG_9dccsvl_w9qPmAv1OV9Q5Iw,25698
|
||||
babel/locale-data/wo_SN.dat,sha256=ryU-hZj708JELq9ldfmRU8I2EDihWGM_6v8QQY4qRuE,589
|
||||
babel/locale-data/xh.dat,sha256=FILfYkTCJIqiqqcEo29ID_9AxcUGdWePyXJnbOI_kGM,15055
|
||||
babel/locale-data/xh_ZA.dat,sha256=LPaE6z0iRUaCSVd2CeuJzy_0GfhGCs2KgtYPHqLL18I,608
|
||||
babel/locale-data/xog.dat,sha256=TU2N1WKiMwbPTe7tF_Hj300hT6Hn-_f5H12h5HU1Xf8,16555
|
||||
babel/locale-data/xog_UG.dat,sha256=5B_ozUekB9sXcaT_-7brqH1nfv_XEP5CnB2PG84_JlM,613
|
||||
babel/locale-data/yav.dat,sha256=R_FIP-S4MiI3XULYddxjJtYhFPPwILvVDbHd3S6C1dc,15302
|
||||
babel/locale-data/yav_CM.dat,sha256=y9SNKPJTMwmSdGc0MO-vn7hUeK4arphzRDp2zBFYigs,609
|
||||
babel/locale-data/yi.dat,sha256=XNca4NO0IFPfGXT-E7HlW-9BOGi9ZvJSxrx8O13tHUs,30314
|
||||
babel/locale-data/yi_001.dat,sha256=wdIcCz3ZcZHFJqT28rBWo4iYmRffPPVWpxod_13KIYY,885
|
||||
babel/locale-data/yo.dat,sha256=a1uZep-5fpoV77z6eDBYeaaWw3c8AMXswNgYdHqpyWs,68429
|
||||
babel/locale-data/yo_BJ.dat,sha256=oy0uMgotXzVGUeC1paiyc0YEoxsXHf1qQ5eYr9dl5TE,34481
|
||||
babel/locale-data/yo_NG.dat,sha256=vVCmItRDqtBEzSXYDsXGoiobciBukV84o_LpnAZRiDs,589
|
||||
babel/locale-data/yue.dat,sha256=kgkc69B6aeh8K1K-iNS1nVb_xi4IWHUcIG9CgIWmjz4,183333
|
||||
babel/locale-data/yue_Hans.dat,sha256=aXi0gwVQezQ6RZDRAd09wLWhwlKUTfrSyDF-ZjEIJvo,183225
|
||||
babel/locale-data/yue_Hans_CN.dat,sha256=0SEPKM5hD5K5TXbakL6_Q7mE-Te_ea6eOhSy1uwwJXA,609
|
||||
babel/locale-data/yue_Hant.dat,sha256=_BWk9N_79PzY7EPWu-O_M8j1ISYhkN29HEbuo-i0AoI,1279
|
||||
babel/locale-data/yue_Hant_HK.dat,sha256=8iSo-1wkebNgS7h3iCFLd9s-nW8TuQ3-4UFUMUEmbMM,609
|
||||
babel/locale-data/zgh.dat,sha256=52E-cKoUGWnMZMAeTavTmgj666axYtF6L9u5tHn1JYQ,30498
|
||||
babel/locale-data/zgh_MA.dat,sha256=sIGElmHSGowAduz_ykRA_-PotBTJaOqmBtRhXJ_swJc,590
|
||||
babel/locale-data/zh.dat,sha256=ffkBVzcOpHqTELueQekXu2xkPOiFnhAH88ImnVX7ZT8,181044
|
||||
babel/locale-data/zh_Hans.dat,sha256=-JH1KTn0ibMkBj6gw2V2Q6ixLBL5x0n7B7AkCpU0TRI,1278
|
||||
babel/locale-data/zh_Hans_CN.dat,sha256=sTrrw5ttuMLr70IDoBM02f7vGVzuB-0gQNQK0IDNyXA,608
|
||||
babel/locale-data/zh_Hans_HK.dat,sha256=gy8r4jqxvwhNf1BUPjnkRmJGzweemtJ1ylkumHBmUgg,3138
|
||||
babel/locale-data/zh_Hans_MO.dat,sha256=C1N9WHRhsqPiq-9su32Ar1ZcBpN5P0pTJapGAFRCOrM,3270
|
||||
babel/locale-data/zh_Hans_SG.dat,sha256=qCiYdP4MAwcVyJyJ-YJ9B_kvsNUxu9nWkeR3XwgNYpQ,3466
|
||||
babel/locale-data/zh_Hant.dat,sha256=dzsvtbyAGj7fzzCl2xBJ010IQzq9IJsi59vW7Qf2d9Y,185029
|
||||
babel/locale-data/zh_Hant_HK.dat,sha256=71VE9xyc0m5Gh4gJ1STha37iLm5lvpISG3fZsKFuQ9g,56895
|
||||
babel/locale-data/zh_Hant_MO.dat,sha256=gTS5IdcTsRoMwAnANseIbj2nyflLj0tBQn2-4AFAaf4,630
|
||||
babel/locale-data/zh_Hant_TW.dat,sha256=QYchBgi8JmeZgs7rQrUYn93CNNL9aavsOWYzAaTndwM,608
|
||||
babel/locale-data/zu.dat,sha256=8ONW9eqg4gnEisbcMQeDl71dCVY1ckM4nJOXat9rPuM,167684
|
||||
babel/locale-data/zu_ZA.dat,sha256=YO0tFWUiAdda0x3XEoL98oPNFGRLuk5OZ8DaR3lUX38,608
|
||||
babel/localedata.py,sha256=bp9ZCXKgvJ08oOwrOIeknZ3Ks7QVi03HS_IhIDOf_ow,7931
|
||||
babel/localtime/__init__.py,sha256=43mNcGAGljnTjngbhTMl6xhfeHMR1Sabby2O-Deh4gE,1721
|
||||
babel/localtime/__pycache__/__init__.cpython-39.pyc,,
|
||||
babel/localtime/__pycache__/_unix.cpython-39.pyc,,
|
||||
babel/localtime/__pycache__/_win32.cpython-39.pyc,,
|
||||
babel/localtime/_unix.py,sha256=P66o3ErKXzhFvj3e3Qk6MBS7AR0qsDqSQclIAMHKp18,4801
|
||||
babel/localtime/_win32.py,sha256=dGzhQ8AlY5iItSd-i3Fi2O3YWuVJ83PFSWe7EG2BaBg,3086
|
||||
babel/messages/__init__.py,sha256=mYEtObYlyGT9zKJog4IjXFN-au3uxnc16wg89edsMxo,254
|
||||
babel/messages/__pycache__/__init__.cpython-39.pyc,,
|
||||
babel/messages/__pycache__/catalog.cpython-39.pyc,,
|
||||
babel/messages/__pycache__/checkers.cpython-39.pyc,,
|
||||
babel/messages/__pycache__/extract.cpython-39.pyc,,
|
||||
babel/messages/__pycache__/frontend.cpython-39.pyc,,
|
||||
babel/messages/__pycache__/jslexer.cpython-39.pyc,,
|
||||
babel/messages/__pycache__/mofile.cpython-39.pyc,,
|
||||
babel/messages/__pycache__/plurals.cpython-39.pyc,,
|
||||
babel/messages/__pycache__/pofile.cpython-39.pyc,,
|
||||
babel/messages/catalog.py,sha256=lQUVsuoNKL8yy--XqrHWX2AEKk6_qj4vpTNwuJJEtOE,32291
|
||||
babel/messages/checkers.py,sha256=tCqwgZpzwJwhouwSIpKNHW0m48338W1omEllOFDxv9s,6085
|
||||
babel/messages/extract.py,sha256=V-_eVZzxtANiue1ST3Yp6Kv1N3z5Swy4eu2_GuEt2WU,26474
|
||||
babel/messages/frontend.py,sha256=skgwlQry-3Sbf2v448eL3KxwUhd4pFRLa_5kkilKgvc,38729
|
||||
babel/messages/jslexer.py,sha256=NU2h-nZxoNnycllWViSv3X-jB_p1Vpw53uvqVklsMQ4,6334
|
||||
babel/messages/mofile.py,sha256=2JBYxNfuBqO35U-H_VqB1rgW2gocS0Has1YgGZwYxLI,7204
|
||||
babel/messages/plurals.py,sha256=GOD89ObneG4--qFbt_PQOvpEY-72o9LdghOsztNgRiw,7206
|
||||
babel/messages/pofile.py,sha256=fMUcLVi5-vIyKfDjkOde6He1QTSr0n4iYEis560zHSw,22146
|
||||
babel/numbers.py,sha256=-V_bQC6whhEalzEmYkFtvydZB0_knjLDgzu2C2SzGbM,39872
|
||||
babel/plural.py,sha256=bo-QkRGinKBBF58KgJoE7aUFKTG9PrFYtpTYvOSfYMw,21314
|
||||
babel/support.py,sha256=uO02VsCqKTcgBopi1RkQGhco2gRTZi4q3hlrbhgnxsw,22622
|
||||
babel/units.py,sha256=QPa8jqWKdS_dB4zTp60ffty2PClONBdlbKc885hb2RA,11291
|
||||
babel/util.py,sha256=o6JpnIY9-dhVdTgli0MAUknu4haiag_swAcLYdi8wVY,7576
|
||||
@ -0,0 +1,6 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.36.2)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
|
||||
[console_scripts]
|
||||
pybabel = babel.messages.frontend:main
|
||||
|
||||
[distutils.commands]
|
||||
compile_catalog = babel.messages.frontend:compile_catalog
|
||||
extract_messages = babel.messages.frontend:extract_messages
|
||||
init_catalog = babel.messages.frontend:init_catalog
|
||||
update_catalog = babel.messages.frontend:update_catalog
|
||||
|
||||
[distutils.setup_keywords]
|
||||
message_extractors = babel.messages.frontend:check_message_extractors
|
||||
|
||||
[babel.checkers]
|
||||
num_plurals = babel.messages.checkers:num_plurals
|
||||
python_format = babel.messages.checkers:python_format
|
||||
|
||||
[babel.extractors]
|
||||
ignore = babel.messages.extract:extract_nothing
|
||||
python = babel.messages.extract:extract_python
|
||||
javascript = babel.messages.extract:extract_javascript
|
||||
|
||||
@ -0,0 +1 @@
|
||||
babel
|
||||
Binary file not shown.
@ -0,0 +1 @@
|
||||
pip
|
||||
@ -0,0 +1,18 @@
|
||||
Copyright (c) 2017-2018 Alex Root Junior
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies
|
||||
or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -0,0 +1,85 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: aiogram
|
||||
Version: 2.14.3
|
||||
Summary: Is a pretty simple and fully asynchronous framework for Telegram Bot API
|
||||
Home-page: https://github.com/aiogram/aiogram
|
||||
Author: Alex Root Junior
|
||||
Author-email: jroot.junior@gmail.com
|
||||
License: MIT
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Framework :: AsyncIO
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: System Administrators
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
||||
Requires-Dist: aiohttp (<4.0.0,>=3.7.2)
|
||||
Requires-Dist: Babel (>=2.8.0)
|
||||
Requires-Dist: certifi (>=2020.6.20)
|
||||
Provides-Extra: fast
|
||||
Requires-Dist: uvloop (<0.15.0,>=0.14.0) ; extra == 'fast'
|
||||
Requires-Dist: ujson (>=1.35) ; extra == 'fast'
|
||||
Provides-Extra: proxy
|
||||
Requires-Dist: aiohttp-socks (<0.6.0,>=0.5.3) ; extra == 'proxy'
|
||||
|
||||
AIOGramBot
|
||||
==========
|
||||
|
||||
.. image:: https://img.shields.io/badge/telegram-aiogram-blue.svg?style=flat-square
|
||||
:target: https://t.me/aiogram_live
|
||||
:alt: [Telegram] aiogram live
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/aiogram.svg?style=flat-square
|
||||
:target: https://pypi.python.org/pypi/aiogram
|
||||
:alt: PyPi Package Version
|
||||
|
||||
.. image:: https://img.shields.io/pypi/status/aiogram.svg?style=flat-square
|
||||
:target: https://pypi.python.org/pypi/aiogram
|
||||
:alt: PyPi status
|
||||
|
||||
.. image:: https://img.shields.io/pypi/dm/aiogram.svg?style=flat-square
|
||||
:target: https://pypi.python.org/pypi/aiogram
|
||||
:alt: PyPi downloads
|
||||
|
||||
.. image:: https://img.shields.io/pypi/pyversions/aiogram.svg?style=flat-square
|
||||
:target: https://pypi.python.org/pypi/aiogram
|
||||
:alt: Supported python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Telegram%20Bot%20API-5.3-blue.svg?style=flat-square&logo=telegram
|
||||
:target: https://core.telegram.org/bots/api
|
||||
:alt: Telegram Bot API
|
||||
|
||||
.. image:: https://img.shields.io/readthedocs/aiogram?style=flat-square
|
||||
:target: http://docs.aiogram.dev/en/latest/?badge=latest
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://img.shields.io/github/issues/aiogram/aiogram.svg?style=flat-square
|
||||
:target: https://github.com/aiogram/aiogram/issues
|
||||
:alt: Github issues
|
||||
|
||||
.. image:: https://img.shields.io/pypi/l/aiogram.svg?style=flat-square
|
||||
:target: https://opensource.org/licenses/MIT
|
||||
:alt: MIT License
|
||||
|
||||
|
||||
**aiogram** is a pretty simple and fully asynchronous framework for `Telegram Bot API <https://core.telegram.org/bots/api>`_ written in Python 3.7 with `asyncio <https://docs.python.org/3/library/asyncio.html>`_ and `aiohttp <https://github.com/aio-libs/aiohttp>`_. It helps you to make your bots faster and simpler.
|
||||
|
||||
You can `read the docs here <http://docs.aiogram.dev/en/latest/>`_.
|
||||
|
||||
Official aiogram resources
|
||||
--------------------------
|
||||
|
||||
- News: `@aiogram_live <https://t.me/aiogram_live>`_
|
||||
- Community: `@aiogram <https://t.me/aiogram>`_
|
||||
- Russian community: `@aiogram_ru <https://t.me/aiogram_ru>`_
|
||||
- Pip: `aiogram <https://pypi.python.org/pypi/aiogram>`_
|
||||
- Docs: `ReadTheDocs <http://docs.aiogram.dev>`_
|
||||
- Source: `Github repo <https://github.com/aiogram/aiogram>`_
|
||||
- Issues/Bug tracker: `Github issues tracker <https://github.com/aiogram/aiogram/issues>`_
|
||||
- Test bot: `@aiogram_bot <https://t.me/aiogram_bot>`_
|
||||
|
||||
|
||||
@ -0,0 +1,237 @@
|
||||
aiogram-2.14.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
aiogram-2.14.3.dist-info/LICENSE,sha256=dsHq3STDQqe8E_gn3RwwGQ3JglVUWW2eSjviR0u3kDk,1064
|
||||
aiogram-2.14.3.dist-info/METADATA,sha256=S1bF0mNu5rfquDHQo83G2lw18-cpXc5lAN7ut_7xrb8,3460
|
||||
aiogram-2.14.3.dist-info/RECORD,,
|
||||
aiogram-2.14.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
aiogram-2.14.3.dist-info/WHEEL,sha256=p46_5Uhzqz6AzeSosiOnxK-zmFja1i22CrQCjmYe8ec,92
|
||||
aiogram-2.14.3.dist-info/top_level.txt,sha256=glLhE1GuNFQxEVRhRIm2lR2YxenVMqt8Q31x2ewaZQ4,8
|
||||
aiogram/__init__.py,sha256=tjmseIDVm3WUOtFlgiiRDvoOCwR5nNbeoSFZCCdBFaQ,1011
|
||||
aiogram/__main__.py,sha256=EiBMkaWdfb_fwJWnHgHAm1JPHvNHcztX1A0rMWg_jxM,1676
|
||||
aiogram/__pycache__/__init__.cpython-39.pyc,,
|
||||
aiogram/__pycache__/__main__.cpython-39.pyc,,
|
||||
aiogram/bot/__init__.py,sha256=OLC2y5Iy7pTHPPAaSrRpk0mnb7I_l-GU0HxW16Gzk3M,117
|
||||
aiogram/bot/__pycache__/__init__.cpython-39.pyc,,
|
||||
aiogram/bot/__pycache__/api.cpython-39.pyc,,
|
||||
aiogram/bot/__pycache__/base.cpython-39.pyc,,
|
||||
aiogram/bot/__pycache__/bot.cpython-39.pyc,,
|
||||
aiogram/bot/api.py,sha256=ijelbA0gbxZFBYNnxo4b_W0bicVpGrACveU1NMdyU4o,10319
|
||||
aiogram/bot/base.py,sha256=qyvL--msJgdRUg7hzDHcGyKaKjyLidxIjMPIxF8AT4Y,10973
|
||||
aiogram/bot/bot.py,sha256=ETM-EEJnkMYxYz5jsP2mhXuFzhwYD4rcvtRExzlWN1w,171145
|
||||
aiogram/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
aiogram/contrib/__pycache__/__init__.cpython-39.pyc,,
|
||||
aiogram/contrib/fsm_storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
aiogram/contrib/fsm_storage/__pycache__/__init__.cpython-39.pyc,,
|
||||
aiogram/contrib/fsm_storage/__pycache__/files.cpython-39.pyc,,
|
||||
aiogram/contrib/fsm_storage/__pycache__/memory.cpython-39.pyc,,
|
||||
aiogram/contrib/fsm_storage/__pycache__/mongo.cpython-39.pyc,,
|
||||
aiogram/contrib/fsm_storage/__pycache__/redis.cpython-39.pyc,,
|
||||
aiogram/contrib/fsm_storage/__pycache__/rethinkdb.cpython-39.pyc,,
|
||||
aiogram/contrib/fsm_storage/files.py,sha256=x-V7oagYARLep7qdGL6Ob4MJOgrt94mXdYc_RSvoiSc,1422
|
||||
aiogram/contrib/fsm_storage/memory.py,sha256=Jq30iYqQieTTrAhqTqGUW51xn-tzGd3z2VDj5MOeHO8,4627
|
||||
aiogram/contrib/fsm_storage/mongo.py,sha256=r-JDWyXQ_WIfm8rJN2sfcSrw_7LLDs4eziXZ7GXk9rw,7941
|
||||
aiogram/contrib/fsm_storage/redis.py,sha256=AOQHMS1N2lVZ-7Cuvjc-92HNnMqcX-keoq75g2ptbmI,15937
|
||||
aiogram/contrib/fsm_storage/rethinkdb.py,sha256=2GsWZfiaGxYHpMy50JoSgC5B3L6ZEcg-ezUOtLW3iko,7332
|
||||
aiogram/contrib/middlewares/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
aiogram/contrib/middlewares/__pycache__/__init__.cpython-39.pyc,,
|
||||
aiogram/contrib/middlewares/__pycache__/environment.cpython-39.pyc,,
|
||||
aiogram/contrib/middlewares/__pycache__/fsm.cpython-39.pyc,,
|
||||
aiogram/contrib/middlewares/__pycache__/i18n.cpython-39.pyc,,
|
||||
aiogram/contrib/middlewares/__pycache__/logging.cpython-39.pyc,,
|
||||
aiogram/contrib/middlewares/environment.py,sha256=kwyzzhEflW6suV_R-Mw-l4_vtkb-qREZHHkghVWyxg4,746
|
||||
aiogram/contrib/middlewares/fsm.py,sha256=xKOSSRMxAFOO5y5TRJbg6mYlkJa9Opk48EC3Qb2pcRI,2331
|
||||
aiogram/contrib/middlewares/i18n.py,sha256=hb8kgKpNkhq1zxhkuD_R7dE5HvR_naRhlK825bnYK9g,4404
|
||||
aiogram/contrib/middlewares/logging.py,sha256=Nnq4IZngEWhNdb65IK8vvYry8cbcT7Fg4sX-Th4n8n8,21689
|
||||
aiogram/dispatcher/__init__.py,sha256=Nkrg2GKVGo5HXJVauYIojrR0NTgILnyKbrjOe5rVgeo,336
|
||||
aiogram/dispatcher/__pycache__/__init__.cpython-39.pyc,,
|
||||
aiogram/dispatcher/__pycache__/dispatcher.cpython-39.pyc,,
|
||||
aiogram/dispatcher/__pycache__/handler.cpython-39.pyc,,
|
||||
aiogram/dispatcher/__pycache__/middlewares.cpython-39.pyc,,
|
||||
aiogram/dispatcher/__pycache__/storage.cpython-39.pyc,,
|
||||
aiogram/dispatcher/__pycache__/webhook.cpython-39.pyc,,
|
||||
aiogram/dispatcher/dispatcher.py,sha256=mxn7wF4pNXsWZASYoi9rps_EDUUz3VGu5Y6T7NTgaQM,54782
|
||||
aiogram/dispatcher/filters/__init__.py,sha256=O-HF8XQq6NAsQb65q-bDYque0fR2cTq-p7-jN_OSUso,1127
|
||||
aiogram/dispatcher/filters/__pycache__/__init__.cpython-39.pyc,,
|
||||
aiogram/dispatcher/filters/__pycache__/builtin.cpython-39.pyc,,
|
||||
aiogram/dispatcher/filters/__pycache__/factory.cpython-39.pyc,,
|
||||
aiogram/dispatcher/filters/__pycache__/filters.cpython-39.pyc,,
|
||||
aiogram/dispatcher/filters/__pycache__/state.cpython-39.pyc,,
|
||||
aiogram/dispatcher/filters/builtin.py,sha256=xIjPbpqHRnAOZyra0VSfD5HwCYzJXfR7UCX_OBjYo5s,25538
|
||||
aiogram/dispatcher/filters/factory.py,sha256=S6NJIKwJFzPFyOmTRd-oWCbzAMy3pzcLOb0V2I0I56A,2517
|
||||
aiogram/dispatcher/filters/filters.py,sha256=A6PbDNVha29Agyx_u13U-dd5sJJubGtvdbgjkZFp0Dw,8383
|
||||
aiogram/dispatcher/filters/state.py,sha256=TnWEiilNDRhdY1lKLc6H4yGnvqNB2KWF_dZKj4rtt9c,5176
|
||||
aiogram/dispatcher/handler.py,sha256=nz0pstovw_JguTZR4_v29K-nMmJon4mGUkcJkxoM6SM,4130
|
||||
aiogram/dispatcher/middlewares.py,sha256=kqWjVbwq0tOUNQp3FeKaoTpuYOpJzeKEALe6UksXGQo,3253
|
||||
aiogram/dispatcher/storage.py,sha256=vTmnFDl7qJ-yywqx0TTFMvRTPDjZp-sZ11X8NvNe9SU,15580
|
||||
aiogram/dispatcher/webhook.py,sha256=N8ofR_yeDaLsOya-RZJGocSafDM5XgwTLesnoiq1tQ8,90302
|
||||
aiogram/types/__init__.py,sha256=w4DZ_oOpBwx744rVw1c4TNbENLPRH3Ny7RqF8QKlFEM,7432
|
||||
aiogram/types/__pycache__/__init__.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/animation.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/audio.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/auth_widget_data.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/base.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/bot_command.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/bot_command_scope.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/callback_game.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/callback_query.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/chat.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/chat_invite_link.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/chat_location.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/chat_member.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/chat_member_updated.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/chat_permissions.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/chat_photo.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/chosen_inline_result.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/contact.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/dice.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/document.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/encrypted_credentials.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/encrypted_passport_element.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/fields.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/file.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/force_reply.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/game.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/game_high_score.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/inline_keyboard.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/inline_query.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/inline_query_result.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/input_file.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/input_media.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/input_message_content.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/invoice.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/labeled_price.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/location.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/login_url.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/mask_position.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/message.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/message_auto_delete_timer_changed.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/message_entity.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/message_id.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/mixins.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/order_info.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/passport_data.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/passport_element_error.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/passport_file.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/photo_size.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/poll.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/pre_checkout_query.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/proximity_alert_triggered.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/reply_keyboard.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/response_parameters.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/shipping_address.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/shipping_option.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/shipping_query.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/sticker.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/sticker_set.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/successful_payment.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/update.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/user.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/user_profile_photos.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/venue.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/video.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/video_note.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/voice.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/voice_chat_ended.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/voice_chat_participants_invited.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/voice_chat_scheduled.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/voice_chat_started.cpython-39.pyc,,
|
||||
aiogram/types/__pycache__/webhook_info.cpython-39.pyc,,
|
||||
aiogram/types/animation.py,sha256=YtZiRt-YYGiefhy2bIWosI4Tch8vHBYZyMgyLwQmEc4,845
|
||||
aiogram/types/audio.py,sha256=NR5TyMg-lYycE0jbfY65ytTzW_1KtHURQrFGRWKA0Xc,707
|
||||
aiogram/types/auth_widget_data.py,sha256=NFjrpzNOstqU9hSgRtGK5L41rAhc8Hpz6UnykCTWxD8,1377
|
||||
aiogram/types/base.py,sha256=OAPxU0pXQKkrK38zlKr_TpmI3soC4Yy5GjWse5MOCNE,8228
|
||||
aiogram/types/bot_command.py,sha256=0oVwFoVY1VM3IqcYTPQ9ATvCjweoBxvYh64dHeVVpUE,433
|
||||
aiogram/types/bot_command_scope.py,sha256=FbHqYr5Xzwx1Ao3Qc-EXVJQpz2FnGW_oc2xfTf9DrvQ,4355
|
||||
aiogram/types/callback_game.py,sha256=rdlqjxiKqnmU89AwmhsOdtsYCNsfK1QcXwqB1cSmF40,226
|
||||
aiogram/types/callback_query.py,sha256=VfpfdkkH4Df9HYB_hxUz0qy5NGeCxGLuVIxOR_Wm1Ek,3058
|
||||
aiogram/types/chat.py,sha256=-uwSFnacYVVV_RfhrlOlNxeIg304DgmPFxkptuzV9lY,34415
|
||||
aiogram/types/chat_invite_link.py,sha256=a5hf1_t2jsftjIdIjBB6-KiU3pMuaosrD0-_OQfdlU4,534
|
||||
aiogram/types/chat_location.py,sha256=ymG2LCOjfe_uB0g59qDTCOW1GYSRH0HDp3dJz1p2_Fk,449
|
||||
aiogram/types/chat_member.py,sha256=h2SkBF6gSYzi9MQ-DZmQilLK6QfokL2Y3-iWktLq6Ss,6380
|
||||
aiogram/types/chat_member_updated.py,sha256=J5k-qePjpxq9xO7f-bkblOcZBYEut8kioK5CNLJU66U,723
|
||||
aiogram/types/chat_permissions.py,sha256=RynykTfyScq4z51UAqtuONMmzy6b3t6DCRsZ0K0k4Yc,1673
|
||||
aiogram/types/chat_photo.py,sha256=0ajMgflTGvVlke6oehsCzxViW3HcyY9TiWCatGB8rf0,2905
|
||||
aiogram/types/chosen_inline_result.py,sha256=VbzJUYnkQG_CgfikEXd2rBpv36GDZU2bh1-xcwzj-MQ,961
|
||||
aiogram/types/contact.py,sha256=9GllGkYqdVhQBzM8QVY6vNgs5DXz9Yy87ZhlsI5g3fg,640
|
||||
aiogram/types/dice.py,sha256=c5tHBvXMeD5ooFXgRLutoU7cx7oQj_tD39KX10Qui_k,430
|
||||
aiogram/types/document.py,sha256=KLPdspuob_KLPg534l_oSn7PSTG0KniX9ETTgFc9PA0,1455
|
||||
aiogram/types/encrypted_credentials.py,sha256=7rC5u3kvrAyMpOzX2FbPAwvQOP-prQ3XBqdDhwmTfZw,503
|
||||
aiogram/types/encrypted_passport_element.py,sha256=zu1ke7yQwcrkIHK6BZ5iWtdky7Df3HOHow5S1yJSfnA,769
|
||||
aiogram/types/fields.py,sha256=_Ty_4aR3o81PUa7h_NuFXyHkfQvkRxGtvF7yQx2346g,5843
|
||||
aiogram/types/file.py,sha256=lwDtE0yzN-dobkOf9hvQ79T6JBGyCBcOJdbkyf3f4Qo,704
|
||||
aiogram/types/force_reply.py,sha256=zGJ4SkjBjjpMiFK7ZUJGr99ujpCmhHpmIUMiybiORwo,1092
|
||||
aiogram/types/game.py,sha256=LT4KjMzHUOns3x5Aaezql-4qDQNA5sdmbPNv1A7Cvuw,725
|
||||
aiogram/types/game_high_score.py,sha256=WzgG1csKkpiQUVm-JGqpwEiXbJz0-8M5crtg_SwZCuY,485
|
||||
aiogram/types/inline_keyboard.py,sha256=UYjPEUUIa8FAc8-2krxntEEqrG8DUHnk_xamUA1i9lw,4089
|
||||
aiogram/types/inline_query.py,sha256=J-6pmPwes84aqjFKyo4ZynuLpilWRk6UKdew_vjdYlQ,3549
|
||||
aiogram/types/inline_query_result.py,sha256=zuhyE_3oqlWdvsHYCPX71J_zXKNZnAMCWBhLwBj8NK8,37458
|
||||
aiogram/types/input_file.py,sha256=a_T7k-aFC6-Tihvi7QIWJT2xDHXIMIbIG7Or8In1PIE,5960
|
||||
aiogram/types/input_media.py,sha256=ESZxZwyZecnmb1UAtaORrTY3TGYOTXxI44e2_eU4TO0,14778
|
||||
aiogram/types/input_message_content.py,sha256=QF8Pyz9iEblDN20D_i3cbUC1pJ-48fCtAF3rHxSfgrc,8322
|
||||
aiogram/types/invoice.py,sha256=OJe3ea6zbHiU0v_PfQJFhWljTPGtLSuzBzqGKYxKHqg,430
|
||||
aiogram/types/labeled_price.py,sha256=oNGpHXL8ArrkeMp1ct8a1MDea_Y5zvEN89Rja74BqHc,445
|
||||
aiogram/types/location.py,sha256=PegQG2XiaA67D23uNQXGZTj14DpN04XLpU7M3LCgqo0,560
|
||||
aiogram/types/login_url.py,sha256=N78VBH79VtPmuwlYxmZrYcOmD4mEGU4M3doa2hkqmEc,1107
|
||||
aiogram/types/mask_position.py,sha256=xwP2mHQCwK8LxYmNv7HJv7FxP-4vnSWVw4QEPYlWG9I,403
|
||||
aiogram/types/message.py,sha256=MxGWnmsAcADTNrfOptUc8Ev0PhH17i-VmFKMYwsVSxs,134937
|
||||
aiogram/types/message_auto_delete_timer_changed.py,sha256=lSzTbHsUP_AmCaEo0l7lfSgGBUW-eQOFRF72g9Fwais,337
|
||||
aiogram/types/message_entity.py,sha256=kvf0bCxumov5I6PbvHcTSHfORPmT9vdic1oJjXJJXrs,4248
|
||||
aiogram/types/message_id.py,sha256=c9Ws62UlHyiu07YiidYLAUXcPEdqPlK_aBeVDUj9Rx4,234
|
||||
aiogram/types/mixins.py,sha256=KhQU0UuRoemD8ZL5Ji5UkEdZClRyOO5jo8cG30ZJJOg,1873
|
||||
aiogram/types/order_info.py,sha256=vCcVqabJvPdD5ZNiqrn7-wn05Wxt-UYnU14iQgFW_kQ,448
|
||||
aiogram/types/passport_data.py,sha256=mKM9nzkDVMUvVT9IFDBGKs3cB1FOYUI-4hO_L0FS7s8,554
|
||||
aiogram/types/passport_element_error.py,sha256=O2BHrF31usOKWLBuA5aoo5wCZZSGl9SG5sQRtsmKodc,4341
|
||||
aiogram/types/passport_file.py,sha256=ktZVp7kY2ECLriCxF83g54Qn1I1lv13ApOhfB_oZc10,497
|
||||
aiogram/types/photo_size.py,sha256=4ewLUutlDwvRSZFh5ZQMwvWKr51-i558YGRadx7bcAk,485
|
||||
aiogram/types/poll.py,sha256=Bb16Yxr4myM45PFe6ih0J4z3to9D95gz9uXlw7aGnC8,2356
|
||||
aiogram/types/pre_checkout_query.py,sha256=VzzWeCBFlf4rJl726vyzpDjP7eHD0yxK5y846yR5-CM,1166
|
||||
aiogram/types/proximity_alert_triggered.py,sha256=3HVR9Ch-_Wx8YaOp98JPCtzcf8T2vciFzr9fxjpDKHA,458
|
||||
aiogram/types/reply_keyboard.py,sha256=YBLpeJlLhHIWDUhzi6vppQFoMtXE8FrJivhXt4h6mic,5254
|
||||
aiogram/types/response_parameters.py,sha256=3WjIHLqlM5aruJCYWoxgsC4-EdGlmI55gJ6s_yycBQI,328
|
||||
aiogram/types/shipping_address.py,sha256=QyN8hy7iXMmFnuquw8hHl5qiWsQLXtTY2y7k43i2WHc,469
|
||||
aiogram/types/shipping_option.py,sha256=tUwtLepy0J3_4LH3kaeEVE4UQPKvaQjjG4AgZPviuHE,825
|
||||
aiogram/types/shipping_query.py,sha256=Q7ruEe4rd0uN0OYUESDZpXui58y50eR-VB75LzpLLFk,707
|
||||
aiogram/types/sticker.py,sha256=ITYOI8nsIJ6UbgEOIJGdXMJ1Itc9-01QR2ZEcriixLU,1790
|
||||
aiogram/types/sticker_set.py,sha256=gdnu5Xu5B0VmL0KWP7r94krM_NSsNE2Q6k2nVsFsDMc,564
|
||||
aiogram/types/successful_payment.py,sha256=OYa5vFeNCgrhOjbsG-JzLIg6b1msjsH8pMz9LcoNLRo,640
|
||||
aiogram/types/update.py,sha256=JnwBaaSTh1tVY8LunLtwwHzGmGSI1aXJ-Df5DmhoeQg,3065
|
||||
aiogram/types/user.py,sha256=eakT6DkHgkrIMQPRwtIhxwZBd6TWwdGQEwQcM2-_a20,2650
|
||||
aiogram/types/user_profile_photos.py,sha256=KYitXWtf9pVVg6Om6cs4DNatYl3yEAk7NUmJ-hp1_ac,396
|
||||
aiogram/types/venue.py,sha256=0FovO15JG29hTa-Ei6hGs0ypji4CiqXkXVsOnW81rGw,540
|
||||
aiogram/types/video.py,sha256=j_d7U-1RDANsYattZ-9oQKXKgoIgmLRb9coDfSoNRoY,658
|
||||
aiogram/types/video_note.py,sha256=xwjW-CMgAbjOflcTd1fIFA8edyQhMIQMLP5PitDorFQ,581
|
||||
aiogram/types/voice.py,sha256=4A0-WI5vZYszqB7Kc-SQ9z_VvlHuY-9gnUU1ILJyzTY,445
|
||||
aiogram/types/voice_chat_ended.py,sha256=b_aNbuxmYXFfAt0J_Lb4JIEGbepVSb_FWWBYwfQ3aL0,326
|
||||
aiogram/types/voice_chat_participants_invited.py,sha256=8XTP5Jc3mpwbaU1qVDKv9ZIhAzeIycSXCaG-sSfwWD0,412
|
||||
aiogram/types/voice_chat_scheduled.py,sha256=mNfF_fzsS1PjhbGSpNDIXm7AsDUs7-dYrtMMxWxzTyM,356
|
||||
aiogram/types/voice_chat_started.py,sha256=cGLxDMRw2X_-61CKHpfY4Gj7utDbHx_USn1CATSBN2k,311
|
||||
aiogram/types/webhook_info.py,sha256=0O6_l_EX5BFy4CVzqpQ1cLBUFr-ypisLUQ4y2QDCP2s,648
|
||||
aiogram/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
aiogram/utils/__pycache__/__init__.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/auth_widget.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/callback_data.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/deep_linking.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/deprecated.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/emoji.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/exceptions.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/executor.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/helper.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/json.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/markdown.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/mixins.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/parts.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/payload.cpython-39.pyc,,
|
||||
aiogram/utils/__pycache__/text_decorations.cpython-39.pyc,,
|
||||
aiogram/utils/auth_widget.py,sha256=d-hDz-zhVA9As6IKufNmI5FsLSKb0bz5saOl0U9zvPA,2126
|
||||
aiogram/utils/callback_data.py,sha256=DkRXt1Nqr6mh8PYI9jiL4EhsQi4ga-H2YzaAkLJSeX8,4089
|
||||
aiogram/utils/deep_linking.py,sha256=9OB1JQVQ9ovYotAMjglylWtGrIZSWGEp96xFUu5nz9I,3721
|
||||
aiogram/utils/deprecated.py,sha256=Oz8GYy-Odwj0eiYAKjm7yQvQ-l-Vmhecr28WkMnkgCY,5539
|
||||
aiogram/utils/emoji.py,sha256=jedTnV32L_mMZFC6d6RKA8QbaHPtDCJrtuEtW48k72I,220
|
||||
aiogram/utils/exceptions.py,sha256=QqNu4NAXGWdJ5YfIZ-lPhKwp2BT_OYpBzEjZ6ZtGAAA,14895
|
||||
aiogram/utils/executor.py,sha256=cBh4JUNxuKtbC2qNwS1Ty3kgJOl4fXuJisCgWiDkMj4,13018
|
||||
aiogram/utils/helper.py,sha256=6p7yRLe8pZUVjmIYAvGHFhsLjrXdLjxTB2VwVRRpXbo,5779
|
||||
aiogram/utils/json.py,sha256=Yzaufq_bts3YTzZ1x0v8p1MlRmxjTbinZrtNltJfIz8,843
|
||||
aiogram/utils/markdown.py,sha256=RKng7KJpGB2WRwBip0UkWNkdJmKPMNROw6WtiOf19EU,5006
|
||||
aiogram/utils/mixins.py,sha256=t3ZqwMI9Qzws7sw_eB4GS06e1xr8IVwudx9PYtL-xig,1284
|
||||
aiogram/utils/parts.py,sha256=Oq9AL4kxkBWtYgHdQk0rTimTaA0uLvuQbtsBe16vslc,1556
|
||||
aiogram/utils/payload.py,sha256=PI789pjTqFSpp5LvKjtw5p0mA5pSYc4cOtXhOLVRLjg,2138
|
||||
aiogram/utils/text_decorations.py,sha256=DeN3J832_J2RQ4G2s7m-1kamVap1j_qU0l-17RWJWYU,5945
|
||||
@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.33.6)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
||||
@ -0,0 +1 @@
|
||||
aiogram
|
||||
47
IKEA_scrapper/.venv/Lib/site-packages/aiogram/__init__.py
Normal file
47
IKEA_scrapper/.venv/Lib/site-packages/aiogram/__init__.py
Normal file
@ -0,0 +1,47 @@
|
||||
import sys
|
||||
if sys.version_info < (3, 7):
|
||||
raise ImportError('Your Python version {0} is not supported by aiogram, please install '
|
||||
'Python 3.7+'.format('.'.join(map(str, sys.version_info[:3]))))
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from . import bot
|
||||
from . import contrib
|
||||
from . import dispatcher
|
||||
from . import types
|
||||
from . import utils
|
||||
from .bot import Bot
|
||||
from .dispatcher import Dispatcher
|
||||
from .dispatcher import filters
|
||||
from .dispatcher import middlewares
|
||||
from .utils import exceptions, executor, helper, markdown as md
|
||||
|
||||
try:
|
||||
import uvloop
|
||||
except ImportError:
|
||||
uvloop = None
|
||||
else:
|
||||
if 'DISABLE_UVLOOP' not in os.environ:
|
||||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||
|
||||
__all__ = (
|
||||
'Bot',
|
||||
'Dispatcher',
|
||||
'__api_version__',
|
||||
'__version__',
|
||||
'bot',
|
||||
'contrib',
|
||||
'dispatcher',
|
||||
'exceptions',
|
||||
'executor',
|
||||
'filters',
|
||||
'helper',
|
||||
'md',
|
||||
'middlewares',
|
||||
'types',
|
||||
'utils',
|
||||
)
|
||||
|
||||
__version__ = '2.14.3'
|
||||
__api_version__ = '5.3'
|
||||
83
IKEA_scrapper/.venv/Lib/site-packages/aiogram/__main__.py
Normal file
83
IKEA_scrapper/.venv/Lib/site-packages/aiogram/__main__.py
Normal file
@ -0,0 +1,83 @@
|
||||
import platform
|
||||
import sys
|
||||
|
||||
import aiohttp
|
||||
|
||||
import aiogram
|
||||
from aiogram.utils import json
|
||||
|
||||
|
||||
class SysInfo:
|
||||
@property
|
||||
def os(self):
|
||||
return platform.platform()
|
||||
|
||||
@property
|
||||
def python_implementation(self):
|
||||
return platform.python_implementation()
|
||||
|
||||
@property
|
||||
def python(self):
|
||||
return sys.version.replace('\n', '')
|
||||
|
||||
@property
|
||||
def aiogram(self):
|
||||
return aiogram.__version__
|
||||
|
||||
@property
|
||||
def api(self):
|
||||
return aiogram.__api_version__
|
||||
|
||||
@property
|
||||
def uvloop(self):
|
||||
try:
|
||||
import uvloop
|
||||
except ImportError:
|
||||
return
|
||||
return uvloop.__version__
|
||||
|
||||
@property
|
||||
def ujson(self):
|
||||
try:
|
||||
import ujson
|
||||
except ImportError:
|
||||
return
|
||||
return ujson.__version__
|
||||
|
||||
@property
|
||||
def rapidjson(self):
|
||||
try:
|
||||
import rapidjson
|
||||
except ImportError:
|
||||
return
|
||||
return rapidjson.__version__
|
||||
|
||||
@property
|
||||
def aiohttp(self):
|
||||
return aiohttp.__version__
|
||||
|
||||
def collect(self):
|
||||
yield f'{self.python_implementation}: {self.python}'
|
||||
yield f'OS: {self.os}'
|
||||
yield f'aiogram: {self.aiogram}'
|
||||
yield f'aiohttp: {self.aiohttp}'
|
||||
|
||||
uvloop = self.uvloop
|
||||
if uvloop:
|
||||
yield f'uvloop: {uvloop}'
|
||||
|
||||
yield f'JSON mode: {json.mode}'
|
||||
|
||||
rapidjson = self.rapidjson
|
||||
if rapidjson:
|
||||
yield f'rapidjson: {rapidjson}'
|
||||
ujson = self.ujson
|
||||
if ujson:
|
||||
yield f'ujson: {ujson}'
|
||||
|
||||
def __str__(self):
|
||||
return '\n'.join(self.collect())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(SysInfo())
|
||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,9 @@
|
||||
from . import api
|
||||
from .base import BaseBot
|
||||
from .bot import Bot
|
||||
|
||||
__all__ = (
|
||||
'BaseBot',
|
||||
'Bot',
|
||||
'api',
|
||||
)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
290
IKEA_scrapper/.venv/Lib/site-packages/aiogram/bot/api.py
Normal file
290
IKEA_scrapper/.venv/Lib/site-packages/aiogram/bot/api.py
Normal file
@ -0,0 +1,290 @@
|
||||
import logging
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from http import HTTPStatus
|
||||
|
||||
import aiohttp
|
||||
|
||||
from .. import types
|
||||
from ..utils import exceptions, json
|
||||
from ..utils.helper import Helper, HelperMode, Item
|
||||
|
||||
# Main aiogram logger
|
||||
log = logging.getLogger('aiogram')
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TelegramAPIServer:
|
||||
"""
|
||||
Base config for API Endpoints
|
||||
"""
|
||||
|
||||
base: str
|
||||
file: str
|
||||
|
||||
def api_url(self, token: str, method: str) -> str:
|
||||
"""
|
||||
Generate URL for API methods
|
||||
|
||||
:param token: Bot token
|
||||
:param method: API method name (case insensitive)
|
||||
:return: URL
|
||||
"""
|
||||
return self.base.format(token=token, method=method)
|
||||
|
||||
def file_url(self, token: str, path: str) -> str:
|
||||
"""
|
||||
Generate URL for downloading files
|
||||
|
||||
:param token: Bot token
|
||||
:param path: file path
|
||||
:return: URL
|
||||
"""
|
||||
return self.file.format(token=token, path=path)
|
||||
|
||||
@classmethod
|
||||
def from_base(cls, base: str) -> 'TelegramAPIServer':
|
||||
base = base.rstrip("/")
|
||||
return cls(
|
||||
base=f"{base}/bot{{token}}/{{method}}",
|
||||
file=f"{base}/file/bot{{token}}/{{path}}",
|
||||
)
|
||||
|
||||
|
||||
TELEGRAM_PRODUCTION = TelegramAPIServer.from_base("https://api.telegram.org")
|
||||
|
||||
|
||||
def check_token(token: str) -> bool:
|
||||
"""
|
||||
Validate BOT token
|
||||
|
||||
:param token:
|
||||
:return:
|
||||
"""
|
||||
if not isinstance(token, str):
|
||||
message = (f"Token is invalid! "
|
||||
f"It must be 'str' type instead of {type(token)} type.")
|
||||
raise exceptions.ValidationError(message)
|
||||
|
||||
if any(x.isspace() for x in token):
|
||||
message = "Token is invalid! It can't contains spaces."
|
||||
raise exceptions.ValidationError(message)
|
||||
|
||||
left, sep, right = token.partition(':')
|
||||
if (not sep) or (not left.isdigit()) or (not right):
|
||||
raise exceptions.ValidationError('Token is invalid!')
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def check_result(method_name: str, content_type: str, status_code: int, body: str):
|
||||
"""
|
||||
Checks whether `result` is a valid API response.
|
||||
A result is considered invalid if:
|
||||
- The server returned an HTTP response code other than 200
|
||||
- The content of the result is invalid JSON.
|
||||
- The method call was unsuccessful (The JSON 'ok' field equals False)
|
||||
|
||||
:param method_name: The name of the method called
|
||||
:param status_code: status code
|
||||
:param content_type: content type of result
|
||||
:param body: result body
|
||||
:return: The result parsed to a JSON dictionary
|
||||
:raises ApiException: if one of the above listed cases is applicable
|
||||
"""
|
||||
log.debug('Response for %s: [%d] "%r"', method_name, status_code, body)
|
||||
|
||||
if content_type != 'application/json':
|
||||
raise exceptions.NetworkError(f"Invalid response with content type {content_type}: \"{body}\"")
|
||||
|
||||
try:
|
||||
result_json = json.loads(body)
|
||||
except ValueError:
|
||||
result_json = {}
|
||||
|
||||
description = result_json.get('description') or body
|
||||
parameters = types.ResponseParameters(**result_json.get('parameters', {}) or {})
|
||||
|
||||
if HTTPStatus.OK <= status_code <= HTTPStatus.IM_USED:
|
||||
return result_json.get('result')
|
||||
elif parameters.retry_after:
|
||||
raise exceptions.RetryAfter(parameters.retry_after)
|
||||
elif parameters.migrate_to_chat_id:
|
||||
raise exceptions.MigrateToChat(parameters.migrate_to_chat_id)
|
||||
elif status_code == HTTPStatus.BAD_REQUEST:
|
||||
exceptions.BadRequest.detect(description)
|
||||
elif status_code == HTTPStatus.NOT_FOUND:
|
||||
exceptions.NotFound.detect(description)
|
||||
elif status_code == HTTPStatus.CONFLICT:
|
||||
exceptions.ConflictError.detect(description)
|
||||
elif status_code in (HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN):
|
||||
exceptions.Unauthorized.detect(description)
|
||||
elif status_code == HTTPStatus.REQUEST_ENTITY_TOO_LARGE:
|
||||
raise exceptions.NetworkError('File too large for uploading. '
|
||||
'Check telegram api limits https://core.telegram.org/bots/api#senddocument')
|
||||
elif status_code >= HTTPStatus.INTERNAL_SERVER_ERROR:
|
||||
if 'restart' in description:
|
||||
raise exceptions.RestartingTelegram()
|
||||
raise exceptions.TelegramAPIError(description)
|
||||
raise exceptions.TelegramAPIError(f"{description} [{status_code}]")
|
||||
|
||||
|
||||
async def make_request(session, server, token, method, data=None, files=None, **kwargs):
|
||||
log.debug('Make request: "%s" with data: "%r" and files "%r"', method, data, files)
|
||||
|
||||
url = server.api_url(token=token, method=method)
|
||||
|
||||
req = compose_data(data, files)
|
||||
try:
|
||||
async with session.post(url, data=req, **kwargs) as response:
|
||||
return check_result(method, response.content_type, response.status, await response.text())
|
||||
except aiohttp.ClientError as e:
|
||||
raise exceptions.NetworkError(f"aiohttp client throws an error: {e.__class__.__name__}: {e}")
|
||||
|
||||
|
||||
def guess_filename(obj):
|
||||
"""
|
||||
Get file name from object
|
||||
|
||||
:param obj:
|
||||
:return:
|
||||
"""
|
||||
name = getattr(obj, 'name', None)
|
||||
if name and isinstance(name, str) and name[0] != '<' and name[-1] != '>':
|
||||
return os.path.basename(name)
|
||||
|
||||
|
||||
def compose_data(params=None, files=None):
|
||||
"""
|
||||
Prepare request data
|
||||
|
||||
:param params:
|
||||
:param files:
|
||||
:return:
|
||||
"""
|
||||
data = aiohttp.formdata.FormData(quote_fields=False)
|
||||
|
||||
if params:
|
||||
for key, value in params.items():
|
||||
data.add_field(key, str(value))
|
||||
|
||||
if files:
|
||||
for key, f in files.items():
|
||||
if isinstance(f, tuple):
|
||||
if len(f) == 2:
|
||||
filename, fileobj = f
|
||||
else:
|
||||
raise ValueError('Tuple must have exactly 2 elements: filename, fileobj')
|
||||
elif isinstance(f, types.InputFile):
|
||||
filename, fileobj = f.filename, f.file
|
||||
else:
|
||||
filename, fileobj = guess_filename(f) or key, f
|
||||
|
||||
data.add_field(key, fileobj, filename=filename)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class Methods(Helper):
|
||||
"""
|
||||
Helper for Telegram API Methods listed on https://core.telegram.org/bots/api
|
||||
|
||||
List is updated to Bot API 5.3
|
||||
"""
|
||||
mode = HelperMode.lowerCamelCase
|
||||
|
||||
# Getting Updates
|
||||
GET_UPDATES = Item() # getUpdates
|
||||
SET_WEBHOOK = Item() # setWebhook
|
||||
DELETE_WEBHOOK = Item() # deleteWebhook
|
||||
GET_WEBHOOK_INFO = Item() # getWebhookInfo
|
||||
|
||||
# Available methods
|
||||
GET_ME = Item() # getMe
|
||||
LOG_OUT = Item() # logOut
|
||||
CLOSE = Item() # close
|
||||
SEND_MESSAGE = Item() # sendMessage
|
||||
FORWARD_MESSAGE = Item() # forwardMessage
|
||||
COPY_MESSAGE = Item() # copyMessage
|
||||
SEND_PHOTO = Item() # sendPhoto
|
||||
SEND_AUDIO = Item() # sendAudio
|
||||
SEND_DOCUMENT = Item() # sendDocument
|
||||
SEND_VIDEO = Item() # sendVideo
|
||||
SEND_ANIMATION = Item() # sendAnimation
|
||||
SEND_VOICE = Item() # sendVoice
|
||||
SEND_VIDEO_NOTE = Item() # sendVideoNote
|
||||
SEND_MEDIA_GROUP = Item() # sendMediaGroup
|
||||
SEND_LOCATION = Item() # sendLocation
|
||||
EDIT_MESSAGE_LIVE_LOCATION = Item() # editMessageLiveLocation
|
||||
STOP_MESSAGE_LIVE_LOCATION = Item() # stopMessageLiveLocation
|
||||
SEND_VENUE = Item() # sendVenue
|
||||
SEND_CONTACT = Item() # sendContact
|
||||
SEND_POLL = Item() # sendPoll
|
||||
SEND_DICE = Item() # sendDice
|
||||
SEND_CHAT_ACTION = Item() # sendChatAction
|
||||
GET_USER_PROFILE_PHOTOS = Item() # getUserProfilePhotos
|
||||
GET_FILE = Item() # getFile
|
||||
KICK_CHAT_MEMBER = Item() # kickChatMember
|
||||
BAN_CHAT_MEMBER = Item() # banChatMember
|
||||
UNBAN_CHAT_MEMBER = Item() # unbanChatMember
|
||||
RESTRICT_CHAT_MEMBER = Item() # restrictChatMember
|
||||
PROMOTE_CHAT_MEMBER = Item() # promoteChatMember
|
||||
SET_CHAT_ADMINISTRATOR_CUSTOM_TITLE = Item() # setChatAdministratorCustomTitle
|
||||
SET_CHAT_PERMISSIONS = Item() # setChatPermissions
|
||||
EXPORT_CHAT_INVITE_LINK = Item() # exportChatInviteLink
|
||||
CREATE_CHAT_INVITE_LINK = Item() # createChatInviteLink
|
||||
EDIT_CHAT_INVITE_LINK = Item() # editChatInviteLink
|
||||
REVOKE_CHAT_INVITE_LINK = Item() # revokeChatInviteLink
|
||||
SET_CHAT_PHOTO = Item() # setChatPhoto
|
||||
DELETE_CHAT_PHOTO = Item() # deleteChatPhoto
|
||||
SET_CHAT_TITLE = Item() # setChatTitle
|
||||
SET_CHAT_DESCRIPTION = Item() # setChatDescription
|
||||
PIN_CHAT_MESSAGE = Item() # pinChatMessage
|
||||
UNPIN_CHAT_MESSAGE = Item() # unpinChatMessage
|
||||
UNPIN_ALL_CHAT_MESSAGES = Item() # unpinAllChatMessages
|
||||
LEAVE_CHAT = Item() # leaveChat
|
||||
GET_CHAT = Item() # getChat
|
||||
GET_CHAT_ADMINISTRATORS = Item() # getChatAdministrators
|
||||
GET_CHAT_MEMBER_COUNT = Item() # getChatMemberCount
|
||||
GET_CHAT_MEMBERS_COUNT = Item() # getChatMembersCount (renamed to getChatMemberCount)
|
||||
GET_CHAT_MEMBER = Item() # getChatMember
|
||||
SET_CHAT_STICKER_SET = Item() # setChatStickerSet
|
||||
DELETE_CHAT_STICKER_SET = Item() # deleteChatStickerSet
|
||||
ANSWER_CALLBACK_QUERY = Item() # answerCallbackQuery
|
||||
SET_MY_COMMANDS = Item() # setMyCommands
|
||||
DELETE_MY_COMMANDS = Item() # deleteMyCommands
|
||||
GET_MY_COMMANDS = Item() # getMyCommands
|
||||
|
||||
# Updating messages
|
||||
EDIT_MESSAGE_TEXT = Item() # editMessageText
|
||||
EDIT_MESSAGE_CAPTION = Item() # editMessageCaption
|
||||
EDIT_MESSAGE_MEDIA = Item() # editMessageMedia
|
||||
EDIT_MESSAGE_REPLY_MARKUP = Item() # editMessageReplyMarkup
|
||||
STOP_POLL = Item() # stopPoll
|
||||
DELETE_MESSAGE = Item() # deleteMessage
|
||||
|
||||
# Stickers
|
||||
SEND_STICKER = Item() # sendSticker
|
||||
GET_STICKER_SET = Item() # getStickerSet
|
||||
UPLOAD_STICKER_FILE = Item() # uploadStickerFile
|
||||
CREATE_NEW_STICKER_SET = Item() # createNewStickerSet
|
||||
ADD_STICKER_TO_SET = Item() # addStickerToSet
|
||||
SET_STICKER_POSITION_IN_SET = Item() # setStickerPositionInSet
|
||||
DELETE_STICKER_FROM_SET = Item() # deleteStickerFromSet
|
||||
SET_STICKER_SET_THUMB = Item() # setStickerSetThumb
|
||||
|
||||
# Inline mode
|
||||
ANSWER_INLINE_QUERY = Item() # answerInlineQuery
|
||||
|
||||
# Payments
|
||||
SEND_INVOICE = Item() # sendInvoice
|
||||
ANSWER_SHIPPING_QUERY = Item() # answerShippingQuery
|
||||
ANSWER_PRE_CHECKOUT_QUERY = Item() # answerPreCheckoutQuery
|
||||
|
||||
# Telegram Passport
|
||||
SET_PASSPORT_DATA_ERRORS = Item() # setPassportDataErrors
|
||||
|
||||
# Games
|
||||
SEND_GAME = Item() # sendGame
|
||||
SET_GAME_SCORE = Item() # setGameScore
|
||||
GET_GAME_HIGH_SCORES = Item() # getGameHighScores
|
||||
298
IKEA_scrapper/.venv/Lib/site-packages/aiogram/bot/base.py
Normal file
298
IKEA_scrapper/.venv/Lib/site-packages/aiogram/bot/base.py
Normal file
@ -0,0 +1,298 @@
|
||||
import asyncio
|
||||
import contextlib
|
||||
import io
|
||||
import ssl
|
||||
import typing
|
||||
import warnings
|
||||
from contextvars import ContextVar
|
||||
from typing import Dict, List, Optional, Union, Type
|
||||
|
||||
import aiohttp
|
||||
import certifi
|
||||
from aiohttp.helpers import sentinel
|
||||
|
||||
from . import api
|
||||
from .api import TelegramAPIServer, TELEGRAM_PRODUCTION
|
||||
from ..types import ParseMode, base
|
||||
from ..utils import json
|
||||
from ..utils.auth_widget import check_integrity
|
||||
from ..utils.deprecated import deprecated
|
||||
|
||||
|
||||
class BaseBot:
|
||||
"""
|
||||
Base class for bot. It's raw bot.
|
||||
"""
|
||||
_ctx_timeout = ContextVar('TelegramRequestTimeout')
|
||||
_ctx_token = ContextVar('BotDifferentToken')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
token: base.String,
|
||||
loop: Optional[Union[asyncio.BaseEventLoop, asyncio.AbstractEventLoop]] = None,
|
||||
connections_limit: Optional[base.Integer] = None,
|
||||
proxy: Optional[base.String] = None,
|
||||
proxy_auth: Optional[aiohttp.BasicAuth] = None,
|
||||
validate_token: Optional[base.Boolean] = True,
|
||||
parse_mode: typing.Optional[base.String] = None,
|
||||
timeout: typing.Optional[typing.Union[base.Integer, base.Float, aiohttp.ClientTimeout]] = None,
|
||||
server: TelegramAPIServer = TELEGRAM_PRODUCTION
|
||||
):
|
||||
"""
|
||||
Instructions how to get Bot token is found here: https://core.telegram.org/bots#3-how-do-i-create-a-bot
|
||||
|
||||
:param token: token from @BotFather
|
||||
:type token: :obj:`str`
|
||||
:param loop: event loop
|
||||
:type loop: Optional Union :obj:`asyncio.BaseEventLoop`, :obj:`asyncio.AbstractEventLoop`
|
||||
:param connections_limit: connections limit for aiohttp.ClientSession
|
||||
:type connections_limit: :obj:`int`
|
||||
:param proxy: HTTP proxy URL
|
||||
:type proxy: :obj:`str`
|
||||
:param proxy_auth: Authentication information
|
||||
:type proxy_auth: Optional :obj:`aiohttp.BasicAuth`
|
||||
:param validate_token: Validate token.
|
||||
:type validate_token: :obj:`bool`
|
||||
:param parse_mode: You can set default parse mode
|
||||
:type parse_mode: :obj:`str`
|
||||
:param timeout: Request timeout
|
||||
:type timeout: :obj:`typing.Optional[typing.Union[base.Integer, base.Float, aiohttp.ClientTimeout]]`
|
||||
:param server: Telegram Bot API Server endpoint.
|
||||
:type server: :obj:`TelegramAPIServer`
|
||||
:raise: when token is invalid throw an :obj:`aiogram.utils.exceptions.ValidationError`
|
||||
"""
|
||||
self._main_loop = loop
|
||||
|
||||
# Authentication
|
||||
if validate_token:
|
||||
api.check_token(token)
|
||||
self._token = None
|
||||
self.__token = token
|
||||
self.id = int(token.split(sep=':')[0])
|
||||
self.server = server
|
||||
|
||||
self.proxy = proxy
|
||||
self.proxy_auth = proxy_auth
|
||||
|
||||
# aiohttp main session
|
||||
ssl_context = ssl.create_default_context(cafile=certifi.where())
|
||||
|
||||
self._session: Optional[aiohttp.ClientSession] = None
|
||||
self._connector_class: Type[aiohttp.TCPConnector] = aiohttp.TCPConnector
|
||||
self._connector_init = dict(limit=connections_limit, ssl=ssl_context)
|
||||
|
||||
if isinstance(proxy, str) and (proxy.startswith('socks5://') or proxy.startswith('socks4://')):
|
||||
from aiohttp_socks import SocksConnector
|
||||
from aiohttp_socks.utils import parse_proxy_url
|
||||
|
||||
socks_ver, host, port, username, password = parse_proxy_url(proxy)
|
||||
if proxy_auth:
|
||||
if not username:
|
||||
username = proxy_auth.login
|
||||
if not password:
|
||||
password = proxy_auth.password
|
||||
|
||||
self._connector_class = SocksConnector
|
||||
self._connector_init.update(
|
||||
socks_ver=socks_ver, host=host, port=port,
|
||||
username=username, password=password, rdns=True,
|
||||
)
|
||||
self.proxy = None
|
||||
self.proxy_auth = None
|
||||
|
||||
self._timeout = None
|
||||
self.timeout = timeout
|
||||
|
||||
self.parse_mode = parse_mode
|
||||
|
||||
def get_new_session(self) -> aiohttp.ClientSession:
|
||||
return aiohttp.ClientSession(
|
||||
connector=self._connector_class(**self._connector_init, loop=self._main_loop),
|
||||
loop=self._main_loop,
|
||||
json_serialize=json.dumps
|
||||
)
|
||||
|
||||
@property
|
||||
def loop(self) -> Optional[asyncio.AbstractEventLoop]:
|
||||
return self._main_loop
|
||||
|
||||
@property
|
||||
def session(self) -> Optional[aiohttp.ClientSession]:
|
||||
if self._session is None or self._session.closed:
|
||||
self._session = self.get_new_session()
|
||||
return self._session
|
||||
|
||||
@staticmethod
|
||||
def _prepare_timeout(
|
||||
value: typing.Optional[typing.Union[base.Integer, base.Float, aiohttp.ClientTimeout]]
|
||||
) -> typing.Optional[aiohttp.ClientTimeout]:
|
||||
if value is None or isinstance(value, aiohttp.ClientTimeout):
|
||||
return value
|
||||
return aiohttp.ClientTimeout(total=value)
|
||||
|
||||
@property
|
||||
def timeout(self):
|
||||
timeout = self._ctx_timeout.get(self._timeout)
|
||||
if timeout is None:
|
||||
return sentinel
|
||||
return timeout
|
||||
|
||||
@timeout.setter
|
||||
def timeout(self, value):
|
||||
self._timeout = self._prepare_timeout(value)
|
||||
|
||||
@timeout.deleter
|
||||
def timeout(self):
|
||||
self.timeout = None
|
||||
|
||||
@contextlib.contextmanager
|
||||
def request_timeout(self, timeout: typing.Union[base.Integer, base.Float, aiohttp.ClientTimeout]):
|
||||
"""
|
||||
Context manager implements opportunity to change request timeout in current context
|
||||
|
||||
:param timeout: Request timeout
|
||||
:type timeout: :obj:`typing.Optional[typing.Union[base.Integer, base.Float, aiohttp.ClientTimeout]]`
|
||||
:return:
|
||||
"""
|
||||
timeout = self._prepare_timeout(timeout)
|
||||
token = self._ctx_timeout.set(timeout)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
self._ctx_timeout.reset(token)
|
||||
|
||||
@property
|
||||
def __token(self):
|
||||
return self._ctx_token.get(self._token)
|
||||
|
||||
@__token.setter
|
||||
def __token(self, value):
|
||||
self._token = value
|
||||
|
||||
@contextlib.contextmanager
|
||||
def with_token(self, bot_token: base.String, validate_token: Optional[base.Boolean] = True):
|
||||
if validate_token:
|
||||
api.check_token(bot_token)
|
||||
token = self._ctx_token.set(bot_token)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
self._ctx_token.reset(token)
|
||||
|
||||
@deprecated("This method's behavior will be changed in aiogram v3.0. "
|
||||
"More info: https://core.telegram.org/bots/api#close", stacklevel=3)
|
||||
async def close(self):
|
||||
"""
|
||||
Close all client sessions
|
||||
"""
|
||||
await self.session.close()
|
||||
|
||||
async def request(self, method: base.String,
|
||||
data: Optional[Dict] = None,
|
||||
files: Optional[Dict] = None, **kwargs) -> Union[List, Dict, base.Boolean]:
|
||||
"""
|
||||
Make an request to Telegram Bot API
|
||||
|
||||
https://core.telegram.org/bots/api#making-requests
|
||||
|
||||
:param method: API method
|
||||
:type method: :obj:`str`
|
||||
:param data: request parameters
|
||||
:type data: :obj:`dict`
|
||||
:param files: files
|
||||
:type files: :obj:`dict`
|
||||
:return: result
|
||||
:rtype: Union[List, Dict]
|
||||
:raise: :obj:`aiogram.exceptions.TelegramApiError`
|
||||
"""
|
||||
return await api.make_request(self.session, self.server, self.__token, method, data, files,
|
||||
proxy=self.proxy, proxy_auth=self.proxy_auth, timeout=self.timeout, **kwargs)
|
||||
|
||||
async def download_file(self, file_path: base.String,
|
||||
destination: Optional[base.InputFile] = None,
|
||||
timeout: Optional[base.Integer] = sentinel,
|
||||
chunk_size: Optional[base.Integer] = 65536,
|
||||
seek: Optional[base.Boolean] = True) -> Union[io.BytesIO, io.FileIO]:
|
||||
"""
|
||||
Download file by file_path to destination
|
||||
|
||||
if You want to automatically create destination (:class:`io.BytesIO`) use default
|
||||
value of destination and handle result of this method.
|
||||
|
||||
:param file_path: file path on telegram server (You can get it from :obj:`aiogram.types.File`)
|
||||
:type file_path: :obj:`str`
|
||||
:param destination: filename or instance of :class:`io.IOBase`. For e. g. :class:`io.BytesIO`
|
||||
:param timeout: Integer
|
||||
:param chunk_size: Integer
|
||||
:param seek: Boolean - go to start of file when downloading is finished.
|
||||
:return: destination
|
||||
"""
|
||||
if destination is None:
|
||||
destination = io.BytesIO()
|
||||
|
||||
url = self.get_file_url(file_path)
|
||||
|
||||
dest = destination if isinstance(destination, io.IOBase) else open(destination, 'wb')
|
||||
async with self.session.get(url, timeout=timeout, proxy=self.proxy, proxy_auth=self.proxy_auth) as response:
|
||||
while True:
|
||||
chunk = await response.content.read(chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
dest.write(chunk)
|
||||
dest.flush()
|
||||
if seek:
|
||||
dest.seek(0)
|
||||
return dest
|
||||
|
||||
def get_file_url(self, file_path):
|
||||
return self.server.file_url(token=self.__token, path=file_path)
|
||||
|
||||
async def send_file(self, file_type, method, file, payload) -> Union[Dict, base.Boolean]:
|
||||
"""
|
||||
Send file
|
||||
|
||||
https://core.telegram.org/bots/api#inputfile
|
||||
|
||||
:param file_type: field name
|
||||
:param method: API method
|
||||
:param file: String or io.IOBase
|
||||
:param payload: request payload
|
||||
:return: response
|
||||
"""
|
||||
if file is None:
|
||||
files = {}
|
||||
elif isinstance(file, str):
|
||||
# You can use file ID or URL in the most of requests
|
||||
payload[file_type] = file
|
||||
files = None
|
||||
else:
|
||||
files = {file_type: file}
|
||||
|
||||
return await self.request(method, payload, files)
|
||||
|
||||
@property
|
||||
def parse_mode(self):
|
||||
return getattr(self, '_parse_mode', None)
|
||||
|
||||
@parse_mode.setter
|
||||
def parse_mode(self, value):
|
||||
if value is None:
|
||||
setattr(self, '_parse_mode', None)
|
||||
else:
|
||||
if not isinstance(value, str):
|
||||
raise TypeError(f"Parse mode must be str, not {type(value)}")
|
||||
value = value.lower()
|
||||
if value not in ParseMode.all():
|
||||
raise ValueError(f"Parse mode must be one of {ParseMode.all()}")
|
||||
setattr(self, '_parse_mode', value)
|
||||
if value == 'markdown':
|
||||
warnings.warn("Parse mode `Markdown` is legacy since Telegram Bot API 4.5, "
|
||||
"retained for backward compatibility. Use `MarkdownV2` instead.\n"
|
||||
"https://core.telegram.org/bots/api#markdown-style", stacklevel=3)
|
||||
|
||||
@parse_mode.deleter
|
||||
def parse_mode(self):
|
||||
self.parse_mode = None
|
||||
|
||||
def check_auth_widget(self, data):
|
||||
return check_integrity(self.__token, data)
|
||||
3243
IKEA_scrapper/.venv/Lib/site-packages/aiogram/bot/bot.py
Normal file
3243
IKEA_scrapper/.venv/Lib/site-packages/aiogram/bot/bot.py
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,59 @@
|
||||
import json
|
||||
import pathlib
|
||||
import pickle
|
||||
import typing
|
||||
|
||||
from .memory import MemoryStorage
|
||||
|
||||
|
||||
class _FileStorage(MemoryStorage):
|
||||
def __init__(self, path: typing.Union[pathlib.Path, str]):
|
||||
"""
|
||||
:param path: file path
|
||||
"""
|
||||
super(_FileStorage, self).__init__()
|
||||
path = self.path = pathlib.Path(path)
|
||||
|
||||
try:
|
||||
self.data = self.read(path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
async def close(self):
|
||||
if self.data:
|
||||
self.write(self.path)
|
||||
await super(_FileStorage, self).close()
|
||||
|
||||
def read(self, path: pathlib.Path):
|
||||
raise NotImplementedError
|
||||
|
||||
def write(self, path: pathlib.Path):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class JSONStorage(_FileStorage):
|
||||
"""
|
||||
JSON File storage based on MemoryStorage
|
||||
"""
|
||||
|
||||
def read(self, path: pathlib.Path):
|
||||
with path.open('r') as f:
|
||||
return json.load(f)
|
||||
|
||||
def write(self, path: pathlib.Path):
|
||||
with path.open('w') as f:
|
||||
return json.dump(self.data, f, indent=4)
|
||||
|
||||
|
||||
class PickleStorage(_FileStorage):
|
||||
"""
|
||||
Pickle File storage based on MemoryStorage
|
||||
"""
|
||||
|
||||
def read(self, path: pathlib.Path):
|
||||
with path.open('rb') as f:
|
||||
return pickle.load(f)
|
||||
|
||||
def write(self, path: pathlib.Path):
|
||||
with path.open('wb') as f:
|
||||
return pickle.dump(self.data, f, protocol=pickle.HIGHEST_PROTOCOL)
|
||||
@ -0,0 +1,112 @@
|
||||
import copy
|
||||
import typing
|
||||
|
||||
from ...dispatcher.storage import BaseStorage
|
||||
|
||||
|
||||
class MemoryStorage(BaseStorage):
|
||||
"""
|
||||
In-memory based states storage.
|
||||
|
||||
This type of storage is not recommended for usage in bots, because you will lost all states after restarting.
|
||||
"""
|
||||
|
||||
async def wait_closed(self):
|
||||
pass
|
||||
|
||||
async def close(self):
|
||||
self.data.clear()
|
||||
|
||||
def __init__(self):
|
||||
self.data = {}
|
||||
|
||||
def resolve_address(self, chat, user):
|
||||
chat_id, user_id = map(str, self.check_address(chat=chat, user=user))
|
||||
|
||||
if chat_id not in self.data:
|
||||
self.data[chat_id] = {}
|
||||
if user_id not in self.data[chat_id]:
|
||||
self.data[chat_id][user_id] = {'state': None, 'data': {}, 'bucket': {}}
|
||||
|
||||
return chat_id, user_id
|
||||
|
||||
async def get_state(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Optional[str]:
|
||||
chat, user = self.resolve_address(chat=chat, user=user)
|
||||
return self.data[chat][user].get("state", self.resolve_state(default))
|
||||
|
||||
async def get_data(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Dict:
|
||||
chat, user = self.resolve_address(chat=chat, user=user)
|
||||
return copy.deepcopy(self.data[chat][user]['data'])
|
||||
|
||||
async def update_data(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None, **kwargs):
|
||||
if data is None:
|
||||
data = {}
|
||||
chat, user = self.resolve_address(chat=chat, user=user)
|
||||
self.data[chat][user]['data'].update(data, **kwargs)
|
||||
|
||||
async def set_state(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
state: typing.AnyStr = None):
|
||||
chat, user = self.resolve_address(chat=chat, user=user)
|
||||
self.data[chat][user]['state'] = self.resolve_state(state)
|
||||
|
||||
async def set_data(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None):
|
||||
chat, user = self.resolve_address(chat=chat, user=user)
|
||||
self.data[chat][user]['data'] = copy.deepcopy(data)
|
||||
self._cleanup(chat, user)
|
||||
|
||||
async def reset_state(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
with_data: typing.Optional[bool] = True):
|
||||
await self.set_state(chat=chat, user=user, state=None)
|
||||
if with_data:
|
||||
await self.set_data(chat=chat, user=user, data={})
|
||||
self._cleanup(chat, user)
|
||||
|
||||
def has_bucket(self):
|
||||
return True
|
||||
|
||||
async def get_bucket(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[dict] = None) -> typing.Dict:
|
||||
chat, user = self.resolve_address(chat=chat, user=user)
|
||||
return copy.deepcopy(self.data[chat][user]['bucket'])
|
||||
|
||||
async def set_bucket(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
bucket: typing.Dict = None):
|
||||
chat, user = self.resolve_address(chat=chat, user=user)
|
||||
self.data[chat][user]['bucket'] = copy.deepcopy(bucket)
|
||||
self._cleanup(chat, user)
|
||||
|
||||
async def update_bucket(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
bucket: typing.Dict = None, **kwargs):
|
||||
if bucket is None:
|
||||
bucket = {}
|
||||
chat, user = self.resolve_address(chat=chat, user=user)
|
||||
self.data[chat][user]['bucket'].update(bucket, **kwargs)
|
||||
|
||||
def _cleanup(self, chat, user):
|
||||
chat, user = self.resolve_address(chat=chat, user=user)
|
||||
if self.data[chat][user] == {'state': None, 'data': {}, 'bucket': {}}:
|
||||
del self.data[chat][user]
|
||||
if not self.data[chat]:
|
||||
del self.data[chat]
|
||||
@ -0,0 +1,224 @@
|
||||
"""
|
||||
This module has mongo storage for finite-state machine
|
||||
based on `motor <https://github.com/mongodb/motor>`_ driver
|
||||
"""
|
||||
|
||||
from typing import Union, Dict, Optional, List, Tuple, AnyStr
|
||||
|
||||
|
||||
try:
|
||||
import pymongo
|
||||
import motor
|
||||
from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase
|
||||
except ModuleNotFoundError as e:
|
||||
import warnings
|
||||
warnings.warn("Install motor with `pip install motor`")
|
||||
raise e
|
||||
|
||||
from ...dispatcher.storage import BaseStorage
|
||||
|
||||
STATE = 'aiogram_state'
|
||||
DATA = 'aiogram_data'
|
||||
BUCKET = 'aiogram_bucket'
|
||||
COLLECTIONS = (STATE, DATA, BUCKET)
|
||||
|
||||
|
||||
class MongoStorage(BaseStorage):
|
||||
"""
|
||||
Mongo-based storage for FSM.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
storage = MongoStorage(host='localhost', port=27017, db_name='aiogram_fsm')
|
||||
dp = Dispatcher(bot, storage=storage)
|
||||
|
||||
And need to close Mongo client connections when shutdown
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
await dp.storage.close()
|
||||
await dp.storage.wait_closed()
|
||||
"""
|
||||
|
||||
def __init__(self, host='localhost', port=27017, db_name='aiogram_fsm', uri=None,
|
||||
username=None, password=None, index=True, **kwargs):
|
||||
self._host = host
|
||||
self._port = port
|
||||
self._db_name: str = db_name
|
||||
self._uri = uri
|
||||
self._username = username
|
||||
self._password = password
|
||||
self._kwargs = kwargs
|
||||
|
||||
self._mongo: Optional[AsyncIOMotorClient] = None
|
||||
self._db: Optional[AsyncIOMotorDatabase] = None
|
||||
|
||||
self._index = index
|
||||
|
||||
async def get_client(self) -> AsyncIOMotorClient:
|
||||
if isinstance(self._mongo, AsyncIOMotorClient):
|
||||
return self._mongo
|
||||
|
||||
if self._uri:
|
||||
try:
|
||||
self._mongo = AsyncIOMotorClient(self._uri)
|
||||
except pymongo.errors.ConfigurationError as e:
|
||||
if "query() got an unexpected keyword argument 'lifetime'" in e.args[0]:
|
||||
import logging
|
||||
logger = logging.getLogger("aiogram")
|
||||
logger.warning("Run `pip install dnspython==1.16.0` in order to fix ConfigurationError. More information: https://github.com/mongodb/mongo-python-driver/pull/423#issuecomment-528998245")
|
||||
raise e
|
||||
return self._mongo
|
||||
|
||||
uri = 'mongodb://'
|
||||
|
||||
# set username + password
|
||||
if self._username and self._password:
|
||||
uri += f'{self._username}:{self._password}@'
|
||||
|
||||
# set host and port (optional)
|
||||
uri += f'{self._host}:{self._port}' if self._host else f'localhost:{self._port}'
|
||||
|
||||
# define and return client
|
||||
self._mongo = AsyncIOMotorClient(uri)
|
||||
return self._mongo
|
||||
|
||||
async def get_db(self) -> AsyncIOMotorDatabase:
|
||||
"""
|
||||
Get Mongo db
|
||||
|
||||
This property is awaitable.
|
||||
"""
|
||||
if isinstance(self._db, AsyncIOMotorDatabase):
|
||||
return self._db
|
||||
|
||||
mongo = await self.get_client()
|
||||
self._db = mongo.get_database(self._db_name)
|
||||
|
||||
if self._index:
|
||||
await self.apply_index(self._db)
|
||||
return self._db
|
||||
|
||||
@staticmethod
|
||||
async def apply_index(db):
|
||||
for collection in COLLECTIONS:
|
||||
await db[collection].create_index(keys=[('chat', 1), ('user', 1)],
|
||||
name="chat_user_idx", unique=True, background=True)
|
||||
|
||||
async def close(self):
|
||||
if self._mongo:
|
||||
self._mongo.close()
|
||||
|
||||
async def wait_closed(self):
|
||||
return True
|
||||
|
||||
async def set_state(self, *,
|
||||
chat: Union[str, int, None] = None,
|
||||
user: Union[str, int, None] = None,
|
||||
state: Optional[AnyStr] = None):
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
db = await self.get_db()
|
||||
|
||||
if state is None:
|
||||
await db[STATE].delete_one(filter={'chat': chat, 'user': user})
|
||||
else:
|
||||
await db[STATE].update_one(
|
||||
filter={'chat': chat, 'user': user},
|
||||
update={'$set': {'state': self.resolve_state(state)}},
|
||||
upsert=True,
|
||||
)
|
||||
|
||||
async def get_state(self, *, chat: Union[str, int, None] = None, user: Union[str, int, None] = None,
|
||||
default: Optional[str] = None) -> Optional[str]:
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
db = await self.get_db()
|
||||
result = await db[STATE].find_one(filter={'chat': chat, 'user': user})
|
||||
|
||||
return result.get('state') if result else self.resolve_state(default)
|
||||
|
||||
async def set_data(self, *, chat: Union[str, int, None] = None, user: Union[str, int, None] = None,
|
||||
data: Dict = None):
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
db = await self.get_db()
|
||||
if not data:
|
||||
await db[DATA].delete_one(filter={'chat': chat, 'user': user})
|
||||
else:
|
||||
await db[DATA].update_one(filter={'chat': chat, 'user': user},
|
||||
update={'$set': {'data': data}}, upsert=True)
|
||||
|
||||
async def get_data(self, *, chat: Union[str, int, None] = None, user: Union[str, int, None] = None,
|
||||
default: Optional[dict] = None) -> Dict:
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
db = await self.get_db()
|
||||
result = await db[DATA].find_one(filter={'chat': chat, 'user': user})
|
||||
|
||||
return result.get('data') if result else default or {}
|
||||
|
||||
async def update_data(self, *, chat: Union[str, int, None] = None, user: Union[str, int, None] = None,
|
||||
data: Dict = None, **kwargs):
|
||||
if data is None:
|
||||
data = {}
|
||||
temp_data = await self.get_data(chat=chat, user=user, default={})
|
||||
temp_data.update(data, **kwargs)
|
||||
await self.set_data(chat=chat, user=user, data=temp_data)
|
||||
|
||||
def has_bucket(self):
|
||||
return True
|
||||
|
||||
async def get_bucket(self, *, chat: Union[str, int, None] = None, user: Union[str, int, None] = None,
|
||||
default: Optional[dict] = None) -> Dict:
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
db = await self.get_db()
|
||||
result = await db[BUCKET].find_one(filter={'chat': chat, 'user': user})
|
||||
return result.get('bucket') if result else default or {}
|
||||
|
||||
async def set_bucket(self, *, chat: Union[str, int, None] = None, user: Union[str, int, None] = None,
|
||||
bucket: Dict = None):
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
db = await self.get_db()
|
||||
|
||||
await db[BUCKET].update_one(filter={'chat': chat, 'user': user},
|
||||
update={'$set': {'bucket': bucket}}, upsert=True)
|
||||
|
||||
async def update_bucket(self, *, chat: Union[str, int, None] = None,
|
||||
user: Union[str, int, None] = None,
|
||||
bucket: Dict = None, **kwargs):
|
||||
if bucket is None:
|
||||
bucket = {}
|
||||
temp_bucket = await self.get_bucket(chat=chat, user=user)
|
||||
temp_bucket.update(bucket, **kwargs)
|
||||
await self.set_bucket(chat=chat, user=user, bucket=temp_bucket)
|
||||
|
||||
async def reset_all(self, full=True):
|
||||
"""
|
||||
Reset states in DB
|
||||
|
||||
:param full: clean DB or clean only states
|
||||
:return:
|
||||
"""
|
||||
db = await self.get_db()
|
||||
|
||||
await db[STATE].drop()
|
||||
|
||||
if full:
|
||||
await db[DATA].drop()
|
||||
await db[BUCKET].drop()
|
||||
|
||||
async def get_states_list(self) -> List[Tuple[int, int]]:
|
||||
"""
|
||||
Get list of all stored chat's and user's
|
||||
|
||||
:return: list of tuples where first element is chat id and second is user id
|
||||
"""
|
||||
db = await self.get_db()
|
||||
result = []
|
||||
|
||||
items = await db[STATE].find().to_list()
|
||||
for item in items:
|
||||
result.append(
|
||||
(int(item['chat']), int(item['user']))
|
||||
)
|
||||
|
||||
return result
|
||||
@ -0,0 +1,414 @@
|
||||
"""
|
||||
This module has redis storage for finite-state machine based on `aioredis <https://github.com/aio-libs/aioredis>`_ driver
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import typing
|
||||
|
||||
import aioredis
|
||||
|
||||
from ...dispatcher.storage import BaseStorage
|
||||
from ...utils import json
|
||||
|
||||
STATE_KEY = 'state'
|
||||
STATE_DATA_KEY = 'data'
|
||||
STATE_BUCKET_KEY = 'bucket'
|
||||
|
||||
|
||||
class RedisStorage(BaseStorage):
|
||||
"""
|
||||
Simple Redis-base storage for FSM.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
storage = RedisStorage('localhost', 6379, db=5)
|
||||
dp = Dispatcher(bot, storage=storage)
|
||||
|
||||
And need to close Redis connection when shutdown
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
await dp.storage.close()
|
||||
await dp.storage.wait_closed()
|
||||
|
||||
"""
|
||||
def __init__(self, host='localhost', port=6379, db=None, password=None, ssl=None, loop=None, **kwargs):
|
||||
self._host = host
|
||||
self._port = port
|
||||
self._db = db
|
||||
self._password = password
|
||||
self._ssl = ssl
|
||||
self._loop = loop or asyncio.get_event_loop()
|
||||
self._kwargs = kwargs
|
||||
|
||||
self._redis: typing.Optional[aioredis.RedisConnection] = None
|
||||
self._connection_lock = asyncio.Lock(loop=self._loop)
|
||||
|
||||
async def close(self):
|
||||
async with self._connection_lock:
|
||||
if self._redis and not self._redis.closed:
|
||||
self._redis.close()
|
||||
|
||||
async def wait_closed(self):
|
||||
async with self._connection_lock:
|
||||
if self._redis:
|
||||
return await self._redis.wait_closed()
|
||||
return True
|
||||
|
||||
async def redis(self) -> aioredis.RedisConnection:
|
||||
"""
|
||||
Get Redis connection
|
||||
"""
|
||||
# Use thread-safe asyncio Lock because this method without that is not safe
|
||||
async with self._connection_lock:
|
||||
if self._redis is None or self._redis.closed:
|
||||
self._redis = await aioredis.create_connection((self._host, self._port),
|
||||
db=self._db, password=self._password, ssl=self._ssl,
|
||||
loop=self._loop,
|
||||
**self._kwargs)
|
||||
return self._redis
|
||||
|
||||
async def get_record(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None) -> typing.Dict:
|
||||
"""
|
||||
Get record from storage
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:return:
|
||||
"""
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
addr = f"fsm:{chat}:{user}"
|
||||
|
||||
conn = await self.redis()
|
||||
data = await conn.execute('GET', addr)
|
||||
if data is None:
|
||||
return {'state': None, 'data': {}}
|
||||
return json.loads(data)
|
||||
|
||||
async def set_record(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
state=None, data=None, bucket=None):
|
||||
"""
|
||||
Write record to storage
|
||||
|
||||
:param bucket:
|
||||
:param chat:
|
||||
:param user:
|
||||
:param state:
|
||||
:param data:
|
||||
:return:
|
||||
"""
|
||||
if data is None:
|
||||
data = {}
|
||||
if bucket is None:
|
||||
bucket = {}
|
||||
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
addr = f"fsm:{chat}:{user}"
|
||||
|
||||
conn = await self.redis()
|
||||
if state is None and data == bucket == {}:
|
||||
await conn.execute('DEL', addr)
|
||||
else:
|
||||
record = {'state': state, 'data': data, 'bucket': bucket}
|
||||
await conn.execute('SET', addr, json.dumps(record))
|
||||
|
||||
async def get_state(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Optional[str]:
|
||||
record = await self.get_record(chat=chat, user=user)
|
||||
return record.get('state', self.resolve_state(default))
|
||||
|
||||
async def get_data(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Dict:
|
||||
record = await self.get_record(chat=chat, user=user)
|
||||
return record['data']
|
||||
|
||||
async def set_state(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
state: typing.Optional[typing.AnyStr] = None):
|
||||
record = await self.get_record(chat=chat, user=user)
|
||||
state = self.resolve_state(state)
|
||||
await self.set_record(chat=chat, user=user, state=state, data=record['data'])
|
||||
|
||||
async def set_data(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None):
|
||||
record = await self.get_record(chat=chat, user=user)
|
||||
await self.set_record(chat=chat, user=user, state=record['state'], data=data)
|
||||
|
||||
async def update_data(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None, **kwargs):
|
||||
if data is None:
|
||||
data = {}
|
||||
record = await self.get_record(chat=chat, user=user)
|
||||
record_data = record.get('data', {})
|
||||
record_data.update(data, **kwargs)
|
||||
await self.set_record(chat=chat, user=user, state=record['state'], data=record_data)
|
||||
|
||||
async def get_states_list(self) -> typing.List[typing.Tuple[str, str]]:
|
||||
"""
|
||||
Get list of all stored chat's and user's
|
||||
|
||||
:return: list of tuples where first element is chat id and second is user id
|
||||
"""
|
||||
conn = await self.redis()
|
||||
result = []
|
||||
|
||||
keys = await conn.execute('KEYS', 'fsm:*')
|
||||
for item in keys:
|
||||
*_, chat, user = item.decode('utf-8').split(':')
|
||||
result.append((chat, user))
|
||||
|
||||
return result
|
||||
|
||||
async def reset_all(self, full=True):
|
||||
"""
|
||||
Reset states in DB
|
||||
|
||||
:param full: clean DB or clean only states
|
||||
:return:
|
||||
"""
|
||||
conn = await self.redis()
|
||||
|
||||
if full:
|
||||
await conn.execute('FLUSHDB')
|
||||
else:
|
||||
keys = await conn.execute('KEYS', 'fsm:*')
|
||||
await conn.execute('DEL', *keys)
|
||||
|
||||
def has_bucket(self):
|
||||
return True
|
||||
|
||||
async def get_bucket(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Dict:
|
||||
record = await self.get_record(chat=chat, user=user)
|
||||
return record.get('bucket', {})
|
||||
|
||||
async def set_bucket(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
bucket: typing.Dict = None):
|
||||
record = await self.get_record(chat=chat, user=user)
|
||||
await self.set_record(chat=chat, user=user, state=record['state'], data=record['data'], bucket=bucket)
|
||||
|
||||
async def update_bucket(self, *, chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
bucket: typing.Dict = None, **kwargs):
|
||||
record = await self.get_record(chat=chat, user=user)
|
||||
record_bucket = record.get('bucket', {})
|
||||
if bucket is None:
|
||||
bucket = {}
|
||||
record_bucket.update(bucket, **kwargs)
|
||||
await self.set_record(chat=chat, user=user, state=record['state'], data=record_bucket, bucket=bucket)
|
||||
|
||||
|
||||
class RedisStorage2(BaseStorage):
|
||||
"""
|
||||
Busted Redis-base storage for FSM.
|
||||
Works with Redis connection pool and customizable keys prefix.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
storage = RedisStorage2('localhost', 6379, db=5, pool_size=10, prefix='my_fsm_key')
|
||||
dp = Dispatcher(bot, storage=storage)
|
||||
|
||||
And need to close Redis connection when shutdown
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
await dp.storage.close()
|
||||
await dp.storage.wait_closed()
|
||||
|
||||
"""
|
||||
def __init__(self, host: str = 'localhost', port=6379, db=None, password=None,
|
||||
ssl=None, pool_size=10, loop=None, prefix='fsm',
|
||||
state_ttl: int = 0,
|
||||
data_ttl: int = 0,
|
||||
bucket_ttl: int = 0,
|
||||
**kwargs):
|
||||
self._host = host
|
||||
self._port = port
|
||||
self._db = db
|
||||
self._password = password
|
||||
self._ssl = ssl
|
||||
self._pool_size = pool_size
|
||||
self._loop = loop or asyncio.get_event_loop()
|
||||
self._kwargs = kwargs
|
||||
self._prefix = (prefix,)
|
||||
|
||||
self._state_ttl = state_ttl
|
||||
self._data_ttl = data_ttl
|
||||
self._bucket_ttl = bucket_ttl
|
||||
|
||||
self._redis: typing.Optional[aioredis.RedisConnection] = None
|
||||
self._connection_lock = asyncio.Lock(loop=self._loop)
|
||||
|
||||
async def redis(self) -> aioredis.Redis:
|
||||
"""
|
||||
Get Redis connection
|
||||
"""
|
||||
# Use thread-safe asyncio Lock because this method without that is not safe
|
||||
async with self._connection_lock:
|
||||
if self._redis is None or self._redis.closed:
|
||||
self._redis = await aioredis.create_redis_pool((self._host, self._port),
|
||||
db=self._db, password=self._password, ssl=self._ssl,
|
||||
minsize=1, maxsize=self._pool_size,
|
||||
loop=self._loop, **self._kwargs)
|
||||
return self._redis
|
||||
|
||||
def generate_key(self, *parts):
|
||||
return ':'.join(self._prefix + tuple(map(str, parts)))
|
||||
|
||||
async def close(self):
|
||||
async with self._connection_lock:
|
||||
if self._redis and not self._redis.closed:
|
||||
self._redis.close()
|
||||
|
||||
async def wait_closed(self):
|
||||
async with self._connection_lock:
|
||||
if self._redis:
|
||||
return await self._redis.wait_closed()
|
||||
return True
|
||||
|
||||
async def get_state(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Optional[str]:
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
key = self.generate_key(chat, user, STATE_KEY)
|
||||
redis = await self.redis()
|
||||
return await redis.get(key, encoding='utf8') or self.resolve_state(default)
|
||||
|
||||
async def get_data(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[dict] = None) -> typing.Dict:
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
key = self.generate_key(chat, user, STATE_DATA_KEY)
|
||||
redis = await self.redis()
|
||||
raw_result = await redis.get(key, encoding='utf8')
|
||||
if raw_result:
|
||||
return json.loads(raw_result)
|
||||
return default or {}
|
||||
|
||||
async def set_state(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
state: typing.Optional[typing.AnyStr] = None):
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
key = self.generate_key(chat, user, STATE_KEY)
|
||||
redis = await self.redis()
|
||||
if state is None:
|
||||
await redis.delete(key)
|
||||
else:
|
||||
await redis.set(key, self.resolve_state(state), expire=self._state_ttl)
|
||||
|
||||
async def set_data(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None):
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
key = self.generate_key(chat, user, STATE_DATA_KEY)
|
||||
redis = await self.redis()
|
||||
if data:
|
||||
await redis.set(key, json.dumps(data), expire=self._data_ttl)
|
||||
else:
|
||||
await redis.delete(key)
|
||||
|
||||
async def update_data(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None, **kwargs):
|
||||
if data is None:
|
||||
data = {}
|
||||
temp_data = await self.get_data(chat=chat, user=user, default={})
|
||||
temp_data.update(data, **kwargs)
|
||||
await self.set_data(chat=chat, user=user, data=temp_data)
|
||||
|
||||
def has_bucket(self):
|
||||
return True
|
||||
|
||||
async def get_bucket(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[dict] = None) -> typing.Dict:
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
key = self.generate_key(chat, user, STATE_BUCKET_KEY)
|
||||
redis = await self.redis()
|
||||
raw_result = await redis.get(key, encoding='utf8')
|
||||
if raw_result:
|
||||
return json.loads(raw_result)
|
||||
return default or {}
|
||||
|
||||
async def set_bucket(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
bucket: typing.Dict = None):
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
key = self.generate_key(chat, user, STATE_BUCKET_KEY)
|
||||
redis = await self.redis()
|
||||
if bucket:
|
||||
await redis.set(key, json.dumps(bucket), expire=self._bucket_ttl)
|
||||
else:
|
||||
await redis.delete(key)
|
||||
|
||||
async def update_bucket(self, *, chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
bucket: typing.Dict = None, **kwargs):
|
||||
if bucket is None:
|
||||
bucket = {}
|
||||
temp_bucket = await self.get_bucket(chat=chat, user=user)
|
||||
temp_bucket.update(bucket, **kwargs)
|
||||
await self.set_bucket(chat=chat, user=user, bucket=temp_bucket)
|
||||
|
||||
async def reset_all(self, full=True):
|
||||
"""
|
||||
Reset states in DB
|
||||
|
||||
:param full: clean DB or clean only states
|
||||
:return:
|
||||
"""
|
||||
conn = await self.redis()
|
||||
|
||||
if full:
|
||||
await conn.flushdb()
|
||||
else:
|
||||
keys = await conn.keys(self.generate_key('*'))
|
||||
await conn.delete(*keys)
|
||||
|
||||
async def get_states_list(self) -> typing.List[typing.Tuple[str, str]]:
|
||||
"""
|
||||
Get list of all stored chat's and user's
|
||||
|
||||
:return: list of tuples where first element is chat id and second is user id
|
||||
"""
|
||||
conn = await self.redis()
|
||||
result = []
|
||||
|
||||
keys = await conn.keys(self.generate_key('*', '*', STATE_KEY), encoding='utf8')
|
||||
for item in keys:
|
||||
*_, chat, user, _ = item.split(':')
|
||||
result.append((chat, user))
|
||||
|
||||
return result
|
||||
|
||||
async def import_redis1(self, redis1):
|
||||
await migrate_redis1_to_redis2(redis1, self)
|
||||
|
||||
|
||||
async def migrate_redis1_to_redis2(storage1: RedisStorage, storage2: RedisStorage2):
|
||||
"""
|
||||
Helper for migrating from RedisStorage to RedisStorage2
|
||||
|
||||
:param storage1: instance of RedisStorage
|
||||
:param storage2: instance of RedisStorage2
|
||||
:return:
|
||||
"""
|
||||
if not isinstance(storage1, RedisStorage): # better than assertion
|
||||
raise TypeError(f"{type(storage1)} is not RedisStorage instance.")
|
||||
if not isinstance(storage2, RedisStorage):
|
||||
raise TypeError(f"{type(storage2)} is not RedisStorage instance.")
|
||||
|
||||
log = logging.getLogger('aiogram.RedisStorage')
|
||||
|
||||
for chat, user in await storage1.get_states_list():
|
||||
state = await storage1.get_state(chat=chat, user=user)
|
||||
await storage2.set_state(chat=chat, user=user, state=state)
|
||||
|
||||
data = await storage1.get_data(chat=chat, user=user)
|
||||
await storage2.set_data(chat=chat, user=user, data=data)
|
||||
|
||||
bucket = await storage1.get_bucket(chat=chat, user=user)
|
||||
await storage2.set_bucket(chat=chat, user=user, bucket=bucket)
|
||||
|
||||
log.info(f"Migrated user {user} in chat {chat}")
|
||||
@ -0,0 +1,184 @@
|
||||
import asyncio
|
||||
import contextlib
|
||||
import typing
|
||||
|
||||
import rethinkdb
|
||||
from rethinkdb.asyncio_net.net_asyncio import Connection
|
||||
|
||||
from ...dispatcher.storage import BaseStorage
|
||||
|
||||
__all__ = ('RethinkDBStorage',)
|
||||
|
||||
r = rethinkdb.RethinkDB()
|
||||
r.set_loop_type('asyncio')
|
||||
|
||||
|
||||
class RethinkDBStorage(BaseStorage):
|
||||
"""
|
||||
RethinkDB-based storage for FSM.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
storage = RethinkDBStorage(db='aiogram', table='aiogram', user='aiogram', password='aiogram_secret')
|
||||
dispatcher = Dispatcher(bot, storage=storage)
|
||||
|
||||
And need to close connection when shutdown
|
||||
|
||||
.. code-block:: python3
|
||||
|
||||
await storage.close()
|
||||
await storage.wait_closed()
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
host: str = 'localhost',
|
||||
port: int = 28015,
|
||||
db: str = 'aiogram',
|
||||
table: str = 'aiogram',
|
||||
auth_key: typing.Optional[str] = None,
|
||||
user: typing.Optional[str] = None,
|
||||
password: typing.Optional[str] = None,
|
||||
timeout: int = 20,
|
||||
ssl: typing.Optional[dict] = None,
|
||||
loop: typing.Optional[asyncio.AbstractEventLoop] = None):
|
||||
self._host = host
|
||||
self._port = port
|
||||
self._db = db
|
||||
self._table = table
|
||||
self._auth_key = auth_key
|
||||
self._user = user
|
||||
self._password = password
|
||||
self._timeout = timeout
|
||||
self._ssl = ssl or {}
|
||||
self._loop = loop
|
||||
|
||||
self._conn: typing.Optional[Connection] = None
|
||||
|
||||
async def connect(self) -> Connection:
|
||||
"""
|
||||
Get or create a connection.
|
||||
"""
|
||||
if self._conn is None:
|
||||
self._conn = await r.connect(host=self._host,
|
||||
port=self._port,
|
||||
db=self._db,
|
||||
auth_key=self._auth_key,
|
||||
user=self._user,
|
||||
password=self._password,
|
||||
timeout=self._timeout,
|
||||
ssl=self._ssl,
|
||||
io_loop=self._loop)
|
||||
return self._conn
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
async def connection(self):
|
||||
conn = await self.connect()
|
||||
yield conn
|
||||
|
||||
async def close(self):
|
||||
"""
|
||||
Close a connection.
|
||||
"""
|
||||
self._conn.close()
|
||||
self._conn = None
|
||||
|
||||
async def wait_closed(self):
|
||||
"""
|
||||
Does nothing
|
||||
"""
|
||||
pass
|
||||
|
||||
async def get_state(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Optional[str]:
|
||||
chat, user = map(str, self.check_address(chat=chat, user=user))
|
||||
async with self.connection() as conn:
|
||||
return await r.table(self._table).get(chat)[user]['state'].default(
|
||||
self.resolve_state(default) or None
|
||||
).run(conn)
|
||||
|
||||
async def get_data(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Dict:
|
||||
chat, user = map(str, self.check_address(chat=chat, user=user))
|
||||
async with self.connection() as conn:
|
||||
return await r.table(self._table).get(chat)[user]['data'].default(default or {}).run(conn)
|
||||
|
||||
async def set_state(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
state: typing.Optional[typing.AnyStr] = None):
|
||||
chat, user = map(str, self.check_address(chat=chat, user=user))
|
||||
async with self.connection() as conn:
|
||||
await r.table(self._table).insert(
|
||||
{'id': chat, user: {'state': self.resolve_state(state)}},
|
||||
conflict="update",
|
||||
).run(conn)
|
||||
|
||||
async def set_data(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None):
|
||||
chat, user = map(str, self.check_address(chat=chat, user=user))
|
||||
async with self.connection() as conn:
|
||||
if await r.table(self._table).get(chat).run(conn):
|
||||
await r.table(self._table).get(chat).update({user: {'data': r.literal(data)}}).run(conn)
|
||||
else:
|
||||
await r.table(self._table).insert({'id': chat, user: {'data': data}}).run(conn)
|
||||
|
||||
async def update_data(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None,
|
||||
**kwargs):
|
||||
chat, user = map(str, self.check_address(chat=chat, user=user))
|
||||
async with self.connection() as conn:
|
||||
await r.table(self._table).insert({'id': chat, user: {'data': data}}, conflict="update").run(conn)
|
||||
|
||||
def has_bucket(self):
|
||||
return True
|
||||
|
||||
async def get_bucket(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[dict] = None) -> typing.Dict:
|
||||
chat, user = map(str, self.check_address(chat=chat, user=user))
|
||||
async with self.connection() as conn:
|
||||
return await r.table(self._table).get(chat)[user]['bucket'].default(default or {}).run(conn)
|
||||
|
||||
async def set_bucket(self, *, chat: typing.Union[str, int, None] = None, user: typing.Union[str, int, None] = None,
|
||||
bucket: typing.Dict = None):
|
||||
chat, user = map(str, self.check_address(chat=chat, user=user))
|
||||
async with self.connection() as conn:
|
||||
if await r.table(self._table).get(chat).run(conn):
|
||||
await r.table(self._table).get(chat).update({user: {'bucket': r.literal(bucket)}}).run(conn)
|
||||
else:
|
||||
await r.table(self._table).insert({'id': chat, user: {'bucket': bucket}}).run(conn)
|
||||
|
||||
async def update_bucket(self, *, chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None, bucket: typing.Dict = None,
|
||||
**kwargs):
|
||||
chat, user = map(str, self.check_address(chat=chat, user=user))
|
||||
async with self.connection() as conn:
|
||||
await r.table(self._table).insert({'id': chat, user: {'bucket': bucket}}, conflict="update").run(conn)
|
||||
|
||||
async def get_states_list(self) -> typing.List[typing.Tuple[int, int]]:
|
||||
"""
|
||||
Get list of all stored chat's and user's
|
||||
|
||||
:return: list of tuples where first element is chat id and second is user id
|
||||
"""
|
||||
async with self.connection() as conn:
|
||||
result = []
|
||||
|
||||
items = (await r.table(self._table).run(conn)).items
|
||||
|
||||
for item in items:
|
||||
chat = int(item.pop('id'))
|
||||
for key in item.keys():
|
||||
user = int(key)
|
||||
result.append((chat, user))
|
||||
|
||||
return result
|
||||
|
||||
async def reset_all(self):
|
||||
"""
|
||||
Reset states in DB
|
||||
"""
|
||||
async with self.connection() as conn:
|
||||
await r.table(self._table).delete().run(conn)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,27 @@
|
||||
import asyncio
|
||||
|
||||
from aiogram.dispatcher.middlewares import BaseMiddleware
|
||||
|
||||
|
||||
class EnvironmentMiddleware(BaseMiddleware):
|
||||
def __init__(self, context=None):
|
||||
super(EnvironmentMiddleware, self).__init__()
|
||||
|
||||
if context is None:
|
||||
context = {}
|
||||
self.context = context
|
||||
|
||||
def update_data(self, data):
|
||||
dp = self.manager.dispatcher
|
||||
data.update(
|
||||
bot=dp.bot,
|
||||
dispatcher=dp,
|
||||
loop=dp.loop or asyncio.get_event_loop()
|
||||
)
|
||||
if self.context:
|
||||
data.update(self.context)
|
||||
|
||||
async def trigger(self, action, args):
|
||||
if 'error' not in action and action.startswith('pre_process_'):
|
||||
self.update_data(args[-1])
|
||||
return True
|
||||
@ -0,0 +1,80 @@
|
||||
import copy
|
||||
import weakref
|
||||
|
||||
from aiogram.dispatcher.middlewares import LifetimeControllerMiddleware
|
||||
from aiogram.dispatcher.storage import FSMContext
|
||||
|
||||
|
||||
class FSMMiddleware(LifetimeControllerMiddleware):
|
||||
skip_patterns = ['error', 'update']
|
||||
|
||||
def __init__(self):
|
||||
super(FSMMiddleware, self).__init__()
|
||||
self._proxies = weakref.WeakKeyDictionary()
|
||||
|
||||
async def pre_process(self, obj, data, *args):
|
||||
proxy = await FSMSStorageProxy.create(self.manager.dispatcher.current_state())
|
||||
data['state_data'] = proxy
|
||||
|
||||
async def post_process(self, obj, data, *args):
|
||||
proxy = data.get('state_data', None)
|
||||
if isinstance(proxy, FSMSStorageProxy):
|
||||
await proxy.save()
|
||||
|
||||
|
||||
class FSMSStorageProxy(dict):
|
||||
def __init__(self, fsm_context: FSMContext):
|
||||
super(FSMSStorageProxy, self).__init__()
|
||||
self.fsm_context = fsm_context
|
||||
self._copy = {}
|
||||
self._data = {}
|
||||
self._state = None
|
||||
self._is_dirty = False
|
||||
|
||||
@classmethod
|
||||
async def create(cls, fsm_context: FSMContext):
|
||||
"""
|
||||
:param fsm_context:
|
||||
:return:
|
||||
"""
|
||||
proxy = cls(fsm_context)
|
||||
await proxy.load()
|
||||
return proxy
|
||||
|
||||
async def load(self):
|
||||
self.clear()
|
||||
self._state = await self.fsm_context.get_state()
|
||||
self.update(await self.fsm_context.get_data())
|
||||
self._copy = copy.deepcopy(self)
|
||||
self._is_dirty = False
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self._state
|
||||
|
||||
@state.setter
|
||||
def state(self, value):
|
||||
self._state = value
|
||||
self._is_dirty = True
|
||||
|
||||
@state.deleter
|
||||
def state(self):
|
||||
self._state = None
|
||||
self._is_dirty = True
|
||||
|
||||
async def save(self, force=False):
|
||||
if self._copy != self or force:
|
||||
await self.fsm_context.set_data(data=self)
|
||||
if self._is_dirty or force:
|
||||
await self.fsm_context.set_state(self.state)
|
||||
self._is_dirty = False
|
||||
self._copy = copy.deepcopy(self)
|
||||
|
||||
def __str__(self):
|
||||
s = super(FSMSStorageProxy, self).__str__()
|
||||
readable_state = f"'{self.state}'" if self.state else "''"
|
||||
return f"<{self.__class__.__name__}(state={readable_state}, data={s})>"
|
||||
|
||||
def clear(self):
|
||||
del self.state
|
||||
return super(FSMSStorageProxy, self).clear()
|
||||
@ -0,0 +1,154 @@
|
||||
import gettext
|
||||
import os
|
||||
from contextvars import ContextVar
|
||||
from typing import Any, Dict, Tuple, Optional
|
||||
|
||||
from babel import Locale
|
||||
from babel.support import LazyProxy
|
||||
|
||||
from ... import types
|
||||
from ...dispatcher.middlewares import BaseMiddleware
|
||||
|
||||
|
||||
class I18nMiddleware(BaseMiddleware):
|
||||
"""
|
||||
I18n middleware based on gettext util
|
||||
|
||||
>>> dp = Dispatcher(bot)
|
||||
>>> i18n = I18nMiddleware(DOMAIN, LOCALES_DIR)
|
||||
>>> dp.middleware.setup(i18n)
|
||||
and then
|
||||
>>> _ = i18n.gettext
|
||||
or
|
||||
>>> _ = i18n = I18nMiddleware(DOMAIN_NAME, LOCALES_DIR)
|
||||
"""
|
||||
|
||||
ctx_locale = ContextVar('ctx_user_locale', default=None)
|
||||
|
||||
def __init__(self, domain, path=None, default='en'):
|
||||
"""
|
||||
:param domain: domain
|
||||
:param path: path where located all *.mo files
|
||||
:param default: default locale name
|
||||
"""
|
||||
super(I18nMiddleware, self).__init__()
|
||||
|
||||
if path is None:
|
||||
path = os.path.join(os.getcwd(), 'locales')
|
||||
|
||||
self.domain = domain
|
||||
self.path = path
|
||||
self.default = default
|
||||
|
||||
self.locales = self.find_locales()
|
||||
|
||||
def find_locales(self) -> Dict[str, gettext.GNUTranslations]:
|
||||
"""
|
||||
Load all compiled locales from path
|
||||
|
||||
:return: dict with locales
|
||||
"""
|
||||
translations = {}
|
||||
|
||||
for name in os.listdir(self.path):
|
||||
if not os.path.isdir(os.path.join(self.path, name)):
|
||||
continue
|
||||
mo_path = os.path.join(self.path, name, 'LC_MESSAGES', self.domain + '.mo')
|
||||
|
||||
if os.path.exists(mo_path):
|
||||
with open(mo_path, 'rb') as fp:
|
||||
translations[name] = gettext.GNUTranslations(fp)
|
||||
elif os.path.exists(mo_path[:-2] + 'po'):
|
||||
raise RuntimeError(f"Found locale '{name}' but this language is not compiled!")
|
||||
|
||||
return translations
|
||||
|
||||
def reload(self):
|
||||
"""
|
||||
Hot reload locales
|
||||
"""
|
||||
self.locales = self.find_locales()
|
||||
|
||||
@property
|
||||
def available_locales(self) -> Tuple[str]:
|
||||
"""
|
||||
list of loaded locales
|
||||
|
||||
:return:
|
||||
"""
|
||||
return tuple(self.locales.keys())
|
||||
|
||||
def __call__(self, singular, plural=None, n=1, locale=None) -> str:
|
||||
return self.gettext(singular, plural, n, locale)
|
||||
|
||||
def gettext(self, singular, plural=None, n=1, locale=None) -> str:
|
||||
"""
|
||||
Get text
|
||||
|
||||
:param singular:
|
||||
:param plural:
|
||||
:param n:
|
||||
:param locale:
|
||||
:return:
|
||||
"""
|
||||
if locale is None:
|
||||
locale = self.ctx_locale.get()
|
||||
|
||||
if locale not in self.locales:
|
||||
if n == 1:
|
||||
return singular
|
||||
return plural
|
||||
|
||||
translator = self.locales[locale]
|
||||
|
||||
if plural is None:
|
||||
return translator.gettext(singular)
|
||||
return translator.ngettext(singular, plural, n)
|
||||
|
||||
def lazy_gettext(self, singular, plural=None, n=1, locale=None, enable_cache=False) -> LazyProxy:
|
||||
"""
|
||||
Lazy get text
|
||||
|
||||
:param singular:
|
||||
:param plural:
|
||||
:param n:
|
||||
:param locale:
|
||||
:param enable_cache:
|
||||
:return:
|
||||
"""
|
||||
return LazyProxy(self.gettext, singular, plural, n, locale, enable_cache=enable_cache)
|
||||
|
||||
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
||||
async def get_user_locale(self, action: str, args: Tuple[Any]) -> Optional[str]:
|
||||
"""
|
||||
User locale getter
|
||||
You can override the method if you want to use different way of
|
||||
getting user language.
|
||||
|
||||
:param action: event name
|
||||
:param args: event arguments
|
||||
:return: locale name or None
|
||||
"""
|
||||
user: Optional[types.User] = types.User.get_current()
|
||||
locale: Optional[Locale] = user.locale if user else None
|
||||
|
||||
if locale and locale.language in self.locales:
|
||||
*_, data = args
|
||||
language = data['locale'] = locale.language
|
||||
return language
|
||||
return self.default
|
||||
|
||||
async def trigger(self, action, args):
|
||||
"""
|
||||
Event trigger
|
||||
|
||||
:param action: event name
|
||||
:param args: event arguments
|
||||
:return:
|
||||
"""
|
||||
if 'update' not in action \
|
||||
and 'error' not in action \
|
||||
and action.startswith('pre_process'):
|
||||
locale = await self.get_user_locale(action, args)
|
||||
self.ctx_locale.set(locale)
|
||||
return True
|
||||
@ -0,0 +1,461 @@
|
||||
import time
|
||||
|
||||
import logging
|
||||
|
||||
from aiogram import types
|
||||
from aiogram.dispatcher.middlewares import BaseMiddleware
|
||||
|
||||
HANDLED_STR = ['Unhandled', 'Handled']
|
||||
|
||||
|
||||
class LoggingMiddleware(BaseMiddleware):
|
||||
def __init__(self, logger=__name__):
|
||||
if not isinstance(logger, logging.Logger):
|
||||
logger = logging.getLogger(logger)
|
||||
|
||||
self.logger = logger
|
||||
|
||||
super(LoggingMiddleware, self).__init__()
|
||||
|
||||
def check_timeout(self, obj):
|
||||
start = obj.conf.get('_start', None)
|
||||
if start:
|
||||
del obj.conf['_start']
|
||||
return round((time.time() - start) * 1000)
|
||||
return -1
|
||||
|
||||
async def on_pre_process_update(self, update: types.Update, data: dict):
|
||||
update.conf['_start'] = time.time()
|
||||
self.logger.debug(f"Received update [ID:{update.update_id}]")
|
||||
|
||||
async def on_post_process_update(self, update: types.Update, result, data: dict):
|
||||
timeout = self.check_timeout(update)
|
||||
if timeout > 0:
|
||||
self.logger.info(f"Process update [ID:{update.update_id}]: [success] (in {timeout} ms)")
|
||||
|
||||
async def on_pre_process_message(self, message: types.Message, data: dict):
|
||||
self.logger.info(f"Received message [ID:{message.message_id}] in chat [{message.chat.type}:{message.chat.id}]")
|
||||
|
||||
async def on_post_process_message(self, message: types.Message, results, data: dict):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} "
|
||||
f"message [ID:{message.message_id}] in chat [{message.chat.type}:{message.chat.id}]")
|
||||
|
||||
async def on_pre_process_edited_message(self, edited_message, data: dict):
|
||||
self.logger.info(f"Received edited message [ID:{edited_message.message_id}] "
|
||||
f"in chat [{edited_message.chat.type}:{edited_message.chat.id}]")
|
||||
|
||||
async def on_post_process_edited_message(self, edited_message, results, data: dict):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} "
|
||||
f"edited message [ID:{edited_message.message_id}] "
|
||||
f"in chat [{edited_message.chat.type}:{edited_message.chat.id}]")
|
||||
|
||||
async def on_pre_process_channel_post(self, channel_post: types.Message, data: dict):
|
||||
self.logger.info(f"Received channel post [ID:{channel_post.message_id}] "
|
||||
f"in channel [ID:{channel_post.chat.id}]")
|
||||
|
||||
async def on_post_process_channel_post(self, channel_post: types.Message, results, data: dict):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} "
|
||||
f"channel post [ID:{channel_post.message_id}] "
|
||||
f"in chat [{channel_post.chat.type}:{channel_post.chat.id}]")
|
||||
|
||||
async def on_pre_process_edited_channel_post(self, edited_channel_post: types.Message, data: dict):
|
||||
self.logger.info(f"Received edited channel post [ID:{edited_channel_post.message_id}] "
|
||||
f"in channel [ID:{edited_channel_post.chat.id}]")
|
||||
|
||||
async def on_post_process_edited_channel_post(self, edited_channel_post: types.Message, results, data: dict):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} "
|
||||
f"edited channel post [ID:{edited_channel_post.message_id}] "
|
||||
f"in channel [ID:{edited_channel_post.chat.id}]")
|
||||
|
||||
async def on_pre_process_inline_query(self, inline_query: types.InlineQuery, data: dict):
|
||||
self.logger.info(f"Received inline query [ID:{inline_query.id}] "
|
||||
f"from user [ID:{inline_query.from_user.id}]")
|
||||
|
||||
async def on_post_process_inline_query(self, inline_query: types.InlineQuery, results, data: dict):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} "
|
||||
f"inline query [ID:{inline_query.id}] "
|
||||
f"from user [ID:{inline_query.from_user.id}]")
|
||||
|
||||
async def on_pre_process_chosen_inline_result(self, chosen_inline_result: types.ChosenInlineResult, data: dict):
|
||||
self.logger.info(f"Received chosen inline result [Inline msg ID:{chosen_inline_result.inline_message_id}] "
|
||||
f"from user [ID:{chosen_inline_result.from_user.id}] "
|
||||
f"result [ID:{chosen_inline_result.result_id}]")
|
||||
|
||||
async def on_post_process_chosen_inline_result(self, chosen_inline_result, results, data: dict):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} "
|
||||
f"chosen inline result [Inline msg ID:{chosen_inline_result.inline_message_id}] "
|
||||
f"from user [ID:{chosen_inline_result.from_user.id}] "
|
||||
f"result [ID:{chosen_inline_result.result_id}]")
|
||||
|
||||
async def on_pre_process_callback_query(self, callback_query: types.CallbackQuery, data: dict):
|
||||
if callback_query.message:
|
||||
text = (f"Received callback query [ID:{callback_query.id}] "
|
||||
f"from user [ID:{callback_query.from_user.id}] "
|
||||
f"for message [ID:{callback_query.message.message_id}] "
|
||||
f"in chat [{callback_query.message.chat.type}:{callback_query.message.chat.id}]")
|
||||
|
||||
if callback_query.message.from_user:
|
||||
text += f" originally posted by user [ID:{callback_query.message.from_user.id}]"
|
||||
|
||||
self.logger.info(text)
|
||||
|
||||
else:
|
||||
self.logger.info(f"Received callback query [ID:{callback_query.id}] "
|
||||
f"from user [ID:{callback_query.from_user.id}] "
|
||||
f"for inline message [ID:{callback_query.inline_message_id}] ")
|
||||
|
||||
async def on_post_process_callback_query(self, callback_query, results, data: dict):
|
||||
if callback_query.message:
|
||||
text = (f"{HANDLED_STR[bool(len(results))]} "
|
||||
f"callback query [ID:{callback_query.id}] "
|
||||
f"from user [ID:{callback_query.from_user.id}] "
|
||||
f"for message [ID:{callback_query.message.message_id}] "
|
||||
f"in chat [{callback_query.message.chat.type}:{callback_query.message.chat.id}]")
|
||||
|
||||
if callback_query.message.from_user:
|
||||
text += f" originally posted by user [ID:{callback_query.message.from_user.id}]"
|
||||
|
||||
self.logger.info(text)
|
||||
|
||||
else:
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} "
|
||||
f"callback query [ID:{callback_query.id}] "
|
||||
f"from user [ID:{callback_query.from_user.id}]"
|
||||
f"from inline message [ID:{callback_query.inline_message_id}]")
|
||||
|
||||
async def on_pre_process_shipping_query(self, shipping_query: types.ShippingQuery, data: dict):
|
||||
self.logger.info(f"Received shipping query [ID:{shipping_query.id}] "
|
||||
f"from user [ID:{shipping_query.from_user.id}]")
|
||||
|
||||
async def on_post_process_shipping_query(self, shipping_query, results, data: dict):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} "
|
||||
f"shipping query [ID:{shipping_query.id}] "
|
||||
f"from user [ID:{shipping_query.from_user.id}]")
|
||||
|
||||
async def on_pre_process_pre_checkout_query(self, pre_checkout_query: types.PreCheckoutQuery, data: dict):
|
||||
self.logger.info(f"Received pre-checkout query [ID:{pre_checkout_query.id}] "
|
||||
f"from user [ID:{pre_checkout_query.from_user.id}]")
|
||||
|
||||
async def on_post_process_pre_checkout_query(self, pre_checkout_query, results, data: dict):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} "
|
||||
f"pre-checkout query [ID:{pre_checkout_query.id}] "
|
||||
f"from user [ID:{pre_checkout_query.from_user.id}]")
|
||||
|
||||
async def on_pre_process_error(self, update, error, data: dict):
|
||||
timeout = self.check_timeout(update)
|
||||
if timeout > 0:
|
||||
self.logger.info(f"Process update [ID:{update.update_id}]: [failed] (in {timeout} ms)")
|
||||
|
||||
async def on_pre_process_poll(self, poll, data):
|
||||
self.logger.info(f"Received poll [ID:{poll.id}]")
|
||||
|
||||
async def on_post_process_poll(self, poll, results, data):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} poll [ID:{poll.id}]")
|
||||
|
||||
async def on_pre_process_poll_answer(self, poll_answer, data):
|
||||
self.logger.info(f"Received poll answer [ID:{poll_answer.poll_id}] "
|
||||
f"from user [ID:{poll_answer.user.id}]")
|
||||
|
||||
async def on_post_process_poll_answer(self, poll_answer, results, data):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} poll answer [ID:{poll_answer.poll_id}] "
|
||||
f"from user [ID:{poll_answer.user.id}]")
|
||||
|
||||
async def on_pre_process_my_chat_member(self, my_chat_member_update, data):
|
||||
self.logger.info(f"Received chat member update "
|
||||
f"for user [ID:{my_chat_member_update.from_user.id}]. "
|
||||
f"Old state: {my_chat_member_update.old_chat_member.to_python()} "
|
||||
f"New state: {my_chat_member_update.new_chat_member.to_python()} ")
|
||||
|
||||
async def on_post_process_my_chat_member(self, my_chat_member_update, results, data):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} my_chat_member "
|
||||
f"for user [ID:{my_chat_member_update.from_user.id}]")
|
||||
|
||||
async def on_pre_process_chat_member(self, chat_member_update, data):
|
||||
self.logger.info(f"Received chat member update "
|
||||
f"for user [ID:{chat_member_update.from_user.id}]. "
|
||||
f"Old state: {chat_member_update.old_chat_member.to_python()} "
|
||||
f"New state: {chat_member_update.new_chat_member.to_python()} ")
|
||||
|
||||
async def on_post_process_chat_member(self, chat_member_update, results, data):
|
||||
self.logger.debug(f"{HANDLED_STR[bool(len(results))]} chat_member "
|
||||
f"for user [ID:{chat_member_update.from_user.id}]")
|
||||
|
||||
|
||||
class LoggingFilter(logging.Filter):
|
||||
"""
|
||||
Extend LogRecord by data from Telegram Update object.
|
||||
|
||||
Can be used in logging config:
|
||||
.. code-block: python3
|
||||
|
||||
'filters': {
|
||||
'telegram': {
|
||||
'()': LoggingFilter,
|
||||
'include_content': True,
|
||||
}
|
||||
},
|
||||
...
|
||||
'handlers': {
|
||||
'graypy': {
|
||||
'()': GELFRabbitHandler,
|
||||
'url': 'amqp://localhost:5672/',
|
||||
'routing_key': '#',
|
||||
'localname': 'testapp',
|
||||
'filters': ['telegram']
|
||||
},
|
||||
},
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name='', prefix='tg', include_content=False):
|
||||
"""
|
||||
:param name:
|
||||
:param prefix: prefix for all records
|
||||
:param include_content: pass into record all data from Update object
|
||||
"""
|
||||
super(LoggingFilter, self).__init__(name=name)
|
||||
|
||||
self.prefix = prefix
|
||||
self.include_content = include_content
|
||||
|
||||
def filter(self, record: logging.LogRecord):
|
||||
"""
|
||||
Extend LogRecord by data from Telegram Update object.
|
||||
|
||||
:param record:
|
||||
:return:
|
||||
"""
|
||||
update = types.Update.get_current(True)
|
||||
if update:
|
||||
for key, value in self.make_prefix(self.prefix, self.process_update(update)):
|
||||
setattr(record, key, value)
|
||||
|
||||
return True
|
||||
|
||||
def process_update(self, update: types.Update):
|
||||
"""
|
||||
Parse Update object
|
||||
|
||||
:param update:
|
||||
:return:
|
||||
"""
|
||||
yield 'update_id', update.update_id
|
||||
|
||||
if update.message:
|
||||
yield 'update_type', 'message'
|
||||
yield from self.process_message(update.message)
|
||||
if update.edited_message:
|
||||
yield 'update_type', 'edited_message'
|
||||
yield from self.process_message(update.edited_message)
|
||||
if update.channel_post:
|
||||
yield 'update_type', 'channel_post'
|
||||
yield from self.process_message(update.channel_post)
|
||||
if update.edited_channel_post:
|
||||
yield 'update_type', 'edited_channel_post'
|
||||
yield from self.process_message(update.edited_channel_post)
|
||||
if update.inline_query:
|
||||
yield 'update_type', 'inline_query'
|
||||
yield from self.process_inline_query(update.inline_query)
|
||||
if update.chosen_inline_result:
|
||||
yield 'update_type', 'chosen_inline_result'
|
||||
yield from self.process_chosen_inline_result(update.chosen_inline_result)
|
||||
if update.callback_query:
|
||||
yield 'update_type', 'callback_query'
|
||||
yield from self.process_callback_query(update.callback_query)
|
||||
if update.shipping_query:
|
||||
yield 'update_type', 'shipping_query'
|
||||
yield from self.process_shipping_query(update.shipping_query)
|
||||
if update.pre_checkout_query:
|
||||
yield 'update_type', 'pre_checkout_query'
|
||||
yield from self.process_pre_checkout_query(update.pre_checkout_query)
|
||||
|
||||
def make_prefix(self, prefix, iterable):
|
||||
"""
|
||||
Add prefix to the label
|
||||
|
||||
:param prefix:
|
||||
:param iterable:
|
||||
:return:
|
||||
"""
|
||||
if not prefix:
|
||||
yield from iterable
|
||||
|
||||
for key, value in iterable:
|
||||
yield f"{prefix}_{key}", value
|
||||
|
||||
def process_user(self, user: types.User):
|
||||
"""
|
||||
Generate user data
|
||||
|
||||
:param user:
|
||||
:return:
|
||||
"""
|
||||
if not user:
|
||||
return
|
||||
|
||||
yield 'user_id', user.id
|
||||
if self.include_content:
|
||||
yield 'user_full_name', user.full_name
|
||||
if user.username:
|
||||
yield 'user_name', f"@{user.username}"
|
||||
|
||||
def process_chat(self, chat: types.Chat):
|
||||
"""
|
||||
Generate chat data
|
||||
|
||||
:param chat:
|
||||
:return:
|
||||
"""
|
||||
if not chat:
|
||||
return
|
||||
|
||||
yield 'chat_id', chat.id
|
||||
yield 'chat_type', chat.type
|
||||
if self.include_content:
|
||||
yield 'chat_title', chat.full_name
|
||||
if chat.username:
|
||||
yield 'chat_name', f"@{chat.username}"
|
||||
|
||||
def process_message(self, message: types.Message):
|
||||
yield 'message_content_type', message.content_type
|
||||
yield from self.process_user(message.from_user)
|
||||
yield from self.process_chat(message.chat)
|
||||
|
||||
if not self.include_content:
|
||||
return
|
||||
|
||||
if message.reply_to_message:
|
||||
yield from self.make_prefix('reply_to', self.process_message(message.reply_to_message))
|
||||
if message.forward_from:
|
||||
yield from self.make_prefix('forward_from', self.process_user(message.forward_from))
|
||||
if message.forward_from_chat:
|
||||
yield from self.make_prefix('forward_from_chat', self.process_chat(message.forward_from_chat))
|
||||
if message.forward_from_message_id:
|
||||
yield 'message_forward_from_message_id', message.forward_from_message_id
|
||||
if message.forward_date:
|
||||
yield 'message_forward_date', message.forward_date
|
||||
if message.edit_date:
|
||||
yield 'message_edit_date', message.edit_date
|
||||
if message.media_group_id:
|
||||
yield 'message_media_group_id', message.media_group_id
|
||||
if message.author_signature:
|
||||
yield 'message_author_signature', message.author_signature
|
||||
|
||||
if message.text:
|
||||
yield 'text', message.text or message.caption
|
||||
yield 'html_text', message.html_text
|
||||
elif message.audio:
|
||||
yield 'audio', message.audio.file_id
|
||||
elif message.animation:
|
||||
yield 'animation', message.animation.file_id
|
||||
elif message.document:
|
||||
yield 'document', message.document.file_id
|
||||
elif message.game:
|
||||
yield 'game', message.game.title
|
||||
elif message.photo:
|
||||
yield 'photo', message.photo[-1].file_id
|
||||
elif message.sticker:
|
||||
yield 'sticker', message.sticker.file_id
|
||||
elif message.video:
|
||||
yield 'video', message.video.file_id
|
||||
elif message.video_note:
|
||||
yield 'video_note', message.video_note.file_id
|
||||
elif message.voice:
|
||||
yield 'voice', message.voice.file_id
|
||||
elif message.contact:
|
||||
yield 'contact_full_name', message.contact.full_name
|
||||
yield 'contact_phone_number', message.contact.phone_number
|
||||
elif message.venue:
|
||||
yield 'venue_address', message.venue.address
|
||||
yield 'location_latitude', message.venue.location.latitude
|
||||
yield 'location_longitude', message.venue.location.longitude
|
||||
elif message.location:
|
||||
yield 'location_latitude', message.location.latitude
|
||||
yield 'location_longitude', message.location.longitude
|
||||
elif message.new_chat_members:
|
||||
yield 'new_chat_members', [user.id for user in message.new_chat_members]
|
||||
elif message.left_chat_member:
|
||||
yield 'left_chat_member', [user.id for user in message.new_chat_members]
|
||||
elif message.invoice:
|
||||
yield 'invoice_title', message.invoice.title
|
||||
yield 'invoice_description', message.invoice.description
|
||||
yield 'invoice_start_parameter', message.invoice.start_parameter
|
||||
yield 'invoice_currency', message.invoice.currency
|
||||
yield 'invoice_total_amount', message.invoice.total_amount
|
||||
elif message.successful_payment:
|
||||
yield 'successful_payment_currency', message.successful_payment.currency
|
||||
yield 'successful_payment_total_amount', message.successful_payment.total_amount
|
||||
yield 'successful_payment_invoice_payload', message.successful_payment.invoice_payload
|
||||
yield 'successful_payment_shipping_option_id', message.successful_payment.shipping_option_id
|
||||
yield 'successful_payment_telegram_payment_charge_id', message.successful_payment.telegram_payment_charge_id
|
||||
yield 'successful_payment_provider_payment_charge_id', message.successful_payment.provider_payment_charge_id
|
||||
elif message.connected_website:
|
||||
yield 'connected_website', message.connected_website
|
||||
elif message.migrate_from_chat_id:
|
||||
yield 'migrate_from_chat_id', message.migrate_from_chat_id
|
||||
elif message.migrate_to_chat_id:
|
||||
yield 'migrate_to_chat_id', message.migrate_to_chat_id
|
||||
elif message.pinned_message:
|
||||
yield from self.make_prefix('pinned_message', message.pinned_message)
|
||||
elif message.new_chat_title:
|
||||
yield 'new_chat_title', message.new_chat_title
|
||||
elif message.new_chat_photo:
|
||||
yield 'new_chat_photo', message.new_chat_photo[-1].file_id
|
||||
# elif message.delete_chat_photo:
|
||||
# yield 'delete_chat_photo', message.delete_chat_photo
|
||||
# elif message.group_chat_created:
|
||||
# yield 'group_chat_created', message.group_chat_created
|
||||
# elif message.passport_data:
|
||||
# yield 'passport_data', message.passport_data
|
||||
|
||||
def process_inline_query(self, inline_query: types.InlineQuery):
|
||||
yield 'inline_query_id', inline_query.id
|
||||
yield from self.process_user(inline_query.from_user)
|
||||
|
||||
if self.include_content:
|
||||
yield 'inline_query_text', inline_query.query
|
||||
if inline_query.location:
|
||||
yield 'location_latitude', inline_query.location.latitude
|
||||
yield 'location_longitude', inline_query.location.longitude
|
||||
if inline_query.offset:
|
||||
yield 'inline_query_offset', inline_query.offset
|
||||
|
||||
def process_chosen_inline_result(self, chosen_inline_result: types.ChosenInlineResult):
|
||||
yield 'chosen_inline_result_id', chosen_inline_result.result_id
|
||||
yield from self.process_user(chosen_inline_result.from_user)
|
||||
|
||||
if self.include_content:
|
||||
yield 'inline_query_text', chosen_inline_result.query
|
||||
if chosen_inline_result.location:
|
||||
yield 'location_latitude', chosen_inline_result.location.latitude
|
||||
yield 'location_longitude', chosen_inline_result.location.longitude
|
||||
|
||||
def process_callback_query(self, callback_query: types.CallbackQuery):
|
||||
yield from self.process_user(callback_query.from_user)
|
||||
yield 'callback_query_data', callback_query.data
|
||||
|
||||
if callback_query.message:
|
||||
yield from self.make_prefix('callback_query_message', self.process_message(callback_query.message))
|
||||
if callback_query.inline_message_id:
|
||||
yield 'callback_query_inline_message_id', callback_query.inline_message_id
|
||||
if callback_query.chat_instance:
|
||||
yield 'callback_query_chat_instance', callback_query.chat_instance
|
||||
if callback_query.game_short_name:
|
||||
yield 'callback_query_game_short_name', callback_query.game_short_name
|
||||
|
||||
def process_shipping_query(self, shipping_query: types.ShippingQuery):
|
||||
yield 'shipping_query_id', shipping_query.id
|
||||
yield from self.process_user(shipping_query.from_user)
|
||||
|
||||
if self.include_content:
|
||||
yield 'shipping_query_invoice_payload', shipping_query.invoice_payload
|
||||
|
||||
def process_pre_checkout_query(self, pre_checkout_query: types.PreCheckoutQuery):
|
||||
yield 'pre_checkout_query_id', pre_checkout_query.id
|
||||
yield from self.process_user(pre_checkout_query.from_user)
|
||||
|
||||
if self.include_content:
|
||||
yield 'pre_checkout_query_currency', pre_checkout_query.currency
|
||||
yield 'pre_checkout_query_total_amount', pre_checkout_query.total_amount
|
||||
yield 'pre_checkout_query_invoice_payload', pre_checkout_query.invoice_payload
|
||||
yield 'pre_checkout_query_shipping_option_id', pre_checkout_query.shipping_option_id
|
||||
@ -0,0 +1,17 @@
|
||||
from . import filters
|
||||
from . import handler
|
||||
from . import middlewares
|
||||
from . import storage
|
||||
from . import webhook
|
||||
from .dispatcher import Dispatcher, FSMContext, DEFAULT_RATE_LIMIT
|
||||
|
||||
__all__ = (
|
||||
'DEFAULT_RATE_LIMIT',
|
||||
'Dispatcher',
|
||||
'FSMContext',
|
||||
'filters',
|
||||
'handler',
|
||||
'middlewares',
|
||||
'storage',
|
||||
'webhook'
|
||||
)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,39 @@
|
||||
from .builtin import Command, CommandHelp, CommandPrivacy, CommandSettings, CommandStart, ContentTypeFilter, \
|
||||
ExceptionsFilter, HashTag, Regexp, RegexpCommandsFilter, StateFilter, \
|
||||
Text, IDFilter, AdminFilter, IsReplyFilter, IsSenderContact, ForwardedMessageFilter, \
|
||||
ChatTypeFilter, MediaGroupFilter
|
||||
from .factory import FiltersFactory
|
||||
from .filters import AbstractFilter, BoundFilter, Filter, FilterNotPassed, FilterRecord, execute_filter, \
|
||||
check_filters, get_filter_spec, get_filters_spec
|
||||
|
||||
__all__ = (
|
||||
'Command',
|
||||
'CommandHelp',
|
||||
'CommandPrivacy',
|
||||
'CommandSettings',
|
||||
'CommandStart',
|
||||
'ContentTypeFilter',
|
||||
'ExceptionsFilter',
|
||||
'HashTag',
|
||||
'Regexp',
|
||||
'RegexpCommandsFilter',
|
||||
'StateFilter',
|
||||
'Text',
|
||||
'IDFilter',
|
||||
'AdminFilter',
|
||||
'IsReplyFilter',
|
||||
'IsSenderContact',
|
||||
'ForwardedMessageFilter',
|
||||
'ChatTypeFilter',
|
||||
'MediaGroupFilter',
|
||||
'FiltersFactory',
|
||||
'AbstractFilter',
|
||||
'BoundFilter',
|
||||
'Filter',
|
||||
'FilterNotPassed',
|
||||
'FilterRecord',
|
||||
'execute_filter',
|
||||
'check_filters',
|
||||
'get_filter_spec',
|
||||
'get_filters_spec',
|
||||
)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,758 @@
|
||||
import inspect
|
||||
import re
|
||||
import typing
|
||||
import warnings
|
||||
from contextvars import ContextVar
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Dict, Iterable, List, Optional, Union
|
||||
|
||||
from babel.support import LazyProxy
|
||||
|
||||
from aiogram import types
|
||||
from aiogram.dispatcher.filters.filters import BoundFilter, Filter
|
||||
from aiogram.types import CallbackQuery, ChatType, InlineQuery, Message, Poll, ChatMemberUpdated
|
||||
|
||||
ChatIDArgumentType = typing.Union[typing.Iterable[typing.Union[int, str]], str, int]
|
||||
|
||||
|
||||
def extract_chat_ids(chat_id: ChatIDArgumentType) -> typing.Set[int]:
|
||||
# since "str" is also an "Iterable", we have to check for it first
|
||||
if isinstance(chat_id, str):
|
||||
return {int(chat_id), }
|
||||
if isinstance(chat_id, Iterable):
|
||||
return {int(item) for (item) in chat_id}
|
||||
# the last possible type is a single "int"
|
||||
return {chat_id, }
|
||||
|
||||
|
||||
class Command(Filter):
|
||||
"""
|
||||
You can handle commands by using this filter.
|
||||
|
||||
If filter is successful processed the :obj:`Command.CommandObj` will be passed to the handler arguments.
|
||||
|
||||
By default this filter is registered for messages and edited messages handlers.
|
||||
"""
|
||||
|
||||
def __init__(self, commands: Union[Iterable, str],
|
||||
prefixes: Union[Iterable, str] = '/',
|
||||
ignore_case: bool = True,
|
||||
ignore_mention: bool = False,
|
||||
ignore_caption: bool = True):
|
||||
"""
|
||||
Filter can be initialized from filters factory or by simply creating instance of this class.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@dp.message_handler(commands=['myCommand'])
|
||||
@dp.message_handler(Command(['myCommand']))
|
||||
@dp.message_handler(commands=['myCommand'], commands_prefix='!/')
|
||||
|
||||
:param commands: Command or list of commands always without leading slashes (prefix)
|
||||
:param prefixes: Allowed commands prefix. By default is slash.
|
||||
If you change the default behavior pass the list of prefixes to this argument.
|
||||
:param ignore_case: Ignore case of the command
|
||||
:param ignore_mention: Ignore mention in command
|
||||
(By default this filter pass only the commands addressed to current bot)
|
||||
:param ignore_caption: Ignore caption from message (in message types like photo, video, audio, etc)
|
||||
By default is True. If you want check commands in captions, you also should set required content_types.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@dp.message_handler(commands=['myCommand'], commands_ignore_caption=False, content_types=ContentType.ANY)
|
||||
@dp.message_handler(Command(['myCommand'], ignore_caption=False), content_types=[ContentType.TEXT, ContentType.DOCUMENT])
|
||||
"""
|
||||
if isinstance(commands, str):
|
||||
commands = (commands,)
|
||||
|
||||
self.commands = list(map(str.lower, commands)) if ignore_case else commands
|
||||
self.prefixes = prefixes
|
||||
self.ignore_case = ignore_case
|
||||
self.ignore_mention = ignore_mention
|
||||
self.ignore_caption = ignore_caption
|
||||
|
||||
@classmethod
|
||||
def validate(cls, full_config: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Validator for filters factory
|
||||
|
||||
From filters factory this filter can be registered with arguments:
|
||||
|
||||
- ``command``
|
||||
- ``commands_prefix`` (will be passed as ``prefixes``)
|
||||
- ``commands_ignore_mention`` (will be passed as ``ignore_mention``)
|
||||
- ``commands_ignore_caption`` (will be passed as ``ignore_caption``)
|
||||
|
||||
:param full_config:
|
||||
:return: config or empty dict
|
||||
"""
|
||||
config = {}
|
||||
if 'commands' in full_config:
|
||||
config['commands'] = full_config.pop('commands')
|
||||
if config and 'commands_prefix' in full_config:
|
||||
config['prefixes'] = full_config.pop('commands_prefix')
|
||||
if config and 'commands_ignore_mention' in full_config:
|
||||
config['ignore_mention'] = full_config.pop('commands_ignore_mention')
|
||||
if config and 'commands_ignore_caption' in full_config:
|
||||
config['ignore_caption'] = full_config.pop('commands_ignore_caption')
|
||||
return config
|
||||
|
||||
async def check(self, message: types.Message):
|
||||
return await self.check_command(message, self.commands, self.prefixes, self.ignore_case, self.ignore_mention, self.ignore_caption)
|
||||
|
||||
@classmethod
|
||||
async def check_command(cls, message: types.Message, commands, prefixes, ignore_case=True, ignore_mention=False, ignore_caption=True):
|
||||
text = message.text or (message.caption if not ignore_caption else None)
|
||||
if not text:
|
||||
return False
|
||||
|
||||
full_command, *args_list = text.split(maxsplit=1)
|
||||
args = args_list[0] if args_list else None
|
||||
prefix, (command, _, mention) = full_command[0], full_command[1:].partition('@')
|
||||
|
||||
if not ignore_mention and mention and (await message.bot.me).username.lower() != mention.lower():
|
||||
return False
|
||||
if prefix not in prefixes:
|
||||
return False
|
||||
if (command.lower() if ignore_case else command) not in commands:
|
||||
return False
|
||||
|
||||
return {'command': cls.CommandObj(command=command, prefix=prefix, mention=mention, args=args)}
|
||||
|
||||
@dataclass
|
||||
class CommandObj:
|
||||
"""
|
||||
Instance of this object is always has command and it prefix.
|
||||
|
||||
Can be passed as keyword argument ``command`` to the handler
|
||||
"""
|
||||
|
||||
"""Command prefix"""
|
||||
prefix: str = '/'
|
||||
"""Command without prefix and mention"""
|
||||
command: str = ''
|
||||
"""Mention (if available)"""
|
||||
mention: str = None
|
||||
"""Command argument"""
|
||||
args: str = field(repr=False, default=None)
|
||||
|
||||
@property
|
||||
def mentioned(self) -> bool:
|
||||
"""
|
||||
This command has mention?
|
||||
|
||||
:return:
|
||||
"""
|
||||
return bool(self.mention)
|
||||
|
||||
@property
|
||||
def text(self) -> str:
|
||||
"""
|
||||
Generate original text from object
|
||||
|
||||
:return:
|
||||
"""
|
||||
line = self.prefix + self.command
|
||||
if self.mentioned:
|
||||
line += '@' + self.mention
|
||||
if self.args:
|
||||
line += ' ' + self.args
|
||||
return line
|
||||
|
||||
|
||||
class CommandStart(Command):
|
||||
"""
|
||||
This filter based on :obj:`Command` filter but can handle only ``/start`` command.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
deep_link: typing.Optional[typing.Union[str, typing.Pattern[str]]] = None,
|
||||
encoded: bool = False):
|
||||
"""
|
||||
Also this filter can handle `deep-linking <https://core.telegram.org/bots#deep-linking>`_ arguments.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@dp.message_handler(CommandStart(re.compile(r'ref-([\\d]+)')))
|
||||
|
||||
:param deep_link: string or compiled regular expression (by ``re.compile(...)``).
|
||||
:param encoded: set True if you're waiting for encoded payload (default - False).
|
||||
"""
|
||||
super().__init__(['start'])
|
||||
self.deep_link = deep_link
|
||||
self.encoded = encoded
|
||||
|
||||
async def check(self, message: types.Message):
|
||||
"""
|
||||
If deep-linking is passed to the filter result of the matching will be passed as ``deep_link`` to the handler
|
||||
|
||||
:param message:
|
||||
:return:
|
||||
"""
|
||||
from ...utils.deep_linking import decode_payload
|
||||
check = await super().check(message)
|
||||
|
||||
if check and self.deep_link is not None:
|
||||
payload = decode_payload(message.get_args()) if self.encoded else message.get_args()
|
||||
|
||||
if not isinstance(self.deep_link, typing.Pattern):
|
||||
return False if payload != self.deep_link else {'deep_link': payload}
|
||||
|
||||
match = self.deep_link.match(payload)
|
||||
if match:
|
||||
return {'deep_link': match}
|
||||
return False
|
||||
|
||||
return check
|
||||
|
||||
|
||||
class CommandHelp(Command):
|
||||
"""
|
||||
This filter based on :obj:`Command` filter but can handle only ``/help`` command.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(['help'])
|
||||
|
||||
|
||||
class CommandSettings(Command):
|
||||
"""
|
||||
This filter based on :obj:`Command` filter but can handle only ``/settings`` command.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(['settings'])
|
||||
|
||||
|
||||
class CommandPrivacy(Command):
|
||||
"""
|
||||
This filter based on :obj:`Command` filter but can handle only ``/privacy`` command.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(['privacy'])
|
||||
|
||||
|
||||
class Text(Filter):
|
||||
"""
|
||||
Simple text filter
|
||||
"""
|
||||
|
||||
_default_params = (
|
||||
('text', 'equals'),
|
||||
('text_contains', 'contains'),
|
||||
('text_startswith', 'startswith'),
|
||||
('text_endswith', 'endswith'),
|
||||
)
|
||||
|
||||
def __init__(self,
|
||||
equals: Optional[Union[str, LazyProxy, Iterable[Union[str, LazyProxy]]]] = None,
|
||||
contains: Optional[Union[str, LazyProxy, Iterable[Union[str, LazyProxy]]]] = None,
|
||||
startswith: Optional[Union[str, LazyProxy, Iterable[Union[str, LazyProxy]]]] = None,
|
||||
endswith: Optional[Union[str, LazyProxy, Iterable[Union[str, LazyProxy]]]] = None,
|
||||
ignore_case=False):
|
||||
"""
|
||||
Check text for one of pattern. Only one mode can be used in one filter.
|
||||
In every pattern, a single string is treated as a list with 1 element.
|
||||
|
||||
:param equals: True if object's text in the list
|
||||
:param contains: True if object's text contains all strings from the list
|
||||
:param startswith: True if object's text starts with any of strings from the list
|
||||
:param endswith: True if object's text ends with any of strings from the list
|
||||
:param ignore_case: case insensitive
|
||||
"""
|
||||
# Only one mode can be used. check it.
|
||||
check = sum(map(lambda s: s is not None, (equals, contains, startswith, endswith)))
|
||||
if check > 1:
|
||||
args = "' and '".join([arg[0] for arg in [('equals', equals),
|
||||
('contains', contains),
|
||||
('startswith', startswith),
|
||||
('endswith', endswith)
|
||||
] if arg[1] is not None])
|
||||
raise ValueError(f"Arguments '{args}' cannot be used together.")
|
||||
elif check == 0:
|
||||
raise ValueError(f"No one mode is specified!")
|
||||
|
||||
equals, contains, endswith, startswith = map(lambda e: [e] if isinstance(e, str) or isinstance(e, LazyProxy)
|
||||
else e,
|
||||
(equals, contains, endswith, startswith))
|
||||
self.equals = equals
|
||||
self.contains = contains
|
||||
self.endswith = endswith
|
||||
self.startswith = startswith
|
||||
self.ignore_case = ignore_case
|
||||
|
||||
@classmethod
|
||||
def validate(cls, full_config: Dict[str, Any]):
|
||||
for param, key in cls._default_params:
|
||||
if param in full_config:
|
||||
return {key: full_config.pop(param)}
|
||||
|
||||
async def check(self, obj: Union[Message, CallbackQuery, InlineQuery, Poll]):
|
||||
if isinstance(obj, Message):
|
||||
text = obj.text or obj.caption or ''
|
||||
if not text and obj.poll:
|
||||
text = obj.poll.question
|
||||
elif isinstance(obj, CallbackQuery):
|
||||
text = obj.data
|
||||
elif isinstance(obj, InlineQuery):
|
||||
text = obj.query
|
||||
elif isinstance(obj, Poll):
|
||||
text = obj.question
|
||||
else:
|
||||
return False
|
||||
|
||||
if self.ignore_case:
|
||||
text = text.lower()
|
||||
_pre_process_func = lambda s: str(s).lower()
|
||||
else:
|
||||
_pre_process_func = str
|
||||
|
||||
# now check
|
||||
if self.equals is not None:
|
||||
equals = list(map(_pre_process_func, self.equals))
|
||||
return text in equals
|
||||
|
||||
if self.contains is not None:
|
||||
contains = list(map(_pre_process_func, self.contains))
|
||||
return all(map(text.__contains__, contains))
|
||||
|
||||
if self.startswith is not None:
|
||||
startswith = list(map(_pre_process_func, self.startswith))
|
||||
return any(map(text.startswith, startswith))
|
||||
|
||||
if self.endswith is not None:
|
||||
endswith = list(map(_pre_process_func, self.endswith))
|
||||
return any(map(text.endswith, endswith))
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class HashTag(Filter):
|
||||
"""
|
||||
Filter for hashtag's and cashtag's
|
||||
"""
|
||||
|
||||
# TODO: allow to use regexp
|
||||
|
||||
def __init__(self, hashtags=None, cashtags=None):
|
||||
if not hashtags and not cashtags:
|
||||
raise ValueError('No one hashtag or cashtag is specified!')
|
||||
|
||||
if hashtags is None:
|
||||
hashtags = []
|
||||
elif isinstance(hashtags, str):
|
||||
hashtags = [hashtags]
|
||||
|
||||
if cashtags is None:
|
||||
cashtags = []
|
||||
elif isinstance(cashtags, str):
|
||||
cashtags = [cashtags.upper()]
|
||||
else:
|
||||
cashtags = list(map(str.upper, cashtags))
|
||||
|
||||
self.hashtags = hashtags
|
||||
self.cashtags = cashtags
|
||||
|
||||
@classmethod
|
||||
def validate(cls, full_config: Dict[str, Any]):
|
||||
config = {}
|
||||
if 'hashtags' in full_config:
|
||||
config['hashtags'] = full_config.pop('hashtags')
|
||||
if 'cashtags' in full_config:
|
||||
config['cashtags'] = full_config.pop('cashtags')
|
||||
return config
|
||||
|
||||
async def check(self, message: types.Message):
|
||||
if message.caption:
|
||||
text = message.caption
|
||||
entities = message.caption_entities
|
||||
elif message.text:
|
||||
text = message.text
|
||||
entities = message.entities
|
||||
else:
|
||||
return False
|
||||
|
||||
hashtags, cashtags = self._get_tags(text, entities)
|
||||
if self.hashtags and set(hashtags) & set(self.hashtags) \
|
||||
or self.cashtags and set(cashtags) & set(self.cashtags):
|
||||
return {'hashtags': hashtags, 'cashtags': cashtags}
|
||||
|
||||
def _get_tags(self, text, entities):
|
||||
hashtags = []
|
||||
cashtags = []
|
||||
|
||||
for entity in entities:
|
||||
if entity.type == types.MessageEntityType.HASHTAG:
|
||||
value = entity.get_text(text).lstrip('#')
|
||||
hashtags.append(value)
|
||||
|
||||
elif entity.type == types.MessageEntityType.CASHTAG:
|
||||
value = entity.get_text(text).lstrip('$')
|
||||
cashtags.append(value)
|
||||
|
||||
return hashtags, cashtags
|
||||
|
||||
|
||||
class Regexp(Filter):
|
||||
"""
|
||||
Regexp filter for messages and callback query
|
||||
"""
|
||||
|
||||
def __init__(self, regexp):
|
||||
if not isinstance(regexp, typing.Pattern):
|
||||
regexp = re.compile(regexp, flags=re.IGNORECASE | re.MULTILINE)
|
||||
self.regexp = regexp
|
||||
|
||||
@classmethod
|
||||
def validate(cls, full_config: Dict[str, Any]):
|
||||
if 'regexp' in full_config:
|
||||
return {'regexp': full_config.pop('regexp')}
|
||||
|
||||
async def check(self, obj: Union[Message, CallbackQuery, InlineQuery, Poll]):
|
||||
if isinstance(obj, Message):
|
||||
content = obj.text or obj.caption or ''
|
||||
if not content and obj.poll:
|
||||
content = obj.poll.question
|
||||
elif isinstance(obj, CallbackQuery) and obj.data:
|
||||
content = obj.data
|
||||
elif isinstance(obj, InlineQuery):
|
||||
content = obj.query
|
||||
elif isinstance(obj, Poll):
|
||||
content = obj.question
|
||||
else:
|
||||
return False
|
||||
|
||||
match = self.regexp.search(content)
|
||||
|
||||
if match:
|
||||
return {'regexp': match}
|
||||
return False
|
||||
|
||||
|
||||
class RegexpCommandsFilter(BoundFilter):
|
||||
"""
|
||||
Check commands by regexp in message
|
||||
"""
|
||||
|
||||
key = 'regexp_commands'
|
||||
|
||||
def __init__(self, regexp_commands):
|
||||
self.regexp_commands = [re.compile(command, flags=re.IGNORECASE | re.MULTILINE) for command in regexp_commands]
|
||||
|
||||
async def check(self, message):
|
||||
if not message.is_command():
|
||||
return False
|
||||
|
||||
command = message.text.split()[0][1:]
|
||||
command, _, mention = command.partition('@')
|
||||
|
||||
if mention and mention != (await message.bot.me).username:
|
||||
return False
|
||||
|
||||
for command in self.regexp_commands:
|
||||
search = command.search(message.text)
|
||||
if search:
|
||||
return {'regexp_command': search}
|
||||
return False
|
||||
|
||||
|
||||
class ContentTypeFilter(BoundFilter):
|
||||
"""
|
||||
Check message content type
|
||||
"""
|
||||
|
||||
key = 'content_types'
|
||||
required = True
|
||||
default = types.ContentTypes.TEXT
|
||||
|
||||
def __init__(self, content_types):
|
||||
if isinstance(content_types, str):
|
||||
content_types = (content_types,)
|
||||
self.content_types = content_types
|
||||
|
||||
async def check(self, message):
|
||||
return types.ContentType.ANY in self.content_types or \
|
||||
message.content_type in self.content_types
|
||||
|
||||
|
||||
class IsSenderContact(BoundFilter):
|
||||
"""
|
||||
Filter check that the contact matches the sender
|
||||
|
||||
`is_sender_contact=True` - contact matches the sender
|
||||
`is_sender_contact=False` - result will be inverted
|
||||
"""
|
||||
key = 'is_sender_contact'
|
||||
|
||||
def __init__(self, is_sender_contact: bool):
|
||||
self.is_sender_contact = is_sender_contact
|
||||
|
||||
async def check(self, message: types.Message) -> bool:
|
||||
if not message.contact:
|
||||
return False
|
||||
is_sender_contact = message.contact.user_id == message.from_user.id
|
||||
if self.is_sender_contact:
|
||||
return is_sender_contact
|
||||
else:
|
||||
return not is_sender_contact
|
||||
|
||||
|
||||
class StateFilter(BoundFilter):
|
||||
"""
|
||||
Check user state
|
||||
"""
|
||||
key = 'state'
|
||||
required = True
|
||||
|
||||
ctx_state = ContextVar('user_state')
|
||||
|
||||
def __init__(self, dispatcher, state):
|
||||
from aiogram.dispatcher.filters.state import State, StatesGroup
|
||||
|
||||
self.dispatcher = dispatcher
|
||||
states = []
|
||||
if not isinstance(state, (list, set, tuple, frozenset)) or state is None:
|
||||
state = [state, ]
|
||||
for item in state:
|
||||
if isinstance(item, State):
|
||||
states.append(item.state)
|
||||
elif inspect.isclass(item) and issubclass(item, StatesGroup):
|
||||
states.extend(item.all_states_names)
|
||||
else:
|
||||
states.append(item)
|
||||
self.states = states
|
||||
|
||||
def get_target(self, obj):
|
||||
if isinstance(obj, CallbackQuery):
|
||||
return getattr(getattr(getattr(obj, 'message', None),'chat', None), 'id', None), getattr(getattr(obj, 'from_user', None), 'id', None)
|
||||
return getattr(getattr(obj, 'chat', None), 'id', None), getattr(getattr(obj, 'from_user', None), 'id', None)
|
||||
|
||||
async def check(self, obj):
|
||||
if '*' in self.states:
|
||||
return {'state': self.dispatcher.current_state()}
|
||||
|
||||
try:
|
||||
state = self.ctx_state.get()
|
||||
except LookupError:
|
||||
chat, user = self.get_target(obj)
|
||||
|
||||
if chat or user:
|
||||
state = await self.dispatcher.storage.get_state(chat=chat, user=user)
|
||||
self.ctx_state.set(state)
|
||||
if state in self.states:
|
||||
return {'state': self.dispatcher.current_state(), 'raw_state': state}
|
||||
|
||||
else:
|
||||
if state in self.states:
|
||||
return {'state': self.dispatcher.current_state(), 'raw_state': state}
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class ExceptionsFilter(BoundFilter):
|
||||
"""
|
||||
Filter for exceptions
|
||||
"""
|
||||
|
||||
key = 'exception'
|
||||
|
||||
def __init__(self, exception):
|
||||
self.exception = exception
|
||||
|
||||
async def check(self, update, exception):
|
||||
try:
|
||||
raise exception
|
||||
except self.exception:
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
class IDFilter(Filter):
|
||||
def __init__(self,
|
||||
user_id: Optional[ChatIDArgumentType] = None,
|
||||
chat_id: Optional[ChatIDArgumentType] = None,
|
||||
):
|
||||
"""
|
||||
:param user_id:
|
||||
:param chat_id:
|
||||
"""
|
||||
if user_id is None and chat_id is None:
|
||||
raise ValueError("Both user_id and chat_id can't be None")
|
||||
|
||||
self.user_id: Optional[typing.Set[int]] = None
|
||||
self.chat_id: Optional[typing.Set[int]] = None
|
||||
|
||||
if user_id:
|
||||
self.user_id = extract_chat_ids(user_id)
|
||||
|
||||
if chat_id:
|
||||
self.chat_id = extract_chat_ids(chat_id)
|
||||
|
||||
@classmethod
|
||||
def validate(cls, full_config: typing.Dict[str, typing.Any]) -> typing.Optional[typing.Dict[str, typing.Any]]:
|
||||
result = {}
|
||||
if 'user_id' in full_config:
|
||||
result['user_id'] = full_config.pop('user_id')
|
||||
|
||||
if 'chat_id' in full_config:
|
||||
result['chat_id'] = full_config.pop('chat_id')
|
||||
|
||||
return result
|
||||
|
||||
async def check(self, obj: Union[Message, CallbackQuery, InlineQuery, ChatMemberUpdated]):
|
||||
if isinstance(obj, Message):
|
||||
user_id = None
|
||||
if obj.from_user is not None:
|
||||
user_id = obj.from_user.id
|
||||
chat_id = obj.chat.id
|
||||
elif isinstance(obj, CallbackQuery):
|
||||
user_id = obj.from_user.id
|
||||
chat_id = None
|
||||
if obj.message is not None:
|
||||
# if the button was sent with message
|
||||
chat_id = obj.message.chat.id
|
||||
elif isinstance(obj, InlineQuery):
|
||||
user_id = obj.from_user.id
|
||||
chat_id = None
|
||||
elif isinstance(obj, ChatMemberUpdated):
|
||||
user_id = obj.from_user.id
|
||||
chat_id = obj.chat.id
|
||||
else:
|
||||
return False
|
||||
|
||||
if self.user_id and self.chat_id:
|
||||
return user_id in self.user_id and chat_id in self.chat_id
|
||||
if self.user_id:
|
||||
return user_id in self.user_id
|
||||
if self.chat_id:
|
||||
return chat_id in self.chat_id
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class AdminFilter(Filter):
|
||||
"""
|
||||
Checks if user is admin in a chat.
|
||||
If is_chat_admin is not set, the filter will check in the current chat (correct only for messages).
|
||||
is_chat_admin is required for InlineQuery.
|
||||
"""
|
||||
|
||||
def __init__(self, is_chat_admin: Optional[Union[ChatIDArgumentType, bool]] = None):
|
||||
self._check_current = False
|
||||
self._chat_ids = None
|
||||
|
||||
if is_chat_admin is False:
|
||||
raise ValueError("is_chat_admin cannot be False")
|
||||
|
||||
if not is_chat_admin:
|
||||
self._check_current = True
|
||||
return
|
||||
|
||||
if isinstance(is_chat_admin, bool):
|
||||
self._check_current = is_chat_admin
|
||||
self._chat_ids = extract_chat_ids(is_chat_admin)
|
||||
|
||||
@classmethod
|
||||
def validate(cls, full_config: typing.Dict[str, typing.Any]) -> typing.Optional[typing.Dict[str, typing.Any]]:
|
||||
result = {}
|
||||
|
||||
if "is_chat_admin" in full_config:
|
||||
result["is_chat_admin"] = full_config.pop("is_chat_admin")
|
||||
|
||||
return result
|
||||
|
||||
async def check(self, obj: Union[Message, CallbackQuery, InlineQuery, ChatMemberUpdated]) -> bool:
|
||||
user_id = obj.from_user.id
|
||||
|
||||
if self._check_current:
|
||||
if isinstance(obj, Message):
|
||||
chat = obj.chat
|
||||
elif isinstance(obj, CallbackQuery) and obj.message:
|
||||
chat = obj.message.chat
|
||||
elif isinstance(obj, ChatMemberUpdated):
|
||||
chat = obj.chat
|
||||
else:
|
||||
return False
|
||||
if chat.type == ChatType.PRIVATE: # there is no admin in private chats
|
||||
return False
|
||||
chat_ids = [chat.id]
|
||||
else:
|
||||
chat_ids = self._chat_ids
|
||||
|
||||
admins = [member.user.id for chat_id in chat_ids for member in await obj.bot.get_chat_administrators(chat_id)]
|
||||
|
||||
return user_id in admins
|
||||
|
||||
|
||||
class IsReplyFilter(BoundFilter):
|
||||
"""
|
||||
Check if message is replied and send reply message to handler
|
||||
"""
|
||||
key = 'is_reply'
|
||||
|
||||
def __init__(self, is_reply):
|
||||
self.is_reply = is_reply
|
||||
|
||||
async def check(self, msg: Message):
|
||||
if msg.reply_to_message and self.is_reply:
|
||||
return {'reply': msg.reply_to_message}
|
||||
elif not msg.reply_to_message and not self.is_reply:
|
||||
return True
|
||||
|
||||
|
||||
class ForwardedMessageFilter(BoundFilter):
|
||||
key = 'is_forwarded'
|
||||
|
||||
def __init__(self, is_forwarded: bool):
|
||||
self.is_forwarded = is_forwarded
|
||||
|
||||
async def check(self, message: Message):
|
||||
return bool(getattr(message, "forward_date")) is self.is_forwarded
|
||||
|
||||
|
||||
class ChatTypeFilter(BoundFilter):
|
||||
key = 'chat_type'
|
||||
|
||||
def __init__(self, chat_type: typing.Container[ChatType]):
|
||||
if isinstance(chat_type, str):
|
||||
chat_type = {chat_type}
|
||||
|
||||
self.chat_type: typing.Set[str] = set(chat_type)
|
||||
|
||||
async def check(self, obj: Union[Message, CallbackQuery, ChatMemberUpdated]):
|
||||
if isinstance(obj, Message):
|
||||
obj = obj.chat
|
||||
elif isinstance(obj, CallbackQuery):
|
||||
obj = obj.message.chat
|
||||
elif isinstance(obj, ChatMemberUpdated):
|
||||
obj = obj.chat
|
||||
else:
|
||||
warnings.warn("ChatTypeFilter doesn't support %s as input", type(obj))
|
||||
return False
|
||||
|
||||
return obj.type in self.chat_type
|
||||
|
||||
|
||||
class MediaGroupFilter(BoundFilter):
|
||||
"""
|
||||
Check if message is part of a media group.
|
||||
|
||||
`is_media_group=True` - the message is part of a media group
|
||||
`is_media_group=False` - the message is NOT part of a media group
|
||||
"""
|
||||
|
||||
key = "is_media_group"
|
||||
|
||||
def __init__(self, is_media_group: bool):
|
||||
self.is_media_group = is_media_group
|
||||
|
||||
async def check(self, message: types.Message) -> bool:
|
||||
return bool(getattr(message, "media_group_id")) is self.is_media_group
|
||||
@ -0,0 +1,73 @@
|
||||
import typing
|
||||
|
||||
from .filters import AbstractFilter, FilterRecord
|
||||
from ..handler import Handler
|
||||
|
||||
|
||||
class FiltersFactory:
|
||||
"""
|
||||
Filters factory
|
||||
"""
|
||||
|
||||
def __init__(self, dispatcher):
|
||||
self._dispatcher = dispatcher
|
||||
self._registered: typing.List[FilterRecord] = []
|
||||
|
||||
def bind(self, callback: typing.Union[typing.Callable, AbstractFilter],
|
||||
validator: typing.Optional[typing.Callable] = None,
|
||||
event_handlers: typing.Optional[typing.List[Handler]] = None,
|
||||
exclude_event_handlers: typing.Optional[typing.Iterable[Handler]] = None):
|
||||
"""
|
||||
Register filter
|
||||
|
||||
:param callback: callable or subclass of :obj:`AbstractFilter`
|
||||
:param validator: custom validator.
|
||||
:param event_handlers: list of instances of :obj:`Handler`
|
||||
:param exclude_event_handlers: list of excluded event handlers (:obj:`Handler`)
|
||||
"""
|
||||
record = FilterRecord(callback, validator, event_handlers, exclude_event_handlers)
|
||||
self._registered.append(record)
|
||||
|
||||
def unbind(self, callback: typing.Union[typing.Callable, AbstractFilter]):
|
||||
"""
|
||||
Unregister filter
|
||||
|
||||
:param callback: callable of subclass of :obj:`AbstractFilter`
|
||||
"""
|
||||
for record in self._registered:
|
||||
if record.callback == callback:
|
||||
self._registered.remove(record)
|
||||
|
||||
def resolve(self, event_handler, *custom_filters, **full_config
|
||||
) -> typing.List[typing.Union[typing.Callable, AbstractFilter]]:
|
||||
"""
|
||||
Resolve filters to filters-set
|
||||
|
||||
:param event_handler:
|
||||
:param custom_filters:
|
||||
:param full_config:
|
||||
:return:
|
||||
"""
|
||||
filters_set = []
|
||||
filters_set.extend(self._resolve_registered(event_handler,
|
||||
{k: v for k, v in full_config.items() if v is not None}))
|
||||
if custom_filters:
|
||||
filters_set.extend(custom_filters)
|
||||
|
||||
return filters_set
|
||||
|
||||
def _resolve_registered(self, event_handler, full_config) -> typing.Generator:
|
||||
"""
|
||||
Resolve registered filters
|
||||
|
||||
:param event_handler:
|
||||
:param full_config:
|
||||
:return:
|
||||
"""
|
||||
for record in self._registered:
|
||||
filter_ = record.resolve(self._dispatcher, event_handler, full_config)
|
||||
if filter_:
|
||||
yield filter_
|
||||
|
||||
if full_config:
|
||||
raise NameError("Invalid filter name(s): '" + "', ".join(full_config.keys()) + "'")
|
||||
@ -0,0 +1,289 @@
|
||||
import abc
|
||||
import inspect
|
||||
import typing
|
||||
|
||||
from ..handler import Handler, FilterObj
|
||||
|
||||
|
||||
class FilterNotPassed(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def wrap_async(func):
|
||||
async def async_wrapper(*args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
|
||||
if inspect.isawaitable(func) \
|
||||
or inspect.iscoroutinefunction(func) \
|
||||
or isinstance(func, AbstractFilter):
|
||||
return func
|
||||
return async_wrapper
|
||||
|
||||
|
||||
def get_filter_spec(dispatcher, filter_: callable):
|
||||
kwargs = {}
|
||||
if not callable(filter_):
|
||||
raise TypeError('Filter must be callable and/or awaitable!')
|
||||
|
||||
spec = inspect.getfullargspec(filter_)
|
||||
if 'dispatcher' in spec:
|
||||
kwargs['dispatcher'] = dispatcher
|
||||
if inspect.isawaitable(filter_) \
|
||||
or inspect.iscoroutinefunction(filter_) \
|
||||
or isinstance(filter_, AbstractFilter):
|
||||
return FilterObj(filter=filter_, kwargs=kwargs, is_async=True)
|
||||
else:
|
||||
return FilterObj(filter=filter_, kwargs=kwargs, is_async=False)
|
||||
|
||||
|
||||
def get_filters_spec(dispatcher, filters: typing.Iterable[callable]):
|
||||
data = []
|
||||
if filters is not None:
|
||||
for i in filters:
|
||||
data.append(get_filter_spec(dispatcher, i))
|
||||
return data
|
||||
|
||||
|
||||
async def execute_filter(filter_: FilterObj, args):
|
||||
"""
|
||||
Helper for executing filter
|
||||
|
||||
:param filter_:
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
if filter_.is_async:
|
||||
return await filter_.filter(*args, **filter_.kwargs)
|
||||
else:
|
||||
return filter_.filter(*args, **filter_.kwargs)
|
||||
|
||||
|
||||
async def check_filters(filters: typing.Iterable[FilterObj], args):
|
||||
"""
|
||||
Check list of filters
|
||||
|
||||
:param filters:
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
data = {}
|
||||
if filters is not None:
|
||||
for filter_ in filters:
|
||||
f = await execute_filter(filter_, args)
|
||||
if not f:
|
||||
raise FilterNotPassed()
|
||||
elif isinstance(f, dict):
|
||||
data.update(f)
|
||||
return data
|
||||
|
||||
|
||||
class FilterRecord:
|
||||
"""
|
||||
Filters record for factory
|
||||
"""
|
||||
|
||||
def __init__(self, callback: typing.Union[typing.Callable, 'AbstractFilter'],
|
||||
validator: typing.Optional[typing.Callable] = None,
|
||||
event_handlers: typing.Optional[typing.Iterable[Handler]] = None,
|
||||
exclude_event_handlers: typing.Optional[typing.Iterable[Handler]] = None):
|
||||
if event_handlers and exclude_event_handlers:
|
||||
raise ValueError("'event_handlers' and 'exclude_event_handlers' arguments cannot be used together.")
|
||||
|
||||
self.callback = callback
|
||||
self.event_handlers = event_handlers
|
||||
self.exclude_event_handlers = exclude_event_handlers
|
||||
|
||||
if validator is not None:
|
||||
if not callable(validator):
|
||||
raise TypeError(f"validator must be callable, not {type(validator)}")
|
||||
self.resolver = validator
|
||||
elif issubclass(callback, AbstractFilter):
|
||||
self.resolver = callback.validate
|
||||
else:
|
||||
raise RuntimeError('validator is required!')
|
||||
|
||||
def resolve(self, dispatcher, event_handler, full_config):
|
||||
if not self._check_event_handler(event_handler):
|
||||
return
|
||||
config = self.resolver(full_config)
|
||||
if config:
|
||||
if 'dispatcher' not in config:
|
||||
spec = inspect.getfullargspec(self.callback)
|
||||
if 'dispatcher' in spec.args:
|
||||
config['dispatcher'] = dispatcher
|
||||
|
||||
for key in config:
|
||||
if key in full_config:
|
||||
full_config.pop(key)
|
||||
|
||||
return self.callback(**config)
|
||||
|
||||
def _check_event_handler(self, event_handler) -> bool:
|
||||
if self.event_handlers:
|
||||
return event_handler in self.event_handlers
|
||||
elif self.exclude_event_handlers:
|
||||
return event_handler not in self.exclude_event_handlers
|
||||
return True
|
||||
|
||||
|
||||
class AbstractFilter(abc.ABC):
|
||||
"""
|
||||
Abstract class for custom filters.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def validate(cls, full_config: typing.Dict[str, typing.Any]) -> typing.Optional[typing.Dict[str, typing.Any]]:
|
||||
"""
|
||||
Validate and parse config.
|
||||
|
||||
This method will be called by the filters factory when you bind this filter.
|
||||
Must be overridden.
|
||||
|
||||
:param full_config: dict with arguments passed to handler registrar
|
||||
:return: Current filter config
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
async def check(self, *args) -> bool:
|
||||
"""
|
||||
Will be called when filters checks.
|
||||
|
||||
This method must be overridden.
|
||||
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
pass
|
||||
|
||||
async def __call__(self, *args) -> bool:
|
||||
return await self.check(*args)
|
||||
|
||||
def __invert__(self):
|
||||
return NotFilter(self)
|
||||
|
||||
def __and__(self, other):
|
||||
if isinstance(self, AndFilter):
|
||||
self.append(other)
|
||||
return self
|
||||
return AndFilter(self, other)
|
||||
|
||||
def __or__(self, other):
|
||||
if isinstance(self, OrFilter):
|
||||
self.append(other)
|
||||
return self
|
||||
return OrFilter(self, other)
|
||||
|
||||
|
||||
class Filter(AbstractFilter):
|
||||
"""
|
||||
You can make subclasses of that class for custom filters.
|
||||
|
||||
Method ``check`` must be overridden
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def validate(cls, full_config: typing.Dict[str, typing.Any]) -> typing.Optional[typing.Dict[str, typing.Any]]:
|
||||
"""
|
||||
Here method ``validate`` is optional.
|
||||
If you need to use filter from filters factory you need to override this method.
|
||||
|
||||
:param full_config: dict with arguments passed to handler registrar
|
||||
:return: Current filter config
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class BoundFilter(Filter):
|
||||
"""
|
||||
To easily create your own filters with one parameter, you can inherit from this filter.
|
||||
|
||||
You need to implement ``__init__`` method with single argument related with key attribute
|
||||
and ``check`` method where you need to implement filter logic.
|
||||
"""
|
||||
|
||||
key = None
|
||||
"""Unique name of the filter argument. You need to override this attribute."""
|
||||
required = False
|
||||
"""If :obj:`True` this filter will be added to the all of the registered handlers"""
|
||||
default = None
|
||||
"""Default value for configure required filters"""
|
||||
|
||||
@classmethod
|
||||
def validate(cls, full_config: typing.Dict[str, typing.Any]) -> typing.Dict[str, typing.Any]:
|
||||
"""
|
||||
If ``cls.key`` is not :obj:`None` and that is in config returns config with that argument.
|
||||
|
||||
:param full_config:
|
||||
:return:
|
||||
"""
|
||||
if cls.key is not None:
|
||||
if cls.key in full_config:
|
||||
return {cls.key: full_config[cls.key]}
|
||||
elif cls.required:
|
||||
return {cls.key: cls.default}
|
||||
|
||||
|
||||
class _LogicFilter(Filter):
|
||||
@classmethod
|
||||
def validate(cls, full_config: typing.Dict[str, typing.Any]):
|
||||
raise ValueError('That filter can\'t be used in filters factory!')
|
||||
|
||||
|
||||
class NotFilter(_LogicFilter):
|
||||
def __init__(self, target):
|
||||
self.target = wrap_async(target)
|
||||
|
||||
async def check(self, *args):
|
||||
return not bool(await self.target(*args))
|
||||
|
||||
|
||||
class AndFilter(_LogicFilter):
|
||||
|
||||
def __init__(self, *targets):
|
||||
self.targets = list(wrap_async(target) for target in targets)
|
||||
|
||||
async def check(self, *args):
|
||||
"""
|
||||
All filters must return a positive result
|
||||
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
data = {}
|
||||
for target in self.targets:
|
||||
result = await target(*args)
|
||||
if not result:
|
||||
return False
|
||||
if isinstance(result, dict):
|
||||
data.update(result)
|
||||
if not data:
|
||||
return True
|
||||
return data
|
||||
|
||||
def append(self, target):
|
||||
self.targets.append(wrap_async(target))
|
||||
|
||||
|
||||
class OrFilter(_LogicFilter):
|
||||
def __init__(self, *targets):
|
||||
self.targets = list(wrap_async(target) for target in targets)
|
||||
|
||||
async def check(self, *args):
|
||||
"""
|
||||
One of filters must return a positive result
|
||||
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
for target in self.targets:
|
||||
result = await target(*args)
|
||||
if result:
|
||||
if isinstance(result, dict):
|
||||
return result
|
||||
return True
|
||||
return False
|
||||
|
||||
def append(self, target):
|
||||
self.targets.append(wrap_async(target))
|
||||
@ -0,0 +1,197 @@
|
||||
import inspect
|
||||
from typing import Optional
|
||||
|
||||
from ..dispatcher import Dispatcher
|
||||
|
||||
|
||||
class State:
|
||||
"""
|
||||
State object
|
||||
"""
|
||||
|
||||
def __init__(self, state: Optional[str] = None, group_name: Optional[str] = None):
|
||||
self._state = state
|
||||
self._group_name = group_name
|
||||
self._group = None
|
||||
|
||||
@property
|
||||
def group(self):
|
||||
if not self._group:
|
||||
raise RuntimeError('This state is not in any group.')
|
||||
return self._group
|
||||
|
||||
def get_root(self):
|
||||
return self.group.get_root()
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
if self._state is None or self._state == '*':
|
||||
return self._state
|
||||
|
||||
if self._group_name is None and self._group:
|
||||
group = self._group.__full_group_name__
|
||||
elif self._group_name:
|
||||
group = self._group_name
|
||||
else:
|
||||
group = '@'
|
||||
|
||||
return f'{group}:{self._state}'
|
||||
|
||||
def set_parent(self, group):
|
||||
if not issubclass(group, StatesGroup):
|
||||
raise ValueError('Group must be subclass of StatesGroup')
|
||||
self._group = group
|
||||
|
||||
def __set_name__(self, owner, name):
|
||||
if self._state is None:
|
||||
self._state = name
|
||||
self.set_parent(owner)
|
||||
|
||||
def __str__(self):
|
||||
return f"<State '{self.state or ''}'>"
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
async def set(self):
|
||||
state = Dispatcher.get_current().current_state()
|
||||
await state.set_state(self.state)
|
||||
|
||||
|
||||
class StatesGroupMeta(type):
|
||||
def __new__(mcs, name, bases, namespace, **kwargs):
|
||||
cls = super(StatesGroupMeta, mcs).__new__(mcs, name, bases, namespace)
|
||||
|
||||
states = []
|
||||
childs = []
|
||||
|
||||
cls._group_name = name
|
||||
|
||||
for name, prop in namespace.items():
|
||||
|
||||
if isinstance(prop, State):
|
||||
states.append(prop)
|
||||
elif inspect.isclass(prop) and issubclass(prop, StatesGroup):
|
||||
childs.append(prop)
|
||||
prop._parent = cls
|
||||
|
||||
cls._parent = None
|
||||
cls._childs = tuple(childs)
|
||||
cls._states = tuple(states)
|
||||
cls._state_names = tuple(state.state for state in states)
|
||||
|
||||
return cls
|
||||
|
||||
@property
|
||||
def __group_name__(cls) -> str:
|
||||
return cls._group_name
|
||||
|
||||
@property
|
||||
def __full_group_name__(cls) -> str:
|
||||
if cls._parent:
|
||||
return '.'.join((cls._parent.__full_group_name__, cls._group_name))
|
||||
return cls._group_name
|
||||
|
||||
@property
|
||||
def states(cls) -> tuple:
|
||||
return cls._states
|
||||
|
||||
@property
|
||||
def childs(cls) -> tuple:
|
||||
return cls._childs
|
||||
|
||||
@property
|
||||
def all_childs(cls):
|
||||
result = cls.childs
|
||||
for child in cls.childs:
|
||||
result += child.childs
|
||||
return result
|
||||
|
||||
@property
|
||||
def all_states(cls):
|
||||
result = cls.states
|
||||
for group in cls.childs:
|
||||
result += group.all_states
|
||||
return result
|
||||
|
||||
@property
|
||||
def all_states_names(cls):
|
||||
return tuple(state.state for state in cls.all_states)
|
||||
|
||||
@property
|
||||
def states_names(cls) -> tuple:
|
||||
return tuple(state.state for state in cls.states)
|
||||
|
||||
def get_root(cls):
|
||||
if cls._parent is None:
|
||||
return cls
|
||||
return cls._parent.get_root()
|
||||
|
||||
def __contains__(cls, item):
|
||||
if isinstance(item, str):
|
||||
return item in cls.all_states_names
|
||||
if isinstance(item, State):
|
||||
return item in cls.all_states
|
||||
if isinstance(item, StatesGroup):
|
||||
return item in cls.all_childs
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
return f"<StatesGroup '{self.__full_group_name__}'>"
|
||||
|
||||
|
||||
class StatesGroup(metaclass=StatesGroupMeta):
|
||||
@classmethod
|
||||
async def next(cls) -> str:
|
||||
state = Dispatcher.get_current().current_state()
|
||||
state_name = await state.get_state()
|
||||
|
||||
try:
|
||||
next_step = cls.states_names.index(state_name) + 1
|
||||
except ValueError:
|
||||
next_step = 0
|
||||
|
||||
try:
|
||||
next_state_name = cls.states[next_step].state
|
||||
except IndexError:
|
||||
next_state_name = None
|
||||
|
||||
await state.set_state(next_state_name)
|
||||
return next_state_name
|
||||
|
||||
@classmethod
|
||||
async def previous(cls) -> str:
|
||||
state = Dispatcher.get_current().current_state()
|
||||
state_name = await state.get_state()
|
||||
|
||||
try:
|
||||
previous_step = cls.states_names.index(state_name) - 1
|
||||
except ValueError:
|
||||
previous_step = 0
|
||||
|
||||
if previous_step < 0:
|
||||
previous_state_name = None
|
||||
else:
|
||||
previous_state_name = cls.states[previous_step].state
|
||||
|
||||
await state.set_state(previous_state_name)
|
||||
return previous_state_name
|
||||
|
||||
@classmethod
|
||||
async def first(cls) -> str:
|
||||
state = Dispatcher.get_current().current_state()
|
||||
first_step_name = cls.states_names[0]
|
||||
|
||||
await state.set_state(first_step_name)
|
||||
return first_step_name
|
||||
|
||||
@classmethod
|
||||
async def last(cls) -> str:
|
||||
state = Dispatcher.get_current().current_state()
|
||||
last_step_name = cls.states_names[-1]
|
||||
|
||||
await state.set_state(last_step_name)
|
||||
return last_step_name
|
||||
|
||||
|
||||
default_state = State()
|
||||
any_state = State(state='*')
|
||||
@ -0,0 +1,138 @@
|
||||
import inspect
|
||||
from contextvars import ContextVar
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, Iterable, List
|
||||
|
||||
ctx_data = ContextVar('ctx_handler_data')
|
||||
current_handler = ContextVar('current_handler')
|
||||
|
||||
|
||||
@dataclass
|
||||
class FilterObj:
|
||||
filter: callable
|
||||
kwargs: dict
|
||||
is_async: bool
|
||||
|
||||
|
||||
class SkipHandler(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class CancelHandler(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def _get_spec(func: callable):
|
||||
while hasattr(func, '__wrapped__'): # Try to resolve decorated callbacks
|
||||
func = func.__wrapped__
|
||||
return inspect.getfullargspec(func)
|
||||
|
||||
|
||||
def _check_spec(spec: inspect.FullArgSpec, kwargs: dict):
|
||||
if spec.varkw:
|
||||
return kwargs
|
||||
|
||||
return {k: v for k, v in kwargs.items() if k in set(spec.args + spec.kwonlyargs)}
|
||||
|
||||
|
||||
class Handler:
|
||||
def __init__(self, dispatcher, once=True, middleware_key=None):
|
||||
self.dispatcher = dispatcher
|
||||
self.once = once
|
||||
|
||||
self.handlers: List[Handler.HandlerObj] = []
|
||||
self.middleware_key = middleware_key
|
||||
|
||||
def register(self, handler, filters=None, index=None):
|
||||
"""
|
||||
Register callback
|
||||
|
||||
Filters can be awaitable or not.
|
||||
|
||||
:param handler: coroutine
|
||||
:param filters: list of filters
|
||||
:param index: you can reorder handlers
|
||||
"""
|
||||
from .filters import get_filters_spec
|
||||
|
||||
spec = _get_spec(handler)
|
||||
|
||||
if filters and not isinstance(filters, (list, tuple, set)):
|
||||
filters = [filters]
|
||||
filters = get_filters_spec(self.dispatcher, filters)
|
||||
|
||||
record = Handler.HandlerObj(handler=handler, spec=spec, filters=filters)
|
||||
if index is None:
|
||||
self.handlers.append(record)
|
||||
else:
|
||||
self.handlers.insert(index, record)
|
||||
|
||||
def unregister(self, handler):
|
||||
"""
|
||||
Remove handler
|
||||
|
||||
:param handler: callback
|
||||
:return:
|
||||
"""
|
||||
for handler_obj in self.handlers:
|
||||
registered = handler_obj.handler
|
||||
if handler is registered:
|
||||
self.handlers.remove(handler_obj)
|
||||
return True
|
||||
raise ValueError('This handler is not registered!')
|
||||
|
||||
async def notify(self, *args):
|
||||
"""
|
||||
Notify handlers
|
||||
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
from .filters import check_filters, FilterNotPassed
|
||||
|
||||
results = []
|
||||
|
||||
data = {}
|
||||
ctx_data.set(data)
|
||||
|
||||
if self.middleware_key:
|
||||
try:
|
||||
await self.dispatcher.middleware.trigger(f"pre_process_{self.middleware_key}", args + (data,))
|
||||
except CancelHandler: # Allow to cancel current event
|
||||
return results
|
||||
|
||||
try:
|
||||
for handler_obj in self.handlers:
|
||||
try:
|
||||
data.update(await check_filters(handler_obj.filters, args))
|
||||
except FilterNotPassed:
|
||||
continue
|
||||
else:
|
||||
ctx_token = current_handler.set(handler_obj.handler)
|
||||
try:
|
||||
if self.middleware_key:
|
||||
await self.dispatcher.middleware.trigger(f"process_{self.middleware_key}", args + (data,))
|
||||
partial_data = _check_spec(handler_obj.spec, data)
|
||||
response = await handler_obj.handler(*args, **partial_data)
|
||||
if response is not None:
|
||||
results.append(response)
|
||||
if self.once:
|
||||
break
|
||||
except SkipHandler:
|
||||
continue
|
||||
except CancelHandler:
|
||||
break
|
||||
finally:
|
||||
current_handler.reset(ctx_token)
|
||||
finally:
|
||||
if self.middleware_key:
|
||||
await self.dispatcher.middleware.trigger(f"post_process_{self.middleware_key}",
|
||||
args + (results, data,))
|
||||
|
||||
return results
|
||||
|
||||
@dataclass
|
||||
class HandlerObj:
|
||||
handler: callable
|
||||
spec: inspect.FullArgSpec
|
||||
filters: Optional[Iterable[FilterObj]] = None
|
||||
@ -0,0 +1,131 @@
|
||||
import logging
|
||||
import typing
|
||||
|
||||
log = logging.getLogger('aiogram.Middleware')
|
||||
|
||||
|
||||
class MiddlewareManager:
|
||||
"""
|
||||
Middlewares manager. Works only with dispatcher.
|
||||
"""
|
||||
|
||||
def __init__(self, dispatcher):
|
||||
"""
|
||||
Init
|
||||
|
||||
:param dispatcher: instance of Dispatcher
|
||||
"""
|
||||
self.dispatcher = dispatcher
|
||||
self.bot = dispatcher.bot
|
||||
self.storage = dispatcher.storage
|
||||
self.applications = []
|
||||
|
||||
@property
|
||||
def loop(self):
|
||||
return self.dispatcher.loop
|
||||
|
||||
def setup(self, middleware):
|
||||
"""
|
||||
Setup middleware
|
||||
|
||||
:param middleware:
|
||||
:return:
|
||||
"""
|
||||
if not isinstance(middleware, BaseMiddleware):
|
||||
raise TypeError(f"`middleware` must be an instance of BaseMiddleware, not {type(middleware)}")
|
||||
if middleware.is_configured():
|
||||
raise ValueError('That middleware is already used!')
|
||||
|
||||
self.applications.append(middleware)
|
||||
middleware.setup(self)
|
||||
log.debug(f"Loaded middleware '{middleware.__class__.__name__}'")
|
||||
return middleware
|
||||
|
||||
async def trigger(self, action: str, args: typing.Iterable):
|
||||
"""
|
||||
Call action to middlewares with args lilt.
|
||||
|
||||
:param action:
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
for app in self.applications:
|
||||
await app.trigger(action, args)
|
||||
|
||||
|
||||
class BaseMiddleware:
|
||||
"""
|
||||
Base class for middleware.
|
||||
|
||||
All methods on the middle always must be coroutines and name starts with "on_" like "on_process_message".
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._configured = False
|
||||
self._manager = None
|
||||
|
||||
@property
|
||||
def manager(self) -> MiddlewareManager:
|
||||
"""
|
||||
Instance of MiddlewareManager
|
||||
"""
|
||||
if self._manager is None:
|
||||
raise RuntimeError('Middleware is not configured!')
|
||||
return self._manager
|
||||
|
||||
def setup(self, manager):
|
||||
"""
|
||||
Mark middleware as configured
|
||||
|
||||
:param manager:
|
||||
:return:
|
||||
"""
|
||||
self._manager = manager
|
||||
self._configured = True
|
||||
|
||||
def is_configured(self) -> bool:
|
||||
"""
|
||||
Check middleware is configured
|
||||
|
||||
:return:
|
||||
"""
|
||||
return self._configured
|
||||
|
||||
async def trigger(self, action, args):
|
||||
"""
|
||||
Trigger action.
|
||||
|
||||
:param action:
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
handler_name = f"on_{action}"
|
||||
handler = getattr(self, handler_name, None)
|
||||
if not handler:
|
||||
return None
|
||||
await handler(*args)
|
||||
|
||||
|
||||
class LifetimeControllerMiddleware(BaseMiddleware):
|
||||
# TODO: Rename class
|
||||
|
||||
skip_patterns = None
|
||||
|
||||
async def pre_process(self, obj, data, *args):
|
||||
pass
|
||||
|
||||
async def post_process(self, obj, data, *args):
|
||||
pass
|
||||
|
||||
async def trigger(self, action, args):
|
||||
if self.skip_patterns is not None and any(item in action for item in self.skip_patterns):
|
||||
return False
|
||||
|
||||
obj, *args, data = args
|
||||
if action.startswith('pre_process_'):
|
||||
await self.pre_process(obj, data, *args)
|
||||
elif action.startswith('post_process_'):
|
||||
await self.post_process(obj, data, *args)
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
@ -0,0 +1,506 @@
|
||||
import copy
|
||||
import typing
|
||||
|
||||
from ..utils.deprecated import warn_deprecated as warn
|
||||
from ..utils.exceptions import FSMStorageWarning
|
||||
|
||||
# Leak bucket
|
||||
KEY = 'key'
|
||||
LAST_CALL = 'called_at'
|
||||
RATE_LIMIT = 'rate_limit'
|
||||
RESULT = 'result'
|
||||
EXCEEDED_COUNT = 'exceeded'
|
||||
DELTA = 'delta'
|
||||
THROTTLE_MANAGER = '$throttle_manager'
|
||||
|
||||
|
||||
class BaseStorage:
|
||||
"""
|
||||
You are able to save current user's state
|
||||
and data for all steps in states-storage
|
||||
"""
|
||||
|
||||
async def close(self):
|
||||
"""
|
||||
You have to override this method and use when application shutdowns.
|
||||
Perhaps you would like to save data and etc.
|
||||
|
||||
:return:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def wait_closed(self):
|
||||
"""
|
||||
You have to override this method for all asynchronous storages (e.g., Redis).
|
||||
|
||||
:return:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def check_address(cls, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
) -> (typing.Union[str, int], typing.Union[str, int]):
|
||||
"""
|
||||
In all storage's methods chat or user is always required.
|
||||
If one of them is not provided, you have to set missing value based on the provided one.
|
||||
|
||||
This method performs the check described above.
|
||||
|
||||
:param chat: chat_id
|
||||
:param user: user_id
|
||||
:return:
|
||||
"""
|
||||
if chat is None and user is None:
|
||||
raise ValueError('`user` or `chat` parameter is required but no one is provided!')
|
||||
|
||||
if user is None:
|
||||
user = chat
|
||||
|
||||
elif chat is None:
|
||||
chat = user
|
||||
|
||||
return chat, user
|
||||
|
||||
async def get_state(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Optional[str]:
|
||||
"""
|
||||
Get current state of user in chat. Return `default` if no record is found.
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:param default:
|
||||
:return:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def get_data(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[typing.Dict] = None) -> typing.Dict:
|
||||
"""
|
||||
Get state-data for user in chat. Return `default` if no data is provided in storage.
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:param default:
|
||||
:return:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def set_state(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
state: typing.Optional[typing.AnyStr] = None):
|
||||
"""
|
||||
Set new state for user in chat
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:param state:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def set_data(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None):
|
||||
"""
|
||||
Set data for user in chat
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:param data:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def update_data(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None,
|
||||
**kwargs):
|
||||
"""
|
||||
Update data for user in chat
|
||||
|
||||
You can use data parameter or|and kwargs.
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param data:
|
||||
:param chat:
|
||||
:param user:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def reset_data(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None):
|
||||
"""
|
||||
Reset data for user in chat.
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:return:
|
||||
"""
|
||||
await self.set_data(chat=chat, user=user, data={})
|
||||
|
||||
async def reset_state(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
with_data: typing.Optional[bool] = True):
|
||||
"""
|
||||
Reset state for user in chat.
|
||||
You may desire to use this method when finishing conversations.
|
||||
|
||||
Chat or user is always required. If one of this is not presented,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:param with_data:
|
||||
:return:
|
||||
"""
|
||||
chat, user = self.check_address(chat=chat, user=user)
|
||||
await self.set_state(chat=chat, user=user, state=None)
|
||||
if with_data:
|
||||
await self.set_data(chat=chat, user=user, data={})
|
||||
|
||||
async def finish(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None):
|
||||
"""
|
||||
Finish conversation for user in chat.
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:return:
|
||||
"""
|
||||
await self.reset_state(chat=chat, user=user, with_data=True)
|
||||
|
||||
def has_bucket(self):
|
||||
return False
|
||||
|
||||
async def get_bucket(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[dict] = None) -> typing.Dict:
|
||||
"""
|
||||
Get bucket for user in chat. Return `default` if no data is provided in storage.
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:param default:
|
||||
:return:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def set_bucket(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
bucket: typing.Dict = None):
|
||||
"""
|
||||
Set bucket for user in chat
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:param bucket:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def update_bucket(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
bucket: typing.Dict = None,
|
||||
**kwargs):
|
||||
"""
|
||||
Update bucket for user in chat
|
||||
|
||||
You can use bucket parameter or|and kwargs.
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param bucket:
|
||||
:param chat:
|
||||
:param user:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def reset_bucket(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None):
|
||||
"""
|
||||
Reset bucket dor user in chat.
|
||||
|
||||
Chat or user is always required. If one of them is not provided,
|
||||
you have to set missing value based on the provided one.
|
||||
|
||||
:param chat:
|
||||
:param user:
|
||||
:return:
|
||||
"""
|
||||
await self.set_data(chat=chat, user=user, data={})
|
||||
|
||||
@staticmethod
|
||||
def resolve_state(value):
|
||||
from .filters.state import State
|
||||
|
||||
if value is None:
|
||||
return
|
||||
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
|
||||
if isinstance(value, State):
|
||||
return value.state
|
||||
|
||||
return str(value)
|
||||
|
||||
|
||||
class FSMContext:
|
||||
def __init__(self, storage, chat, user):
|
||||
self.storage: BaseStorage = storage
|
||||
self.chat, self.user = self.storage.check_address(chat=chat, user=user)
|
||||
|
||||
def proxy(self):
|
||||
return FSMContextProxy(self)
|
||||
|
||||
async def get_state(self, default: typing.Optional[str] = None) -> typing.Optional[str]:
|
||||
return await self.storage.get_state(chat=self.chat, user=self.user, default=default)
|
||||
|
||||
async def get_data(self, default: typing.Optional[str] = None) -> typing.Dict:
|
||||
return await self.storage.get_data(chat=self.chat, user=self.user, default=default)
|
||||
|
||||
async def update_data(self, data: typing.Dict = None, **kwargs):
|
||||
await self.storage.update_data(chat=self.chat, user=self.user, data=data, **kwargs)
|
||||
|
||||
async def set_state(self, state: typing.Optional[typing.AnyStr] = None):
|
||||
await self.storage.set_state(chat=self.chat, user=self.user, state=state)
|
||||
|
||||
async def set_data(self, data: typing.Dict = None):
|
||||
await self.storage.set_data(chat=self.chat, user=self.user, data=data)
|
||||
|
||||
async def reset_state(self, with_data: typing.Optional[bool] = True):
|
||||
await self.storage.reset_state(chat=self.chat, user=self.user, with_data=with_data)
|
||||
|
||||
async def reset_data(self):
|
||||
await self.storage.reset_data(chat=self.chat, user=self.user)
|
||||
|
||||
async def finish(self):
|
||||
await self.storage.finish(chat=self.chat, user=self.user)
|
||||
|
||||
|
||||
class FSMContextProxy:
|
||||
def __init__(self, fsm_context: FSMContext):
|
||||
super(FSMContextProxy, self).__init__()
|
||||
self.fsm_context = fsm_context
|
||||
self._copy = {}
|
||||
self._data = {}
|
||||
self._state = None
|
||||
self._is_dirty = False
|
||||
|
||||
self._closed = True
|
||||
|
||||
async def __aenter__(self):
|
||||
await self.load()
|
||||
return self
|
||||
|
||||
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
||||
if exc_type is None:
|
||||
await self.save()
|
||||
self._closed = True
|
||||
|
||||
def _check_closed(self):
|
||||
if self._closed:
|
||||
raise LookupError('Proxy is closed!')
|
||||
|
||||
@classmethod
|
||||
async def create(cls, fsm_context: FSMContext):
|
||||
"""
|
||||
:param fsm_context:
|
||||
:return:
|
||||
"""
|
||||
proxy = cls(fsm_context)
|
||||
await proxy.load()
|
||||
return proxy
|
||||
|
||||
async def load(self):
|
||||
self._closed = False
|
||||
|
||||
self.clear()
|
||||
self._state = await self.fsm_context.get_state()
|
||||
self.update(await self.fsm_context.get_data())
|
||||
self._copy = copy.deepcopy(self._data)
|
||||
self._is_dirty = False
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self._state
|
||||
|
||||
@state.setter
|
||||
def state(self, value):
|
||||
self._check_closed()
|
||||
|
||||
self._state = value
|
||||
self._is_dirty = True
|
||||
|
||||
@state.deleter
|
||||
def state(self):
|
||||
self._check_closed()
|
||||
|
||||
self._state = None
|
||||
self._is_dirty = True
|
||||
|
||||
async def save(self, force=False):
|
||||
self._check_closed()
|
||||
|
||||
if self._copy != self._data or force:
|
||||
await self.fsm_context.set_data(data=self._data)
|
||||
if self._is_dirty or force:
|
||||
await self.fsm_context.set_state(self.state)
|
||||
self._is_dirty = False
|
||||
self._copy = copy.deepcopy(self._data)
|
||||
|
||||
def clear(self):
|
||||
del self.state
|
||||
return self._data.clear()
|
||||
|
||||
def get(self, value, default=None):
|
||||
return self._data.get(value, default)
|
||||
|
||||
def setdefault(self, key, default):
|
||||
self._check_closed()
|
||||
|
||||
return self._data.setdefault(key, default)
|
||||
|
||||
def update(self, data=None, **kwargs):
|
||||
self._check_closed()
|
||||
|
||||
self._data.update(data, **kwargs)
|
||||
|
||||
def pop(self, key, default=None):
|
||||
self._check_closed()
|
||||
|
||||
return self._data.pop(key, default)
|
||||
|
||||
def keys(self):
|
||||
return self._data.keys()
|
||||
|
||||
def values(self):
|
||||
return self._data.values()
|
||||
|
||||
def items(self):
|
||||
return self._data.items()
|
||||
|
||||
def as_dict(self):
|
||||
return copy.deepcopy(self._data)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._data)
|
||||
|
||||
def __iter__(self):
|
||||
return self._data.__iter__()
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self._data[item]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self._check_closed()
|
||||
|
||||
self._data[key] = value
|
||||
|
||||
def __delitem__(self, key):
|
||||
self._check_closed()
|
||||
|
||||
del self._data[key]
|
||||
|
||||
def __contains__(self, item):
|
||||
return item in self._data
|
||||
|
||||
def __str__(self):
|
||||
readable_state = f"'{self.state}'" if self.state else "<default>"
|
||||
result = f"{self.__class__.__name__} state = {readable_state}, data = {self._data}"
|
||||
if self._closed:
|
||||
result += ', closed = True'
|
||||
return result
|
||||
|
||||
|
||||
class DisabledStorage(BaseStorage):
|
||||
"""
|
||||
Empty storage. Use it if you don't want to use Finite-State Machine
|
||||
"""
|
||||
|
||||
async def close(self):
|
||||
pass
|
||||
|
||||
async def wait_closed(self):
|
||||
pass
|
||||
|
||||
async def get_state(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Optional[str]:
|
||||
return None
|
||||
|
||||
async def get_data(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
default: typing.Optional[str] = None) -> typing.Dict:
|
||||
self._warn()
|
||||
return {}
|
||||
|
||||
async def update_data(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None, **kwargs):
|
||||
self._warn()
|
||||
|
||||
async def set_state(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
state: typing.Optional[typing.AnyStr] = None):
|
||||
self._warn()
|
||||
|
||||
async def set_data(self, *,
|
||||
chat: typing.Union[str, int, None] = None,
|
||||
user: typing.Union[str, int, None] = None,
|
||||
data: typing.Dict = None):
|
||||
self._warn()
|
||||
|
||||
@staticmethod
|
||||
def _warn():
|
||||
warn(f"You haven’t set any storage yet so no states and no data will be saved. \n"
|
||||
f"You can connect MemoryStorage for debug purposes or non-essential data.",
|
||||
FSMStorageWarning, 5)
|
||||
2191
IKEA_scrapper/.venv/Lib/site-packages/aiogram/dispatcher/webhook.py
Normal file
2191
IKEA_scrapper/.venv/Lib/site-packages/aiogram/dispatcher/webhook.py
Normal file
File diff suppressed because it is too large
Load Diff
214
IKEA_scrapper/.venv/Lib/site-packages/aiogram/types/__init__.py
Normal file
214
IKEA_scrapper/.venv/Lib/site-packages/aiogram/types/__init__.py
Normal file
@ -0,0 +1,214 @@
|
||||
from . import base
|
||||
from . import fields
|
||||
from .animation import Animation
|
||||
from .audio import Audio
|
||||
from .auth_widget_data import AuthWidgetData
|
||||
from .bot_command import BotCommand
|
||||
from .bot_command_scope import BotCommandScope, BotCommandScopeAllChatAdministrators, \
|
||||
BotCommandScopeAllGroupChats, BotCommandScopeAllPrivateChats, BotCommandScopeChat, \
|
||||
BotCommandScopeChatAdministrators, BotCommandScopeChatMember, \
|
||||
BotCommandScopeDefault, BotCommandScopeType
|
||||
from .callback_game import CallbackGame
|
||||
from .callback_query import CallbackQuery
|
||||
from .chat import Chat, ChatActions, ChatType
|
||||
from .chat_invite_link import ChatInviteLink
|
||||
from .chat_location import ChatLocation
|
||||
from .chat_member import ChatMember, ChatMemberStatus
|
||||
from .chat_member_updated import ChatMemberUpdated
|
||||
from .chat_permissions import ChatPermissions
|
||||
from .chat_photo import ChatPhoto
|
||||
from .chosen_inline_result import ChosenInlineResult
|
||||
from .contact import Contact
|
||||
from .dice import Dice, DiceEmoji
|
||||
from .document import Document
|
||||
from .encrypted_credentials import EncryptedCredentials
|
||||
from .encrypted_passport_element import EncryptedPassportElement
|
||||
from .file import File
|
||||
from .force_reply import ForceReply
|
||||
from .game import Game
|
||||
from .game_high_score import GameHighScore
|
||||
from .inline_keyboard import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from .inline_query import InlineQuery
|
||||
from .inline_query_result import InlineQueryResult, InlineQueryResultArticle, InlineQueryResultAudio, \
|
||||
InlineQueryResultCachedAudio, InlineQueryResultCachedDocument, InlineQueryResultCachedGif, \
|
||||
InlineQueryResultCachedMpeg4Gif, InlineQueryResultCachedPhoto, InlineQueryResultCachedSticker, \
|
||||
InlineQueryResultCachedVideo, InlineQueryResultCachedVoice, InlineQueryResultContact, InlineQueryResultDocument, \
|
||||
InlineQueryResultGame, InlineQueryResultGif, InlineQueryResultLocation, InlineQueryResultMpeg4Gif, \
|
||||
InlineQueryResultPhoto, InlineQueryResultVenue, InlineQueryResultVideo, InlineQueryResultVoice
|
||||
from .input_file import InputFile
|
||||
from .input_media import InputMedia, InputMediaAnimation, InputMediaAudio, InputMediaDocument, InputMediaPhoto, \
|
||||
InputMediaVideo, MediaGroup
|
||||
from .input_message_content import InputContactMessageContent, InputLocationMessageContent, InputMessageContent, \
|
||||
InputTextMessageContent, InputVenueMessageContent, InputInvoiceMessageContent
|
||||
from .invoice import Invoice
|
||||
from .labeled_price import LabeledPrice
|
||||
from .location import Location
|
||||
from .login_url import LoginUrl
|
||||
from .mask_position import MaskPosition
|
||||
from .message import ContentType, ContentTypes, Message, ParseMode
|
||||
from .message_auto_delete_timer_changed import MessageAutoDeleteTimerChanged
|
||||
from .message_entity import MessageEntity, MessageEntityType
|
||||
from .message_id import MessageId
|
||||
from .order_info import OrderInfo
|
||||
from .passport_data import PassportData
|
||||
from .passport_element_error import PassportElementError, PassportElementErrorDataField, PassportElementErrorFile, \
|
||||
PassportElementErrorFiles, PassportElementErrorFrontSide, PassportElementErrorReverseSide, \
|
||||
PassportElementErrorSelfie
|
||||
from .passport_file import PassportFile
|
||||
from .photo_size import PhotoSize
|
||||
from .poll import PollOption, Poll, PollAnswer, PollType
|
||||
from .pre_checkout_query import PreCheckoutQuery
|
||||
from .proximity_alert_triggered import ProximityAlertTriggered
|
||||
from .reply_keyboard import KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove, KeyboardButtonPollType
|
||||
from .response_parameters import ResponseParameters
|
||||
from .shipping_address import ShippingAddress
|
||||
from .shipping_option import ShippingOption
|
||||
from .shipping_query import ShippingQuery
|
||||
from .sticker import Sticker
|
||||
from .sticker_set import StickerSet
|
||||
from .successful_payment import SuccessfulPayment
|
||||
from .update import AllowedUpdates, Update
|
||||
from .user import User
|
||||
from .user_profile_photos import UserProfilePhotos
|
||||
from .venue import Venue
|
||||
from .video import Video
|
||||
from .video_note import VideoNote
|
||||
from .voice import Voice
|
||||
from .voice_chat_ended import VoiceChatEnded
|
||||
from .voice_chat_participants_invited import VoiceChatParticipantsInvited
|
||||
from .voice_chat_scheduled import VoiceChatScheduled
|
||||
from .voice_chat_started import VoiceChatStarted
|
||||
from .webhook_info import WebhookInfo
|
||||
|
||||
__all__ = (
|
||||
'AllowedUpdates',
|
||||
'Animation',
|
||||
'Audio',
|
||||
'AuthWidgetData',
|
||||
'BotCommand',
|
||||
'BotCommandScope',
|
||||
'BotCommandScopeAllChatAdministrators',
|
||||
'BotCommandScopeAllGroupChats',
|
||||
'BotCommandScopeAllPrivateChats',
|
||||
'BotCommandScopeChat',
|
||||
'BotCommandScopeChatAdministrators',
|
||||
'BotCommandScopeChatMember',
|
||||
'BotCommandScopeDefault',
|
||||
'BotCommandScopeType',
|
||||
'CallbackGame',
|
||||
'CallbackQuery',
|
||||
'Chat',
|
||||
'ChatActions',
|
||||
'ChatInviteLink',
|
||||
'ChatLocation',
|
||||
'ChatMember',
|
||||
'ChatMemberStatus',
|
||||
'ChatMemberUpdated',
|
||||
'ChatPermissions',
|
||||
'ChatPhoto',
|
||||
'ChatType',
|
||||
'ChosenInlineResult',
|
||||
'Contact',
|
||||
'ContentType',
|
||||
'ContentTypes',
|
||||
'Dice',
|
||||
'DiceEmoji',
|
||||
'Document',
|
||||
'EncryptedCredentials',
|
||||
'EncryptedPassportElement',
|
||||
'File',
|
||||
'ForceReply',
|
||||
'Game',
|
||||
'GameHighScore',
|
||||
'InlineKeyboardButton',
|
||||
'InlineKeyboardMarkup',
|
||||
'InlineQuery',
|
||||
'InlineQueryResult',
|
||||
'InlineQueryResultArticle',
|
||||
'InlineQueryResultAudio',
|
||||
'InlineQueryResultCachedAudio',
|
||||
'InlineQueryResultCachedDocument',
|
||||
'InlineQueryResultCachedGif',
|
||||
'InlineQueryResultCachedMpeg4Gif',
|
||||
'InlineQueryResultCachedPhoto',
|
||||
'InlineQueryResultCachedSticker',
|
||||
'InlineQueryResultCachedVideo',
|
||||
'InlineQueryResultCachedVoice',
|
||||
'InlineQueryResultContact',
|
||||
'InlineQueryResultDocument',
|
||||
'InlineQueryResultGame',
|
||||
'InlineQueryResultGif',
|
||||
'InlineQueryResultLocation',
|
||||
'InlineQueryResultMpeg4Gif',
|
||||
'InlineQueryResultPhoto',
|
||||
'InlineQueryResultVenue',
|
||||
'InlineQueryResultVideo',
|
||||
'InlineQueryResultVoice',
|
||||
'InputContactMessageContent',
|
||||
'InputInvoiceMessageContent',
|
||||
'InputFile',
|
||||
'InputLocationMessageContent',
|
||||
'InputMedia',
|
||||
'InputMediaAnimation',
|
||||
'InputMediaAudio',
|
||||
'InputMediaDocument',
|
||||
'InputMediaPhoto',
|
||||
'InputMediaVideo',
|
||||
'InputMessageContent',
|
||||
'InputTextMessageContent',
|
||||
'InputVenueMessageContent',
|
||||
'Invoice',
|
||||
'KeyboardButton',
|
||||
'KeyboardButtonPollType',
|
||||
'LabeledPrice',
|
||||
'Location',
|
||||
'LoginUrl',
|
||||
'MaskPosition',
|
||||
'MediaGroup',
|
||||
'Message',
|
||||
'MessageAutoDeleteTimerChanged',
|
||||
'MessageEntity',
|
||||
'MessageEntityType',
|
||||
'MessageId',
|
||||
'OrderInfo',
|
||||
'ParseMode',
|
||||
'PassportData',
|
||||
'PassportElementError',
|
||||
'PassportElementErrorDataField',
|
||||
'PassportElementErrorFile',
|
||||
'PassportElementErrorFiles',
|
||||
'PassportElementErrorFrontSide',
|
||||
'PassportElementErrorReverseSide',
|
||||
'PassportElementErrorSelfie',
|
||||
'PassportFile',
|
||||
'PhotoSize',
|
||||
'Poll',
|
||||
'PollAnswer',
|
||||
'PollOption',
|
||||
'PollType',
|
||||
'PreCheckoutQuery',
|
||||
'ProximityAlertTriggered',
|
||||
'ReplyKeyboardMarkup',
|
||||
'ReplyKeyboardRemove',
|
||||
'ResponseParameters',
|
||||
'ShippingAddress',
|
||||
'ShippingOption',
|
||||
'ShippingQuery',
|
||||
'Sticker',
|
||||
'StickerSet',
|
||||
'SuccessfulPayment',
|
||||
'Update',
|
||||
'User',
|
||||
'UserProfilePhotos',
|
||||
'Venue',
|
||||
'Video',
|
||||
'VideoNote',
|
||||
'Voice',
|
||||
'VoiceChatEnded',
|
||||
'VoiceChatParticipantsInvited',
|
||||
'VoiceChatScheduled',
|
||||
'VoiceChatStarted',
|
||||
'WebhookInfo',
|
||||
'base',
|
||||
'fields',
|
||||
)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user