-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathmain.py
More file actions
216 lines (170 loc) · 7.1 KB
/
Copy pathmain.py
File metadata and controls
216 lines (170 loc) · 7.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
"""
Automation Bot for Threads (Meta) and Shopee Affiliate
Session-First Architecture:
- NO automatic login retries
- Uses pre-authenticated session cookies
- Validates session before use
- Stops if session is expired (no retry)
This eliminates the login loop problem caused by trust-layer rejection.
"""
import logging
import os
import sys
from dotenv import load_dotenv
from services.session_manager import SessionManager, ThreadsAuth, SessionStatus
from services.feed_explorer import FeedExplorer
from services.network_discovery import NetworkDiscovery
# Load environment variables
load_dotenv()
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
BANNER = """
╔══════════════════════════════════════════════════════════════╗
║ Threads & Shopee Affiliate Automation Bot ║
║ ║
║ Session-First Architecture (no auto login) ║
╚══════════════════════════════════════════════════════════════╝
"""
def initialize_session() -> tuple[bool, SessionManager | None]:
"""
Initialize session using SessionManager.
Flow:
1. Load session from env/file
2. Validate session
3. If valid → return session manager
4. If expired → STOP
5. If rate_limited/unknown → preserve session, continue with warning
Returns:
(success, session_manager)
"""
logger.info("=" * 60)
logger.info("INITIALIZING SESSION")
logger.info("=" * 60)
# Create session manager
session_manager = SessionManager()
# Step 1: Load session
logger.info("\n[Step 1] Loading session from env/file...")
if not session_manager.load_session():
return False, None
# Step 2: Validate session
logger.info("\n[Step 2] Validating session...")
result = session_manager.validate_session()
if result.status == SessionStatus.VALID:
logger.info(f"[SESSION] VALID")
logger.info(f" Status: {result.status.value}")
logger.info(f" User ID: {result.user_id or 'N/A'}")
return True, session_manager
elif result.status == SessionStatus.EXPIRED:
# Session explicitly expired - STOP
logger.error(f"[SESSION] EXPIRED: {result.reason}")
return False, None
elif result.status == SessionStatus.RATE_LIMITED:
# Rate limited - DO NOT STOP, preserve session
logger.warning(f"[SESSION] RATE LIMITED: {result.reason}")
logger.warning("[SESSION] Session preserved - will retry later")
if result.retry_after:
logger.warning(f"[SESSION] Retry-After: {result.retry_after}s")
# Continue with session (may work for non-validation requests)
return True, session_manager
elif result.status == SessionStatus.UNKNOWN:
# Unknown state - preserve session
logger.warning(f"[SESSION] UNKNOWN: {result.reason}")
logger.warning("[SESSION] Session preserved - proceeding with caution")
return True, session_manager
else:
# Other invalid states
logger.error(f"[SESSION] {result.status.value}: {result.reason}")
return False, None
def run_automation(session_manager: SessionManager):
"""
Run automation tasks with valid session.
Uses Playwright to capture browser network traffic for endpoint discovery.
Args:
session_manager: Validated SessionManager instance
"""
logger.info("\n" + "=" * 60)
logger.info("RUNNING AUTOMATION")
logger.info("=" * 60)
# Get authenticated session cookies
cookies = session_manager.get_cookies()
if not cookies:
logger.error("Failed to get session cookies")
return False
logger.info(f"[✓] Authenticated session ready with {len(cookies)} cookies")
# Run Network Discovery with Playwright
logger.info("\n[*] Running Playwright Network Discovery...")
logger.info("[*] This captures ALL browser network traffic (30s capture)")
try:
discovery = NetworkDiscovery(cookies)
discovery.capture(duration_seconds=30)
# Save results
logger.info("\n[*] Saving discovery results...")
discovery.save_results(
network_file="network_capture.json",
feed_file="feed_candidates.json",
graphql_file="graphql_candidates.json"
)
# Generate report
logger.info("\n[*] Generating discovery report...")
report = discovery.generate_report("NETWORK_DISCOVERY_REPORT.md")
# Print summary
discovery.print_summary(report)
logger.info("\n[✓] Network discovery complete!")
logger.info("[*] Files generated:")
logger.info(" - network_capture.json")
logger.info(" - feed_candidates.json")
logger.info(" - graphql_candidates.json")
logger.info(" - NETWORK_DISCOVERY_REPORT.md")
except Exception as e:
logger.error(f"[!] Network discovery failed: {e}")
import traceback
traceback.print_exc()
return False
return True
def main():
"""Main entry point for the automation bot."""
print(BANNER)
try:
# Initialize session (NO AUTO LOGIN)
success, session_manager = initialize_session()
if not success:
# Session invalid - show manual refresh instructions
print("\n" + "=" * 60)
print("🚫 SESSION EXPIRED")
print("=" * 60)
print("\nTo refresh your session:")
print(" 1. Open browser to https://www.instagram.com")
print(" 2. Login and complete any verification (2FA, email)")
print(" 3. Press F12 → Application → Cookies → instagram.com")
print(" 4. Copy these cookies to .env:")
print(" - sessionid")
print(" - csrftoken")
print(" - ds_user_id")
print(" - mid")
print(" - ig_did")
print(" 5. Run this script again")
print("=" * 60 + "\n")
return 1
# Session valid - run automation
threads_success = run_automation(session_manager)
# Summary
logger.info("\n" + "=" * 60)
logger.info("SUMMARY")
logger.info("=" * 60)
logger.info(f"Threads Session: {'✓ PASS' if threads_success else '✗ FAIL'}")
logger.info("=" * 60)
if threads_success:
logger.info("All tests passed!")
return 0
else:
logger.warning("Some tests failed. Check logs for details.")
return 1
except Exception as e:
logger.exception(f"Unexpected error: {e}")
return 1
if __name__ == "__main__":
sys.exit(main())