From 6acef907a8c3e0de7b1452f19dfac22ea59c550a Mon Sep 17 00:00:00 2001 From: Victor Phan Date: Thu, 23 Jul 2026 15:19:01 +0700 Subject: [PATCH] feat: implement FacebookBot class for automated image posting and commenting via uiautomator2 --- .../__pycache__/facebook_bot.cpython-314.pyc | Bin 0 -> 12868 bytes serverPython/__pycache__/main.cpython-314.pyc | Bin 6889 -> 8477 bytes serverPython/facebook_bot.py | 38 ++++++++++-------- 3 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 serverPython/__pycache__/facebook_bot.cpython-314.pyc diff --git a/serverPython/__pycache__/facebook_bot.cpython-314.pyc b/serverPython/__pycache__/facebook_bot.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4136a3e9fb2fee5472c1a1531ec35e80fb3b2f11 GIT binary patch literal 12868 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 literal 0 HcmV?d00001 diff --git a/serverPython/__pycache__/main.cpython-314.pyc b/serverPython/__pycache__/main.cpython-314.pyc index b3c21c368f160baa18be50b745b0e5363162c610..d4a61f2ba4b8e10fd6ee0d3251f4a5f54928457e 100644 GIT binary patch delta 2900 zcmZWrYfM|$9Y5EP>$fq+_`xH-U}7L(%)_*S5FQ~fG9d0v>Wsud48DPz82k46I;4CE zXkU_4twM5EL8exPbyHZ=Y008W8&v96GA+}Z=@Oio-eg-W^+PA^1KA=mZC`ed!AZjo z_;>#2@AH43^FRK3!S%l)vqW40|c$0<*&=| zCIAF=05lM^(gq@GK|_;*HUI=2O}Id%O0vQ)R8}}owl^ml(cWX}rE8QhnqK-DC8U?` zP(#aeEOnkuFMc6V6?If(d2W++?^=5CW`Yvfu^Bfgf>-o^)ccUKp&#I zAY(oQdt|iIjr9|!hftIi*hVIM*RI zoK0HKO&!@Vz#psMBRqF&H68`g2nP&DmB)~Z>bt)*d`75!*apGxf+mf#@CaJOEeNK- z2G~oqJj0N5Hli6G(G<%LtM1;<=_DpU1)vBF0GjO5aLNGin~=!1!I88oKsF(67^Sob z1W14Wwk>E$s|E<)R>=omNj{QS2d!BNzdcLg8R{)+!Uy|u3+;M9YwG2kB3PW=5Kz!s zpA5dCwHI)zfXa`PxNQWKa6Q*j6d--X<~P~di9*7EJ~{lWxiViDQ0PIu?B%xyh#osM znym%pTN)1#Ve&;T%$zz{4oS1y$Z3LGK>^^efN4#hw`!XYXc^FCHD}d@Q4~esxQ0`} zcTFXe`tA06ZqbH-CX-ZDDwI^U-}C=^X(Q6SWuMaqv@f*RW@NN}e3-TkREDiwa5_3C zpu=&?I1P5gX$ojwO~b2|xo)v+7Q^zQ7|77(@YmzuZTOaM8z+8#GwId40G&r$=zQ7=J9VYn z1G4VBd*sD{CEy|5j%u`YZ7wMg+@IA&f^aLA<_y71m&APk!RwZMgY9LM#|`j~&eq$N z6{79m{VrQS+L7&{qXbQIhBgCBuwc_=btq$o+K-i>Cu4aIg%V~BJTttx0mlIETc`t@0iwRm@KHuU zY}{WmSwNw^7exUs{+ip252t0Unc~~f4!#|Mq#9%5ar8LAiu}q+ejn!J6J5EJ$8C)7 z#DGiBAHZ-B!yycZG2r_1_=Za4*4v_ta}idM6o~{ImXsKMl6;i8ASq%T6P1+XJS#Ag zX6Q9vm>G_R8NLQf%XkJqL6bmIa3Nt-BAE+pT!>3#oC)#6qmpujk0m&XOz@EiJ0z)i z=B)%17bG2G@QlE-%y~xAXPz}wl`$qN@YUEgTw@+zaEauZu^7rNel_^-Vd%!tg8|>a zN+aJ0jA+q|IY%-0VUE>$V!z`CLZvesxrN>_;fMP1=zz2m8^AZ06Gv6Wvw zyq0609({Lmty6e0*TP$?g>|<}9u@kg)$lLY;>p~6(du4Mq;fsUT+i*?HB;`4 z>Y8enOxY_|>=g_4ReOEX)UY83=9+Kxc~`sN=@tt+#C^2baZGd^|Fizhrv}s2{;U00 z`XB4_pP2KfhiAsFjjfu?E_XgBfysPz{L1*%i&rkr4ySTTALf*UuY3g|4*h{~Xrqj@4E1gXBjjZ&I ztmckhCO1f+FZzk>rfObw(>QMwy=^I~{UO!9mg5kMJ;@x;6O(yHb6q1A>`I!dUg&HQ z_x6Y_y<+jvq{;t{E`R#W2jP^?^-$+pP~Se7tZ2sZ7hLXnYO>E(&h_0kh&ipIx^;sk zfU(S)GPp#8>pvR>s1&GNVy@@E&uIdFYipW(8=Z$An0p-HeK&&7wFrKza$uy&yX%x+ zstOVPrK_VHP4~1VJxb-hszyZruB4+GO}{VdY(mo?tsNFLeO0BzSf}feX})UFAo_t) z*JIT@FlA_muD3+~plo+R)IAM>FnLFJH|6zBKBgh>-2z8ET;vhWec$37x zz<3_cJ8HF85Q*R3xEelo%o#}{Ld^C(2Y6mL!Ak|69P}gXUveNTTbChf{UTg0aQ_bz C3fB$* delta 1626 zcmZvcZ%k8H6u|Fm-=F?@Ev2QcrIz?m1LP@j}oz&$yiOK6^l-Em? z7X?^6&ki|9DcD3hX*6^#^rt8A8?=B^T#SZ=3|{6oR|d3-4or%RU^4)B=yp+^_+4E` z<)3;)QA!Q52!MbAKhgQHQy&yW82E-Q^9_n>#+??wdpAtvssPhy6^T^W9|Q$qD@g1ycr;(q3!hs0 zC|eexjY#4WR#>{$;#K&7)k8UO#%k}?g|t~ZvEhZSx}=q5+*8&|T7smr*6^K52mZpY z)5tUq+Uo;)ndVVQ)4EZ1s%Tr!VVsf~FOrOs zMKVj3jT$c!Q9UC0V$SKTr(%(-toqRFNCe|)BnUA;Px19DVYq^vM z+0xhkdlE0l`G2clj!j~-Y&V;tQs{XU0h`hWA5+>1NLiFHV1k^ic>km2TUa*PHVur7 zCXZ$^Z#F2MFh5w-<&){`@Uf%A@6Zh=vd1R`9CV32VR6C<=KHhvE{c=)7DmM7n-@=w zi}~f7^Xagtbb(FTL(mNB@;0=)sZLN2Y+L(ogGgP@O~pI|2e zDU#9vDAE%Xsj(tM*jm(%Cnxbxb5;OfEk>nn|aVr}D}cvWMJ>BAp${j~ChG zWGa`>6-Zm3E7gOC~7^~r!>e^S}2XVyn+SFp@&{=ksMf}D~n#zP;FWpx}^Hi}c9mI=k;T%ZBO; zfw{xiOlrk;RkwY$5t)5UCa-Gp{{1Y3pLsgu*CFZmth){96F=a#0q`B?A{1+PZDa0o zZqV;~`>H^E-`?8>;)f=NaGP;Ar++}{L4RN{My=Wh_V%br`=g18TJhDI47+v@dT@>4 zV&SbK$J3PW!r^BK#0rmZiNOky>Uye0 P8sCZrw3U9mD*FEgc`Q;y diff --git a/serverPython/facebook_bot.py b/serverPython/facebook_bot.py index 3ffdd05..8777c63 100644 --- a/serverPython/facebook_bot.py +++ b/serverPython/facebook_bot.py @@ -67,30 +67,34 @@ class FacebookBot: c_desc_en = self.d(descriptionMatches="(?i)^comment$") c_text_en = self.d(textMatches="(?i)^comment$") - btn = None - if c_desc_vn.exists: btn = c_desc_vn - elif c_text_vn.exists: btn = c_text_vn - elif c_desc_en.exists: btn = c_desc_en - elif c_text_en.exists: btn = c_text_en + # Lấy tất cả các nút có thể là nút Bình luận + candidates = [] + if c_desc_vn.exists: candidates.extend([c_desc_vn[i] for i in range(c_desc_vn.count)]) + if c_text_vn.exists: candidates.extend([c_text_vn[i] for i in range(c_text_vn.count)]) + if c_desc_en.exists: candidates.extend([c_desc_en[i] for i in range(c_desc_en.count)]) + if c_text_en.exists: candidates.extend([c_text_en[i] for i in range(c_text_en.count)]) - if btn and btn.exists: + # Chỉ lấy những nút nằm dưới khu vực Header của Facebook (Y > 350) + btn = None + for c in candidates: + if c.info["bounds"]["bottom"] > 350: + btn = c + break + + if btn: if current_post_count == post_index: comment_btn = btn break else: - logging.info(f"Đã thấy bài viết thứ {current_post_count}, đang đẩy nó ra khỏi màn hình để tìm bài {post_index}...") - bounds = btn[0].info["bounds"] - start_y = bounds["bottom"] + logging.info(f"Đã thấy bài viết thứ {current_post_count}, đang đẩy nó vào góc khuất để tìm bài {post_index}...") + bounds = btn.info["bounds"] center_x = (bounds["left"] + bounds["right"]) // 2 + start_y = bounds["bottom"] - # Nếu nút đang nằm ở nửa dưới màn hình, vuốt nó lên sát mép trên - if start_y > 300: - self.d.swipe(center_x, start_y, center_x, 250, duration=0.4) - time.sleep(1) - - # Bồi thêm một cú vuốt 400 pixel nữa để tống cổ hoàn toàn cái nút này khỏi viền trên màn hình - self.d.swipe(center_x, 600, center_x, 100, duration=0.3) - time.sleep(2) + # Vuốt đúng khoảng cách để đẩy nút Bình luận hiện tại lên tọa độ Y=200 (Vùng bị bỏ qua) + if start_y > 250: + self.d.swipe(center_x, start_y, center_x, 200, duration=0.4) + time.sleep(2) current_post_count += 1 continue