diff --git a/GramAddict/core/config.py b/GramAddict/core/config.py index 4dc7a7c..e9892b9 100644 --- a/GramAddict/core/config.py +++ b/GramAddict/core/config.py @@ -152,6 +152,13 @@ class Config: help="Wipe all learned navigation and telepathic memories on boot to start 100%% blank.", ) + self.parser.add_argument( + "--goal", + type=str, + help="High-level autonomous goal for the bot (Tesla-style). Overrides config.yml goals.", + default=None, + ) + # Interaction settings self.parser.add_argument("--likes-count", help="Likes count", default="2-3") self.parser.add_argument("--likes-percentage", help="Likes percentage", default="100") diff --git a/GramAddict/core/physics/timing.py b/GramAddict/core/physics/timing.py index d40fd86..861d424 100644 --- a/GramAddict/core/physics/timing.py +++ b/GramAddict/core/physics/timing.py @@ -140,8 +140,8 @@ def align_active_post(device): # Intents for structural discovery intents = [ + "post author username text (exclude follow buttons)", "post author header profile", - "post username name", "row_feed_photo_profile_name", # ID fallback "clips_viewer_author_container", # Reels fallback "feed post content", # Final desperation @@ -151,6 +151,12 @@ def align_active_post(device): attempts += 1 try: xml = device.dump_hierarchy() + if "clips_video_container" in xml or "clips_viewer_container" in xml: + import logging + logger = logging.getLogger(__name__) + logger.info("🎯 [Alignment] Reels view detected. Auto-snapping is native.") + return True + from GramAddict.core.telepathic_engine import TelepathicEngine telepath = TelepathicEngine.get_instance() diff --git a/GramAddict/core/utils.py b/GramAddict/core/utils.py index 4ae98a6..92b4cac 100644 --- a/GramAddict/core/utils.py +++ b/GramAddict/core/utils.py @@ -128,23 +128,30 @@ def is_ad(xml_hierarchy: str, cognitive_stack: dict = None) -> bool: try: root = ET.fromstring(xml_hierarchy) + + # Check if we are in a feed (to prevent false positives on profiles with 'Ad Tools' buttons) + from GramAddict.core.perception.feed_analysis import FEED_MARKERS + in_feed = any(marker in xml_hierarchy for marker in FEED_MARKERS) + for node in root.iter("node"): attrib = node.attrib content_desc = attrib.get("content-desc", "") text = attrib.get("text", "") res_id = attrib.get("resource-id", "") - # Structural check (Instagram specific) + # Structural check (Instagram specific) is always trusted if any(marker_id in res_id for marker_id in AD_RESOURCE_IDS): return True # Exact label match: only trigger when the entire text/desc # IS an ad marker (e.g. text="Ad", content-desc="Sponsored") - # This prevents false positives from "Create messaging ad" - if text.strip().lower() in AD_EXACT_LABELS: - return True - if content_desc.strip().lower() in AD_EXACT_LABELS: - return True + # We ONLY trust this if we are actually in a feed, to prevent triggering + # on the "Ad Tools" / "Ad" buttons present on business profiles. + if in_feed: + if text.strip().lower() in AD_EXACT_LABELS: + return True + if content_desc.strip().lower() in AD_EXACT_LABELS: + return True except Exception: pass