feat: add FastAPI server and Facebook automation bot for device-based task execution
This commit is contained in:
@@ -14,9 +14,15 @@ class FacebookBot:
|
|||||||
logging.warning("Không có file ảnh cục bộ để đẩy lên điện thoại.")
|
logging.warning("Không có file ảnh cục bộ để đẩy lên điện thoại.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
import uuid
|
||||||
logging.info(f"Đang đẩy ảnh {local_image_path} vào điện thoại...")
|
logging.info(f"Đang đẩy ảnh {local_image_path} vào điện thoại...")
|
||||||
# Đẩy ảnh vào thư mục Pictures
|
# Tạo tên file độc nhất để đảm bảo luôn hiện lên ĐẦU thư viện ảnh
|
||||||
remote_path = "/sdcard/Pictures/n8n_fb_comment.jpg"
|
random_name = f"n8n_fb_{uuid.uuid4().hex[:8]}.jpg"
|
||||||
|
remote_path = f"/sdcard/Pictures/{random_name}"
|
||||||
|
|
||||||
|
# Xóa bớt các file tạm cũ trước khi đẩy file mới (giữ điện thoại sạch sẽ)
|
||||||
|
self.d.shell("rm -f /sdcard/Pictures/n8n_fb_*.jpg")
|
||||||
|
|
||||||
self.d.push(local_image_path, remote_path)
|
self.d.push(local_image_path, remote_path)
|
||||||
|
|
||||||
# Gọi Media Scanner để Thư viện ảnh nhận diện ngay lập tức
|
# Gọi Media Scanner để Thư viện ảnh nhận diện ngay lập tức
|
||||||
@@ -111,11 +117,16 @@ class FacebookBot:
|
|||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
self.dump_ui_for_debug("fb_step5_camera_opened.xml")
|
self.dump_ui_for_debug("fb_step5_camera_opened.xml")
|
||||||
|
|
||||||
# Chọn ảnh đầu tiên trong thư viện (vừa mới push vào)
|
# Facebook gallery mới dùng Button với description 'Ảnh, mục X...'
|
||||||
# Facebook gallery thường có checkbox hoặc chỉ cần click vào vùng ảnh
|
gallery_images = self.d(descriptionContains="Ảnh, mục")
|
||||||
gallery_images = self.d(className="android.widget.ImageView")
|
if not gallery_images.exists:
|
||||||
if gallery_images.count >= 2:
|
gallery_images = self.d(descriptionContains="Photo")
|
||||||
gallery_images[1].click() # Bỏ qua icon đầu tiên thường là icon camera
|
if not gallery_images.exists:
|
||||||
|
gallery_images = self.d(descriptionContains="Ảnh")
|
||||||
|
|
||||||
|
if gallery_images.exists:
|
||||||
|
# Bấm vào ảnh đầu tiên (ảnh vừa mới push vào điện thoại sẽ nằm ở đầu danh sách)
|
||||||
|
gallery_images[0].click()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
self.dump_ui_for_debug("fb_step6_image_selected.xml")
|
self.dump_ui_for_debug("fb_step6_image_selected.xml")
|
||||||
|
|
||||||
|
|||||||
+36
-6
@@ -38,6 +38,7 @@ class FacebookCommentRequest(BaseModel):
|
|||||||
group_id: Any
|
group_id: Any
|
||||||
content: str
|
content: str
|
||||||
image_url: Optional[str] = None
|
image_url: Optional[str] = None
|
||||||
|
image_base64: Optional[str] = None
|
||||||
|
|
||||||
@app.post("/get_commission")
|
@app.post("/get_commission")
|
||||||
def get_commission_endpoint(req: CommissionRequest):
|
def get_commission_endpoint(req: CommissionRequest):
|
||||||
@@ -79,18 +80,47 @@ def post_facebook_comment(req: FacebookCommentRequest):
|
|||||||
bot = FacebookBot(device_ip=raw_ip)
|
bot = FacebookBot(device_ip=raw_ip)
|
||||||
|
|
||||||
local_image_path = None
|
local_image_path = None
|
||||||
if req.image_url:
|
if req.image_base64:
|
||||||
# Tải ảnh về máy chủ Python tạm thời
|
import base64
|
||||||
|
# Bỏ phần header data:image/jpeg;base64, nếu có
|
||||||
|
b64_data = req.image_base64
|
||||||
|
if "," in b64_data:
|
||||||
|
b64_data = b64_data.split(",", 1)[1]
|
||||||
|
|
||||||
local_image_path = f"temp_fb_{uuid.uuid4().hex}.jpg"
|
local_image_path = f"temp_fb_{uuid.uuid4().hex}.jpg"
|
||||||
urllib.request.urlretrieve(str(req.image_url), local_image_path)
|
with open(local_image_path, "wb") as f:
|
||||||
logging.info(f"Đã tải ảnh tạm thời: {local_image_path}")
|
f.write(base64.b64decode(b64_data))
|
||||||
|
logging.info(f"Đã tạo ảnh từ chuỗi Base64: {local_image_path}")
|
||||||
|
|
||||||
|
elif req.image_url:
|
||||||
|
import re
|
||||||
|
url = str(req.image_url)
|
||||||
|
|
||||||
|
# Kiểm tra xem url có phải là một đường dẫn file nội bộ trên máy hay không
|
||||||
|
if os.path.exists(url):
|
||||||
|
local_image_path = url
|
||||||
|
logging.info(f"Sử dụng file ảnh nội bộ có sẵn: {local_image_path}")
|
||||||
|
else:
|
||||||
|
# Tự động chuyển link Google Drive sang link tải trực tiếp
|
||||||
|
if "drive.google.com" in url:
|
||||||
|
file_id_match = re.search(r"/d/([a-zA-Z0-9_-]+)", url)
|
||||||
|
if file_id_match:
|
||||||
|
file_id = file_id_match.group(1)
|
||||||
|
url = f"https://drive.google.com/uc?export=download&id={file_id}"
|
||||||
|
logging.info(f"Đã convert link Google Drive thành direct link: {url}")
|
||||||
|
|
||||||
|
# Tải ảnh về máy chủ Python tạm thời
|
||||||
|
local_image_path = f"temp_fb_{uuid.uuid4().hex}.jpg"
|
||||||
|
urllib.request.urlretrieve(url, local_image_path)
|
||||||
|
logging.info(f"Đã tải ảnh tạm thời từ internet: {local_image_path}")
|
||||||
|
|
||||||
result = bot.post_comment(str(req.group_id), str(req.content), local_image_path)
|
result = bot.post_comment(str(req.group_id), str(req.content), local_image_path)
|
||||||
|
|
||||||
# Dọn dẹp ảnh tạm sau khi xong
|
# Dọn dẹp ảnh tạm sau khi xong
|
||||||
if local_image_path and os.path.exists(local_image_path):
|
if local_image_path and os.path.exists(local_image_path):
|
||||||
os.remove(local_image_path)
|
if "temp_fb_" in local_image_path:
|
||||||
logging.info(f"Đã xóa ảnh tạm: {local_image_path}")
|
os.remove(local_image_path)
|
||||||
|
logging.info(f"Đã dọn dẹp file tạm: {local_image_path}")
|
||||||
|
|
||||||
if isinstance(result, dict) and "status" in result:
|
if isinstance(result, dict) and "status" in result:
|
||||||
# Trả về luôn JSON kết quả, n8n sẽ nhận HTTP 200 và tiếp tục vòng lặp
|
# Trả về luôn JSON kết quả, n8n sẽ nhận HTTP 200 và tiếp tục vòng lặp
|
||||||
|
|||||||
Reference in New Issue
Block a user