From c3c85abff01855cb4f103805a339e9ad58c6ad31 Mon Sep 17 00:00:00 2001 From: avitoras Date: Tue, 21 Jan 2025 15:38:24 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=D0=B0?= =?UTF-8?q?=20=D0=B3=D0=B0=D0=B2=D0=BD=D0=BE=20=D1=81=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=BA=D1=82=D1=83=D1=80=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=B0=20=D0=BF=D0=BE=D0=BB=D0=BD=D0=BE=D0=B5=20=D0=B2?= =?UTF-8?q?=D0=B0=D1=89=D0=B5=D0=B5=D0=B5=D0=B5=20=D0=BA=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=BE=D1=82=D1=81=D1=82=D0=BE=D0=B9=20=D0=B5=D0=B1=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D0=B9=20=D0=BF=D1=80=D0=BE=D1=81=D1=82=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/tokens.cpython-313.pyc | Bin 0 -> 195 bytes app/__init__.py | 0 app/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 158 bytes app/__pycache__/app.cpython-313.pyc | Bin 0 -> 3872 bytes app/app.py | 44 +++++++ main.py | 124 +----------------- styles.tcss => tcss/style.tcss | 0 telegram/__init__.py | 0 telegram/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 163 bytes telegram/__pycache__/client.cpython-313.pyc | Bin 0 -> 2681 bytes telegram/client.py | 31 +++++ tokens.py | 2 + widgets/__init__.py | 0 widgets/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 162 bytes widgets/__pycache__/chat.cpython-313.pyc | Bin 0 -> 1930 bytes widgets/__pycache__/dialog.cpython-313.pyc | Bin 0 -> 2238 bytes widgets/__pycache__/message.cpython-313.pyc | Bin 0 -> 2141 bytes widgets/chat.py | 18 +++ widgets/dialog.py | 24 ++++ widgets/message.py | 27 ++++ 20 files changed, 149 insertions(+), 121 deletions(-) create mode 100644 __pycache__/tokens.cpython-313.pyc create mode 100644 app/__init__.py create mode 100644 app/__pycache__/__init__.cpython-313.pyc create mode 100644 app/__pycache__/app.cpython-313.pyc create mode 100644 app/app.py rename styles.tcss => tcss/style.tcss (100%) create mode 100644 telegram/__init__.py create mode 100644 telegram/__pycache__/__init__.cpython-313.pyc create mode 100644 telegram/__pycache__/client.cpython-313.pyc create mode 100644 telegram/client.py create mode 100644 tokens.py create mode 100644 widgets/__init__.py create mode 100644 widgets/__pycache__/__init__.cpython-313.pyc create mode 100644 widgets/__pycache__/chat.cpython-313.pyc create mode 100644 widgets/__pycache__/dialog.cpython-313.pyc create mode 100644 widgets/__pycache__/message.cpython-313.pyc create mode 100644 widgets/chat.py create mode 100644 widgets/dialog.py create mode 100644 widgets/message.py diff --git a/__pycache__/tokens.cpython-313.pyc b/__pycache__/tokens.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae364056d10c74c8c9110c7c917933b4bb5401e5 GIT binary patch literal 195 zcmey&%ge<81Sco=r%MCr#~=<2FhUuhd4P=jOk38%rEnSLNB?2gr6qU zEsn&3%=nDN;*48tAXa9|N`}uMy|>Ku%My$9GxBp&^%Ki7OY(~ni}eGF^0QKtON#Z= zGl4`&YEEi;QDSa>P{wB#AY&>+I)f&o-%5reCLr%KNa~iYepzCXenx(7 zs(xZwW=VcgVzGWeQGQlxa!Ij%dM1!4NzF-3FG|dfFDcE`Pb?_VkB`sH%PfhH*DI*J g#bJ}1pHiBWYFESxG!0~1F^KVznURsPh#ANN0P}k$#{d8T literal 0 HcmV?d00001 diff --git a/app/__pycache__/app.cpython-313.pyc b/app/__pycache__/app.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53fddff829e3b45b48bf927f0640ca857485d6f7 GIT binary patch literal 3872 zcmb7HO>7&-6`mn?$>rZtBK1Sc`k_Tj7HyeKTK~IoP0KB8s$mVSevMW#3_QpY7Z@nws6{}jZVET!?<(?GE^WZ-xAA#ouY@n+2v9c z;k4)o`{vEOH^Z4X-}}*q&*w(a-uv0>`H&N#Puaj~e1qBeB{0{Jgd{wPQkdYBjo2b= zY@4*FIKriP!W(1zq$A}d&Xhoel#94hZsIoPxk*pTOS~x`@ufr}ru@X8>L4AdPSR<} z`N=>kNP-6MnCwb*lWv1|PWGgFNw2{Rlc7|Ygj0Q_FM>j77)h=^B)QLV`|Rd9$+o;F z=Dp7bF&h=9m7=7>WEK};cN=wN77KDAM+Mf; zXVm$uc}+eVOKe1u;mFg=I{cqLF`fV8gRsW;@2mJ&6cJ=j3fp|QjWmPqyY8Q)2oUvI9 z+gObOjy>kac_2seH8g8U&@`Sw-v{}=#!LjwTJS`(4ohuTu(%mCWdPe6o4o~<8B}bp z$)gpVjyWl>R>1I7kmW+Dpvf``!Wz=WNH-AboX?bUMbPkT4P?n#16nIK%Bf0mj=E%+ z$*8Ixylk#~btEq{60Z4N%tx`z9)3YzWc#-t8 zpX_QedfYmfA0%oN$m7dsP4K*tYx(gW~057_50>4P;fI~jzII zLY-+r`yZC!H?4xn80g1r#?>irMl%CurU}RZh-t7DF%7`>f&mbIQ}E0z>OT0LnOsPCkoJ$v$JBVkT;9B@X7rwn-R1X|BZ2x-8AJ z-;x}#vcnp0_9FVaO>!QxmmF{d2HCbY^W!0@F_0nf&JRxq^{axu5*f1bRe$vGoUsnqpiMIjgE zatU&p!IDn+DHd54%1a96N|^nq5gVkyc!y>hYnUl2X7NSbWjf+uLq7V zJMV@E-WmM)pgwk}7Cu}LpQwgUe0a7NPS?X{tKqZy_s-YCFD#39g`T?5Ulsb_o~{YQ zbs<(2Vjl~;KkXS<{`TEq`1+AIjx3+J8wg#GzY(to#;Sp_<%zXm?+xx2e{1eHg_Xjs zS$*_SHFy}bynS_Vr0R{_?D~gy^nnZY4u0-J!3q4O%5ZRHV8V;v!4q!o=JDOYZgD`C z(xUKfJTMp*sb`y!#B?wl0HI|L^8X=h%r#^8X0ntxCbfXHgsx#&+jJMH=|-jmYCQPc z*NAPP*@Us>C{NbQqwQ!Mv53W54$eDgi=ZJmX9T6A&)A319R6yJJTf&5SUb{G+=^rJ zH0((Y%&O!FD!;WU$x03g5;ekfZqj4bIjJwufhUWezqpno)Lv9WC7* zEMEsUvl3^<3U{ucHqtfO1`DYdLWQin1a%bDGh_&+8YPjLu01VM+S}^WErM~jiaqt? zX5uol_MWP^rzR%qLP8f3YyPfRFI4@}ntwz$Gxk$vM!Pz=AHR$Da=!@f$1!Z26S60J z*L2L!$~+dcWSP2Us2p-otpo3s*4urHwGRe z=pKn6+CV_a4r`-yte*-RRIl26xkMOz2zzPj(Ug}oxObdA7OUTkE6{*7-Aoi}i+8a| zK-ke(L2NF+P{={jPzlScgr&?D7i48CVZn}i8)|VD=gmAKT2qZ=!2ETy&W@XPwo#B% zhgN<;DXE)v>=@&9w0j-xT1V*`O0T2II-0zP a2JWHl_t4YpDEg4wfk%HD{Q^N}Z1^9?s9&l8 literal 0 HcmV?d00001 diff --git a/app/app.py b/app/app.py new file mode 100644 index 0000000..41124a6 --- /dev/null +++ b/app/app.py @@ -0,0 +1,44 @@ +from telethon import TelegramClient, events +from textual.app import App, ComposeResult +from textual.containers import Horizontal, VerticalScroll, Vertical, Container +from textual.widgets import Placeholder, Label, Static, Rule, Input, Button +from widgets.chat import Chat +from widgets.dialog import Dialog +from telegram.client import TelegramClientWrapper +from tokens import api_id, api_hash + +class TelegramTUI(App): + CSS_PATH = "../tcss/style.tcss" + + def __init__(self): + super().__init__() + self.telegram_client = TelegramClientWrapper(api_id, api_hash, self.handler) + + async def on_mount(self) -> None: + await self.telegram_client.connect() + await self.update_chat_list() + + async def handler(self, event): + await self.update_chat_list() + + async def update_chat_list(self): + dialogs = await self.telegram_client.get_dialogs(limit=10) + chat_container = self.query_one("#main_container").query_one("#chats").query_one("#chat_container") + chat_container.query(Chat).remove() + + for dialog in dialogs: + name = dialog.name + msg = dialog.message.message + chat = Chat(name, msg, id=f"chat-{dialog.id}") + chat_container.mount(chat) + + def compose(self) -> ComposeResult: + with Horizontal(id="main_container"): + with Horizontal(id="chats"): + yield VerticalScroll(Static(id="chat_container")) + yield Rule("vertical") + yield Dialog() + + async def on_exit_app(self): + await self.telegram_client.disconnect() + return super()._on_exit_app() diff --git a/main.py b/main.py index fb934a2..d438f0f 100644 --- a/main.py +++ b/main.py @@ -1,123 +1,5 @@ -from telethon import TelegramClient, events, utils -from textual.app import App, ComposeResult -from textual.widgets import Placeholder, Label, Static, Rule, Input, Button -from textual.containers import Horizontal, VerticalScroll, Vertical, Container -from textual.reactive import var -from textual.widget import Widget -from tokens import api_id, api_hash - -class Chat(Widget): - """Кастомный виджет чата слева""" - - def __init__(self, name: str | None = None, msg: str | None = None, id: str | None = None, classes: str | None = None, disabled: bool = False): - super().__init__(name=str(name), id=id, classes=classes, disabled=disabled) - self.msg = str(msg) - - def _on_click(self): - pass - - def compose(self) -> ComposeResult: - with Horizontal(): - yield Label(f"┌───┐\n│ {self.name[:1]} │\n└───┘") - with Vertical(): - yield Label(self.name, id="name") - yield Label(self.msg, id="last_msg") - -class Dialog(Widget): - """Кастомный виджет диалога справа""" - - def __init__(self, name = None, id = None, classes = None, disabled = False): - super().__init__(name=name, id=id, classes=classes, disabled=disabled) - - def compose(self): - with Vertical(): - with VerticalScroll(id="dialog"): - yield Message(message="привет, я ыплыжлп", is_me=True) - yield Message(message="о, дщытрапшщцрущ", is_me=False) - yield Message(message="ДАТОУШЩАРШЩУРЩША!!!!", is_me=False) - #должно быть примерно is_me = message.from_id == client.get_peer_id("me") - #но я могу ошибаться, я это фиш если что - - with Horizontal(id="input_place"): - yield Input(placeholder="Сообщение", id="msg_input") - yield Button(label="➤", id="send", variant="primary") - - def on_button_pressed(event): - app.notify("Нажато отправить") - - -class Message(Widget): - """Кастомный виджет сообщения""" - - def __init__(self, name = None, message = None, is_me = None, id = None, classes = None, disabled = False): - super().__init__(name=name, id=id, classes=classes, disabled=disabled) - self.message = message - self.is_me = is_me - - def _on_mount(self): - if self.is_me: - self.styles.padding = (0, 0, 0, 15) - self.query_one(Container).query_one(Label).styles.text_align = "right" - self.query_one(Container).styles.align_horizontal = "right" - self.query_one(Container).query_one(Label).styles.border = ("solid", "#4287f5") - else: - self.styles.padding = (0, 15, 0, 0) - self.query_one(Container).query_one(Label).styles.text_align = "left" - self.query_one(Container).styles.align_horizontal = "left" - self.query_one(Container).query_one(Label).styles.border = ("solid", "#ffffff") - - def compose(self): - with Container(): - #yield Label(self.message.message) #это нормальный вариант - yield Label(str(self.message)) #это тестовый вариант - -class TelegramTUI(App): - """Главный класс приложения""" - - CSS_PATH = "styles.tcss" - - def __init__(self): - super().__init__() - self.api_id = api_id - self.api_hash = api_hash - self.chats = [] - self.client = TelegramClient('user', api_id, api_hash) - self.client.on(events.NewMessage())(self.handler) - - async def on_mount(self) -> None: - await self.client.start() - await self.update_chat_list() - - async def handler(self, event): - await self.update_chat_list() - - async def update_chat_list(self): - dialogs = [] - async for dialog in self.client.iter_dialogs(limit=10): - dialogs.append(dialog) - - chat_container = self.query_one("#main_container").query_one("#chats").query_one("#chat_container") - chat_container.query(Chat).remove() - - for dialog in dialogs: - name = utils.get_display_name(dialog.entity) - msg = dialog.message.message - chat = Chat(name, msg, id=f"chat-{dialog.id}") - chat_container.mount(chat) - - def compose(self) -> ComposeResult: - with Horizontal(id="main_container"): - with Horizontal(id="chats"): - yield VerticalScroll(*[Static(id="chat_container")]) - - yield Rule("vertical") - - yield Dialog() - - async def _on_exit_app(self): - await self.client.disconnect() - return super()._on_exit_app() +from app.app import TelegramTUI if __name__ == "__main__": - app = TelegramTUI() - app.run() + tg = TelegramTUI() + tg.run() diff --git a/styles.tcss b/tcss/style.tcss similarity index 100% rename from styles.tcss rename to tcss/style.tcss diff --git a/telegram/__init__.py b/telegram/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/telegram/__pycache__/__init__.cpython-313.pyc b/telegram/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f890a5cc6786001b08ede4c62e8e9df92dad2018 GIT binary patch literal 163 zcmey&%ge<81PT-T(?RrO5CH>>P{wB#AY&>+I)f&o-%5reCLr%KNa~i8epzCXenx(7 zs(xZwW=VcgVzGWeQGQlxa!Ij%dM1!4NzF-3FG|dfFDcE0bM)imGxIV_;^XxSDsOSv dy?*Sy>EXd}L;1WGrF^vH7fK6rR~XZyd)?LVh5mi31^t)q)Wsq@)ogY7dYU3&og5f@-z3H_pPwPG>f$ zBK1(w3V}qGa)_#4+LTHa>7|z*s;U>RJz?BpYlT!*J>>>*5z4La&Du@?SL&%F?VC40 zZ)V>6-p^KAT7m@H>h0C+Z!#f&;h@%(DpNTP%o<6OB%LNxl+h`PNmDYDqhv2RK$21q zNy?*=zndvyPJubKKBs22SYQ)3#AGjg!E&rDGZ)@+Y%Aw_nzala_tYiVc6i!9#;4UY zN#z8L*T`kUXp%4~NtukdG9@VkRg-WV(~?a|wTE1xERfV-tS1AkDXYhVUgz@{zRS$T zMT>2Mx+GoG5${vs!^z60K-S153Y}<4I@>;qE6`HJsn4g#OznmKqM$Q)&I>IiU(#w* zGkT5N=?{?6>Y!$`D9MtTl<<@#Zn2ok@On>6`zC8MGZ{me&6qcH8OLG_74d=z>%(&v z=VsQ5DW1YDXU@~iMcc45o{s&z$>+Vug1@CE%TYE8%{v`mHd%Z=zhK49W!ud&lgH1q z{1q$h@_5z;;#RRU+$Fm{i2Khvvbf^uhGFMy*D$=khE_jPTgN;3VIUuqM_q&K7w=vy zcAdJR+-ffCq1EP_%_aR%K|i#f|8coAcILs@nc~>g@A`BF1W39L01VJBpTJkS0OTNv z0&oBe@GrKRDuBD^Yeqi{&OHz7%XCdns3ABdOLUS@$K*M>K@%~FHG`O^a@S<;24!Iw zaePITwc|n{ozLaKNZu=rm98!$@O(dzP0+d=ZeP86^J*#FUkLXX!viIKpr{XQS3`(;?*>ZG`^6+OlrAzNT+5WAp0M**<*xj>@bL#$L3sx;tWMwwE;?EQAM(;h~Z~ zRMdyISubo#?+zpk6@lrm!1$QPNlyCjxTa{5o}{g${RLcea!P6(o};K5v?w_T&jIYa zgCr&GAr}=c#R&)Q%pOAWr)L8GzTGsX)TGZ#=Q;^#hEuqdQwD+h+#Eqqf^d#ePj&1C z+l?u{ONDILVn)U`oqU#KtS(x)jMr=|n2Xg}h<$W7HUPv6Rd*VW%^`F8Badb{<{S*+ zszWwsEw_H^Kx344Z4v(b9vmSYvwPo-P`Nky_4Jq1rQYL(-s3-w-p79O8KF%hpAVHo zdrP7ILa2XTdl(viBE#hU-pM}?pDaekzrTE!mRh5Q*64cM!`6cvmkW{c`}+9ygUI+c ze-&=H);oESex*!Ecj&nGtvn%p*8vkh(+TMp6_|UpXR=SZw_gYTC7-|uu6zV!cXCeA zMoIV*<`>as>WQ~DL!fAZRD(2J!x2_RS=^C84tz=;#H73-dlF<+C1);JUZ9#yW11Iy zTi|#$H$3$rgGH_H9 zqrwZpEjLkLsFjev@rjVXgNCt?&n!8}hYaI`CDW;{L=0ojX54k`oR!NP27|~TtOp5Z z1vY|2JipU0AZ5CC+Av+0+3zp87B`FyA}$xHlVLmwg5YvY1=q=zB&qMvEuE?dwlt~^ z|E($N8&5;3>c3iSPs7f7s|GKr;3FFUConauKq#T5HZcW1SNYNI!nyG2Yh_-y%T7t^WWcW*}1l literal 0 HcmV?d00001 diff --git a/telegram/client.py b/telegram/client.py new file mode 100644 index 0000000..21935a4 --- /dev/null +++ b/telegram/client.py @@ -0,0 +1,31 @@ +from telethon import TelegramClient, events, utils + +class TelegramClientWrapper: + def __init__(self, api_id, api_hash, message_handler): + self.client = TelegramClient('user', api_id, api_hash) + self.client.add_event_handler(message_handler, events.NewMessage()) + + async def connect(self): + await self.client.start() + + async def disconnect(self): + await self.client.disconnect() + + async def get_dialogs(self, limit=10): + dialogs_list = [] + async for dialog in self.client.iter_dialogs(limit=limit): + dialogs_list.append(dialog) + return [self._map_dialog(d) for d in dialogs_list] + + def _map_dialog(self, dialog): + return DialogInfo( + id=dialog.id, + name=utils.get_display_name(dialog.entity), + message=dialog.message + ) + +class DialogInfo: + def __init__(self, id, name, message): + self.id = id + self.name = name + self.message = message diff --git a/tokens.py b/tokens.py new file mode 100644 index 0000000..1c6c644 --- /dev/null +++ b/tokens.py @@ -0,0 +1,2 @@ +api_hash = 111 +api_id = 11 diff --git a/widgets/__init__.py b/widgets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/widgets/__pycache__/__init__.cpython-313.pyc b/widgets/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60dd34e3c0a50fe566aa73c2073eee422a938b38 GIT binary patch literal 162 zcmey&%ge<81V$74(?RrO5CH>>P{wB#AY&>+I)f&o-%5reCLr%KNa~iOepzCXenx(7 zs(xZwW=VcgVzGWeQGQlxa!Ij%dM1!4NzF-3FG|dfFDcE`FV9R#PX!9b$7kkcmc+;F j6;$5hu*uC&Da}c>D`Ewj2(qyl#Q4a}$jDg43}gWS$xJAn literal 0 HcmV?d00001 diff --git a/widgets/__pycache__/chat.cpython-313.pyc b/widgets/__pycache__/chat.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..401b80beae9d60a33e4bec18954c5f3a2e54d178 GIT binary patch literal 1930 zcmZ`4TWl0n^xS#u%x-sETBI!t3CkmdiNZ?QswB42Vh9woF${~wu1==2)9sY$4&Ir? z$B(5SiqS@lZ9>IFKFeP*f;B#p@`Zo1^+zW)Cir3cSFHwO{P5g6yA_C>wr9@ko_n6R z>zPan5avGmuqufFzcQu;a+6peL}C_n(8&oHB9!D9Eu0XBL@EwRRN}mNLLN%cL=Jjk z7wA$Jbh(`9L!S(&QcY;eDkC)#$X=8Jx4c?lx{-R?rh#LbE*d0WbShOl zu$X-d+M2|=i^QuKPZ=oDfeJdIqApNL&*)NF*2Vn_u)AASVuMmPD7Bm@q)JdAdNK>+ z>bNvcsG_H`KvlgBaZ*oH)b|tGwgVhU%Qb!9_9M08 z_~wXfSFA)cL-xTOfYomOG@=1A3&Z%0;Z&jouV5_0t^PoX^pRNiQlTX42HiUPN~%VMWcnr!>^wPpvC^E<5vsxAuiFNoy`333AE3qfxzCQz9iQLZ=svi->0m54Hg{}3+vqMVZz|l8p=&#$_Uwi7Z=Ks_vww4Dy8MsN zUYx16!EQ3G4a(w;{m&NUrQIr$OOGZ|x>QIF3dyAb1tmA-)Zk|2W`}}u%%1P7Ttqmk zrP(sGCkU50Wf&7)rS391Z5XfBO}DA(FpN=$`hn}z?3#ya#V{(KWf-&zqllyt&vW@I z(rw7o920KAMGs7Tx(zc3s54RzY#&c%n$Lh`yRKniG^~@n!q4!fqHN4KVomVb`*!yo z_(|&jT@vK&m-H)zxtG@f$pw9}a4jZp9SKjK{(gvy!?81AjW)(8=hgs@3PZvjc7O~1 zP>GzmlaS@UH9*8Sliya<)Tkq{-v}`41I<^4Pejz!l3MIP5>|lv@w~7AqxP0IK111S y9p|u>QEc<$$3lHNF75!`k1{rVbe)Xbjt;7Id@RZI2~;x999$ z6%&(E6GDRo5^W?T5)>cct)h?`pp`!HI9o!Zn-UUz;*D5L3Gu;iX7>uIM(1+h%zX3B zH{ZPp-|=oELt_C=_)EM$#VL zwzZ<3_mA;qa3-4H4D%1*Mh6h)6oh$&!-B%&kRlDBS2#szL5JnT92S*O3&LR1aYs`y zm?RVA8m#|7CQ|NEGVP9l;xd`Yhy3`Mqz-AI^J_tD<;Kx|rlz7lG=ScRq`ccWAShf9 zJbw|T`963c-Y9rd-qdVcw>`OF*xEr;FQj=-w5t^zd$Ot;Wy4X`wCIIw-5kOR@P`|y zNP_Sps>-&js!g+=f;Qs4mKoM?=8#p=Gup7>SXi?&Z)5AQo_Fj_(E#D-re4HaNp-45 z<|Fp_cBa5yrn7PcFQcv#{!4Y%LWqFUUIF6K2%3}QW0EU3pUFlD9=$D zG#UCf_|Ff5whg5qZ~GV5y8T?BlC9YhmjriU!Epkx0U6c)do`;G#?3}sTmMoGg*DBYNpUzm|60n`nx z?4+U0!5-86VoHse79^%VFfCJfo8{2ikPDQ;O(3E0tWw3Yb+0}^dN8k}cAtZ|j{xcM z6(q=bBcM_RT-9bes0fHtd;eT6Mnb;=W0+-8tK^b3sInoeN1+-+X-VUb5p(vg7dr z?CiXgT>qGN}iU6lRZPACC-w0wH4WPYLyQJ-<7E7AKb4jhbT!7D1WDqQ6JXJj!olA1qn)8 zW%VHYq^K1PSk((&bC9ZktUL?*Y|2|B=oh)}lsqP%N{l5)bI%=lBW?!$CHPSF_3cPU zDXEsVlCG*=R8>n>p=#1`ovMCV)y!Zep{hd$wjI+b>tzd;B~>k0c~xcHh-n$%mq2(c zfO#DaK5VMyIM{%2bsNm%0Waru(**YBFeOd~zSkM}Fa;SC6sGnn5RZG-}s5p>MS-*wVmIsgCw literal 0 HcmV?d00001 diff --git a/widgets/__pycache__/message.cpython-313.pyc b/widgets/__pycache__/message.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d066b63ef0c394c7ed126957dff943805a3ea77 GIT binary patch literal 2141 zcmah~|8EpU6rb6>y}diG^sEJrLhM0_vV1#2C>2r&L@<%o#<*6S96H(F?Hx<@Zp+Lb z3O@lqm^OeH5*yK&@C&~f6N5$+6Cv?G*t0d9laiSDQ-32?13&nKZ{~KdVA}AK`|O*U zH*em|d+&2gU0o>z^7ZvbWjKb=pJEV+7Ai|eK$%4*GVusHi7CzrT^UhMs#KM_Iubjn zQ7wnEXe%;feaO^KX@hEeKaE%7hQ25U2IktRHEFw`BwzDtzU9z_DRI5%T8!C@CrS>pCSAJ(%Nnas*_0;;acYiF2-mCa+i=Zcq-w+c zV$62SRHTw-1iT<%jexX(E&!e+M0zKLC19Lu%SC=Pf6k)$(_YoiTjw0#qZZ4*MZGh2 z(P#OJ1K``PU7=Q$_;n}$q0AJ^hcWD#I#0WW`%L)6d!jJKA*>(Z$wjn~=$g@+iR_Ki z?V%u%Z6?NA8(zAaZmsLPmRbT6RKx;95f3CE_bSZJqH*;0)2pFTq4T7J;c5+!;}tET zu-nqHRKRCEnqB^G4^`^~f?@|7afknjD@sU;sf;TtT68>v1zypjQ%a_~ijU686=#!>T7g4J>``Os_v0De{dUsDJTbYdyG6T)bz^xN=nH|$wYfX3KP~%W*YkvB8V`OGz zKHcAXdH3{*#^}uGe0rd@cWC;J2kFht^yc~W?$*`=?Umos{eL{OW7ktV4y>|+u7`M@ z=@^mc0r)L_DwP~`O`+2>gD@vVK{-?q_m)!V)bYx_5cNv*J%?toBzqwL!LavoKw(?Z zE)?}m3C=7lIn)m)iM7LOKPuxPwTulcDyNfEt}>rWsxq+55QCj4%!Xd{s#6}bd3Qu9 z;lw7eVXpuzLN*q<)?X_u^lbQ2y>a~J=;xzzS!1qe$FJ!fk5#mGW25j%;a|29Y%i}l zmcZAx45{BFLHRLtOw)hCI;c>7k|qUV8u2k9uNx^rvx1I+W>W-;qEvTO}Mhk6oD$bL>zCvxk?fw{UKg1C#YDuI@#`H+V7(YZ?9-{4l Qf5) Date: Tue, 21 Jan 2025 15:40:00 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D1=81=D0=BB=D1=83=D1=87=D0=B0=D0=B9=D0=BD?= =?UTF-8?q?=D0=BE=20=D0=B7=D0=B0=D0=BB=D0=B8=D0=BB=20=D0=BF=D0=B0=D0=B9?= =?UTF-8?q?=D0=BA=D0=B5=D1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/tokens.cpython-313.pyc | Bin 195 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 __pycache__/tokens.cpython-313.pyc diff --git a/__pycache__/tokens.cpython-313.pyc b/__pycache__/tokens.cpython-313.pyc deleted file mode 100644 index ae364056d10c74c8c9110c7c917933b4bb5401e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 195 zcmey&%ge<81Sco=r%MCr#~=<2FhUuhd4P=jOk38%rEnSLNB?2gr6qU zEsn&3%=nDN;*48tAXa9|N`}uMy|>Ku%My$9GxBp&^%Ki7OY(~ni}eGF^0QKtON#Z= zGl4`&YEEi;QDSa