fix: support cookie-based auth, direct login often blocked by Instagram

- Try instaloader session file first
- Then cookies.txt (Mozilla format from browser extension)
- Then cookies.json (from browser extensions)
- Direct login as last resort with clear instructions
This commit is contained in:
2026-06-17 11:37:53 +07:00
parent 6c51413d12
commit b1aa0eb6f5

View File

@@ -1,3 +1,4 @@
import http.cookiejar
import json
import os
import shutil
@@ -40,19 +41,72 @@ class InstagramMonitor:
json.dump(self._state, f, indent=2)
def login(self) -> bool:
try:
if self._session_path.exists():
# Method 1: load existing instaloader session file
if self._session_path.exists():
try:
self.loader.load_session_from_file(config.instagram_username, str(self._session_path))
logger.info("Session loaded from file")
logger.info("Session loaded from instaloader session file")
return True
except Exception as e:
logger.warning(f"Session file invalid: {e}")
self.loader.login(config.instagram_username, config.instagram_password)
self.loader.save_session_to_file(str(self._session_path))
logger.info("Logged in and session saved")
return True
except Exception as e:
logger.error(f"Login failed: {e}")
return False
# Method 2: load cookies.txt exported from browser
cookies_path = Path(config.download_dir) / "cookies.txt"
if cookies_path.exists():
try:
self._load_cookies_from_txt(cookies_path)
logger.info("Session loaded from cookies.txt")
return True
except Exception as e:
logger.warning(f"cookies.txt invalid: {e}")
# Method 3: load cookies.json exported from browser extension
cookies_json_path = Path(config.download_dir) / "cookies.json"
if cookies_json_path.exists():
try:
self._load_cookies_from_json(cookies_json_path)
logger.info("Session loaded from cookies.json")
return True
except Exception as e:
logger.warning(f"cookies.json invalid: {e}")
# Method 4: direct login (often blocked by Instagram now)
if config.instagram_password:
try:
self.loader.login(config.instagram_username, config.instagram_password)
self.loader.save_session_to_file(str(self._session_path))
logger.info("Logged in via direct login and session saved")
return True
except Exception as e:
logger.error(f"Direct login failed: {e}")
logger.info(
"Use cookies.txt or cookies.json instead. "
"Export from browser: install 'Get cookies.txt LOCALLY' extension, "
"go to instagram.com, export, put file in /data/downloads/cookies.txt"
)
return False
logger.error("No valid session or credentials found")
return False
def _load_cookies_from_txt(self, path: Path) -> None:
cj = http.cookiejar.MozillaCookieJar(str(path))
cj.load(ignore_discard=True, ignore_expires=True)
self.loader.context._session.cookies.update(cj)
# Verify session works
instaloader.Profile.from_username(self.loader.context, config.instagram_username)
def _load_cookies_from_json(self, path: Path) -> None:
with open(path) as f:
cookies = json.load(f)
for cookie in cookies:
self.loader.context._session.cookies.set(
cookie["name"],
cookie["value"],
domain=cookie.get("domain", ".instagram.com"),
path=cookie.get("path", "/"),
)
instaloader.Profile.from_username(self.loader.context, config.instagram_username)
def _get_profile_posts(self, username: str) -> list[instaloader.Post]:
try: