Initial commit with extractor project files
This commit is contained in:
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"python-envs.defaultEnvManager": "ms-python.python:system"
|
||||||
|
}
|
||||||
Executable
+1
@@ -0,0 +1 @@
|
|||||||
|
<!doctype html><html><head><title>DDoS-Guard</title><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><link rel="stylesheet" href="/.well-known/ddos-guard/js-challenge/index.css"><script defer="defer" src="/.well-known/ddos-guard/js-challenge/view.js"></script><script defer="defer" src="/.well-known/ddos-guard/js-challenge/index.js"></script><script src="https://check.ddos-guard.net/check.js"></script></head><body data-ddg-origin="true" data-ddg-l10n="true"><div class="container"><div class="top"><h1 id="ddg-l10n-title">Checking your browser before accessing <span class="ddg-origin"></span></h1><p id="ddg-l10n-description">Please wait a few seconds. Once this check is complete, the website will open automatically</p><img id="ddg-img-loading" src="" alt="loading"/></div><div class="bottom"><span id="request-info"></span></div></div></body></html>
|
||||||
Executable
+366
@@ -0,0 +1,366 @@
|
|||||||
|
import re
|
||||||
|
import cloudscraper # Changed from requests
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
from urllib.parse import urlparse, urljoin
|
||||||
|
|
||||||
|
class SimPCityExtractor:
|
||||||
|
def __init__(self, cookies=None):
|
||||||
|
# Use cloudscraper instead of requests.Session()
|
||||||
|
self.session = cloudscraper.create_scraper(
|
||||||
|
browser={
|
||||||
|
'browser': 'chrome',
|
||||||
|
'platform': 'windows',
|
||||||
|
'desktop': True
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Optional: Add any custom headers (cloudscraper handles most automatically)
|
||||||
|
self.session.headers.update({
|
||||||
|
'Accept-Language': 'en-US,en;q=0.9',
|
||||||
|
})
|
||||||
|
|
||||||
|
if cookies:
|
||||||
|
for name, value in cookies.items():
|
||||||
|
self.session.cookies.set(name, value, domain='.simpcity.cr')
|
||||||
|
print("Cookies loaded for authenticated session.")
|
||||||
|
print(f"Total cookies loaded: {len(cookies)}")
|
||||||
|
|
||||||
|
# Test the session
|
||||||
|
self._test_session()
|
||||||
|
|
||||||
|
def _test_session(self):
|
||||||
|
"""Test if the session is properly authenticated"""
|
||||||
|
try:
|
||||||
|
print("\nTesting session authentication...")
|
||||||
|
test_url = "https://simpcity.cr/"
|
||||||
|
response = self.session.get(test_url, timeout=30, allow_redirects=True)
|
||||||
|
|
||||||
|
print(f"Status Code: {response.status_code}")
|
||||||
|
print(f"Final URL: {response.url}")
|
||||||
|
|
||||||
|
if response.status_code == 403:
|
||||||
|
print("\n⚠ WARNING: Still receiving 403 Forbidden even with cloudscraper")
|
||||||
|
print("This suggests:")
|
||||||
|
print("1. Your cookies are definitely expired/invalid")
|
||||||
|
print("2. Your IP may be blocked")
|
||||||
|
print("3. The site requires CAPTCHA solving")
|
||||||
|
|
||||||
|
# Check for specific protection
|
||||||
|
if 'cloudflare' in response.text.lower() or 'cf-ray' in response.headers:
|
||||||
|
print("→ Cloudflare challenge page detected")
|
||||||
|
print(" Cloudscraper may need a delay or the challenge is too advanced")
|
||||||
|
|
||||||
|
if 'captcha' in response.text.lower():
|
||||||
|
print("→ CAPTCHA detected - cloudscraper cannot solve CAPTCHAs")
|
||||||
|
print(" You'll need to use Selenium with CAPTCHA solving service")
|
||||||
|
|
||||||
|
# Save response for debugging
|
||||||
|
with open('403_response_cloudscraper.html', 'w', encoding='utf-8') as f:
|
||||||
|
f.write(response.text)
|
||||||
|
print("→ Saved response to '403_response_cloudscraper.html'")
|
||||||
|
|
||||||
|
elif response.status_code == 200:
|
||||||
|
if 'login' in response.url.lower():
|
||||||
|
print("⚠ Redirected to login page - cookies are invalid or expired")
|
||||||
|
print(" Export fresh cookies from your browser")
|
||||||
|
else:
|
||||||
|
print("✓ Cloudscraper successfully bypassed protection!")
|
||||||
|
|
||||||
|
# Check if logged in
|
||||||
|
if 'logout' in response.text.lower() or 'account' in response.text.lower():
|
||||||
|
print("✓ Authentication confirmed - you're logged in")
|
||||||
|
else:
|
||||||
|
print("⚠ Not logged in - update your cookies")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ Error testing session: {e}")
|
||||||
|
|
||||||
|
def get_thread_pages(self, base_url, max_pages=50):
|
||||||
|
"""Discover all pages in a thread by scanning links containing '/page-'."""
|
||||||
|
pages = []
|
||||||
|
try:
|
||||||
|
print(f"\nDiscovering pages for thread: {base_url}")
|
||||||
|
|
||||||
|
response = self.session.get(base_url, timeout=30, allow_redirects=True)
|
||||||
|
|
||||||
|
print(f"Status: {response.status_code}, URL: {response.url}")
|
||||||
|
|
||||||
|
if response.status_code == 403:
|
||||||
|
print("\n✗ 403 Forbidden - Cannot access thread")
|
||||||
|
print("Even with cloudscraper, getting 403. This means:")
|
||||||
|
print("1. Cookies are expired - export fresh ones")
|
||||||
|
print("2. IP is blocked - try different IP/VPN")
|
||||||
|
print("3. CAPTCHA required - need Selenium solution")
|
||||||
|
|
||||||
|
with open('thread_403_cloudscraper.html', 'w', encoding='utf-8') as f:
|
||||||
|
f.write(response.text)
|
||||||
|
print("→ Saved response to 'thread_403_cloudscraper.html'")
|
||||||
|
return pages
|
||||||
|
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
soup = BeautifulSoup(response.text, 'html.parser')
|
||||||
|
page_links = soup.find_all('a', href=True)
|
||||||
|
|
||||||
|
page_numbers = set()
|
||||||
|
for link in page_links:
|
||||||
|
href = link['href']
|
||||||
|
match = re.search(r'/page-(\d+)', href)
|
||||||
|
if match:
|
||||||
|
page_numbers.add(int(match.group(1)))
|
||||||
|
|
||||||
|
if page_numbers:
|
||||||
|
max_page = min(max(page_numbers), max_pages)
|
||||||
|
print(f"Found {max_page} pages in thread")
|
||||||
|
pages.append(base_url)
|
||||||
|
for page_num in range(2, max_page + 1):
|
||||||
|
if base_url.endswith('/'):
|
||||||
|
pages.append(f"{base_url}page-{page_num}")
|
||||||
|
else:
|
||||||
|
pages.append(f"{base_url}/page-{page_num}")
|
||||||
|
else:
|
||||||
|
print("No pagination found, defaulting to single page")
|
||||||
|
pages.append(base_url)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error discovering pages: {e}")
|
||||||
|
if pages:
|
||||||
|
return pages
|
||||||
|
pages.append(base_url)
|
||||||
|
|
||||||
|
return pages
|
||||||
|
|
||||||
|
def fetch_all_pages_to_file(self, page_urls, output_file):
|
||||||
|
"""Fetch all thread pages and append them into a single HTML file."""
|
||||||
|
if not page_urls:
|
||||||
|
print("No pages to fetch")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"\nSaving all pages into: {output_file}")
|
||||||
|
|
||||||
|
successful_pages = 0
|
||||||
|
with open(output_file, 'w', encoding='utf-8') as out_file:
|
||||||
|
for i, url in enumerate(page_urls, 1):
|
||||||
|
print(f"\nFetching page {i}/{len(page_urls)}: {url}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = self.session.get(url, timeout=30, allow_redirects=True)
|
||||||
|
|
||||||
|
print(f" Status: {response.status_code}")
|
||||||
|
|
||||||
|
if response.status_code == 403:
|
||||||
|
print(f" ✗ 403 Forbidden on page {i}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
if 'login' in response.url.lower():
|
||||||
|
print(" ✗ Redirected to login page")
|
||||||
|
continue
|
||||||
|
|
||||||
|
out_file.write(f"\n<!-- PAGE {i}: {url} -->\n")
|
||||||
|
out_file.write(response.text + "\n\n")
|
||||||
|
successful_pages += 1
|
||||||
|
print(f" ✓ Successfully saved page {i}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Error fetching page {i}: {e}")
|
||||||
|
|
||||||
|
# Be polite with delays
|
||||||
|
if i < len(page_urls):
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
print(f"\n✓ Successfully saved {successful_pages}/{len(page_urls)} pages")
|
||||||
|
|
||||||
|
def resolve_turbovid(self, url):
|
||||||
|
"""Resolve Turbovid URLs using their sign API endpoint."""
|
||||||
|
try:
|
||||||
|
match = re.search(r'/(v|d|embed)/([a-zA-Z0-9]+)', url)
|
||||||
|
if not match:
|
||||||
|
print(f" ✗ Could not extract video ID from: {url}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
video_id = match.group(2)
|
||||||
|
print(f" Resolving Turbovid ID: {video_id}")
|
||||||
|
|
||||||
|
embed_url = f"https://turbo.cr/embed/{video_id}"
|
||||||
|
|
||||||
|
sign_urls = [
|
||||||
|
f"https://turbo.cr/api/sign?v={video_id}",
|
||||||
|
f"https://turbo.cr/sign?v={video_id}",
|
||||||
|
]
|
||||||
|
|
||||||
|
for sign_url in sign_urls:
|
||||||
|
try:
|
||||||
|
response = self.session.get(
|
||||||
|
sign_url,
|
||||||
|
headers={'Referer': embed_url},
|
||||||
|
timeout=30
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
if data.get('success') and data.get('url'):
|
||||||
|
signed_url = data['url']
|
||||||
|
|
||||||
|
original_name = data.get('original_filename')
|
||||||
|
if original_name and 'fn=' not in signed_url:
|
||||||
|
delimiter = '&' if '?' in signed_url else '?'
|
||||||
|
signed_url += f"{delimiter}fn={original_name}"
|
||||||
|
|
||||||
|
print(f" ✓ Resolved to: {signed_url[:80]}...")
|
||||||
|
return signed_url
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = self.session.get(embed_url, headers={'Referer': embed_url}, timeout=30)
|
||||||
|
soup = BeautifulSoup(response.text, 'html.parser')
|
||||||
|
|
||||||
|
source_tag = soup.find('source', src=True)
|
||||||
|
if source_tag:
|
||||||
|
return source_tag['src']
|
||||||
|
|
||||||
|
video_tag = soup.find('video', src=True)
|
||||||
|
if video_tag:
|
||||||
|
return video_tag['src']
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Error resolving Turbovid: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Rest of the functions remain the same...
|
||||||
|
def extract_links(file_path, resolve_turbovid=False, extractor=None):
|
||||||
|
"""Extract links from an HTML file using regex."""
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
print(f"File not found: {file_path}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
html = f.read()
|
||||||
|
|
||||||
|
if len(html) < 1000 and '403' in html:
|
||||||
|
print("⚠ Warning: HTML file appears to contain 403 error page")
|
||||||
|
return []
|
||||||
|
|
||||||
|
patterns = [
|
||||||
|
r'https?://\S*bunkr\.\S*',
|
||||||
|
r'https?://[a-zA-Z0-9\-]+\.jpg5\.su/images3/[^\s"\'<>]+?\.md\.jpg',
|
||||||
|
r'https?://jpg6\.su/img/[a-zA-Z0-9]+',
|
||||||
|
r'https?://jpg6\.su/a/[^\s"\'<>]+',
|
||||||
|
r'https?://saint2\.cr/embed/[a-zA-Z0-9]+',
|
||||||
|
r'https?://(?:www\.)?redgifs\.com/watch/[a-zA-Z0-9]+',
|
||||||
|
r'//redgifs\.com/ifr/[a-zA-Z0-9]+',
|
||||||
|
r'https?://gofile\.io/d/[a-zA-Z0-9]+',
|
||||||
|
r'https?://pixeldrain\.com/u/[a-zA-Z0-9]+',
|
||||||
|
r'https?://cyberdrop\.me/a/[a-zA-Z0-9]+',
|
||||||
|
r'https?://cyberdrop\.cr/f/[a-zA-Z0-9]+',
|
||||||
|
r'https?://(?:[\w-]+\.)?turbo(?:vid)?\.cr/(?:v|d|embed)/[a-zA-Z0-9]+',
|
||||||
|
r'https?://goonbox\.cr/img/[a-zA-Z0-9]+',
|
||||||
|
r'https?://goonbox\.ce/a/[^\s"\'<>]+',
|
||||||
|
]
|
||||||
|
|
||||||
|
clean_links = []
|
||||||
|
for pattern in patterns:
|
||||||
|
matches = re.findall(pattern, html)
|
||||||
|
for match in matches:
|
||||||
|
clean_link = match.strip().rstrip('"\'<>')
|
||||||
|
clean_links.append(clean_link)
|
||||||
|
|
||||||
|
unique_links = list(set(clean_links))
|
||||||
|
print(f"\nFound {len(unique_links)} unique links total")
|
||||||
|
|
||||||
|
if resolve_turbovid and extractor:
|
||||||
|
print("\n--- Resolving Turbovid Links ---")
|
||||||
|
resolved_links = []
|
||||||
|
turbovid_count = 0
|
||||||
|
failed_count = 0
|
||||||
|
for link in unique_links:
|
||||||
|
if 'turbo' in link.lower() and '.cr' in link.lower():
|
||||||
|
turbovid_count += 1
|
||||||
|
print(f"\nProcessing Turbovid link {turbovid_count}: {link}")
|
||||||
|
resolved = extractor.resolve_turbovid(link)
|
||||||
|
if resolved:
|
||||||
|
resolved_links.append(resolved)
|
||||||
|
else:
|
||||||
|
failed_count += 1
|
||||||
|
time.sleep(1)
|
||||||
|
else:
|
||||||
|
resolved_links.append(link)
|
||||||
|
print(f"\nResolved {turbovid_count - failed_count}/{turbovid_count} Turbovid links")
|
||||||
|
if failed_count > 0:
|
||||||
|
print(f"Failed: {failed_count} Turbovid link(s)")
|
||||||
|
return resolved_links
|
||||||
|
|
||||||
|
return unique_links
|
||||||
|
|
||||||
|
def save_links_to_file(links, output_file):
|
||||||
|
if not links:
|
||||||
|
print("No links found to save.")
|
||||||
|
return
|
||||||
|
|
||||||
|
existing = set()
|
||||||
|
if os.path.exists(output_file):
|
||||||
|
with open(output_file, 'r', encoding='utf-8') as f:
|
||||||
|
existing = set(line.strip() for line in f if line.strip())
|
||||||
|
|
||||||
|
new_links = [l for l in links if l not in existing]
|
||||||
|
|
||||||
|
if not new_links:
|
||||||
|
print("No new unique links found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(output_file, 'a', encoding='utf-8') as f:
|
||||||
|
for link in new_links:
|
||||||
|
f.write(link + "\n")
|
||||||
|
|
||||||
|
print(f"✓ Saved {len(new_links)} new links to {output_file}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("="*70)
|
||||||
|
print("SimPCity Link Extractor - Cloudscraper Version")
|
||||||
|
print("="*70)
|
||||||
|
print("\nMake sure you have cloudscraper installed:")
|
||||||
|
print(" pip install cloudscraper\n")
|
||||||
|
|
||||||
|
base_thread_url = "https://simpcity.cr/threads/haileyybrown.50455/"
|
||||||
|
output_html = "page_source.html"
|
||||||
|
output_links = "links.txt"
|
||||||
|
|
||||||
|
# CRITICAL: Export FRESH cookies from your browser while logged in
|
||||||
|
cookies = {
|
||||||
|
"__ddg1_": "ztu3bAWXt1yNTQLx4anD",
|
||||||
|
"__ddg2_": "XITPIP1OKNx5qhiT",
|
||||||
|
"__ddg8_": "oWldvDW5w2JAjymf",
|
||||||
|
"__ddg9_": "217.138.213.52",
|
||||||
|
"__ddg10_": "1781612477",
|
||||||
|
"__ddgid_": "yhSli2A9nG5Xkwcu",
|
||||||
|
"__ddgmark_": "pVXsbrKqDemwPHiu",
|
||||||
|
"oMased": "b4",
|
||||||
|
"oMasid": "9e19ba410603e03b1286baca7c2917ef56b9c760415db5e2b9574c87eb092e7e",
|
||||||
|
"ogaddgmetaprof_csrf": "",
|
||||||
|
"yMziCv8BrCZz1o7_csrf": "vGZEMX5-P-XSKuG_",
|
||||||
|
"yMziCv8BrCZz1o7_session": "upTVlbK2kspfKlRGyD74rOh_PacNF7DI",
|
||||||
|
"yMziCv8BrCZz1o7_user": "3944332%2Cr8xH2AcnE_hg0kkeNSSsi3luzSkW6odfKX21CHdk",
|
||||||
|
"yMziCv8BrCZz1o7_dbWriteForced": "1781612424"
|
||||||
|
}
|
||||||
|
|
||||||
|
extractor = SimPCityExtractor(cookies=cookies)
|
||||||
|
pages = extractor.get_thread_pages(base_thread_url)
|
||||||
|
|
||||||
|
if pages:
|
||||||
|
extractor.fetch_all_pages_to_file(pages, output_html)
|
||||||
|
links = extract_links(output_html, resolve_turbovid=True, extractor=extractor)
|
||||||
|
save_links_to_file(links, output_links)
|
||||||
|
print("\n" + "="*70)
|
||||||
|
print("Process completed!")
|
||||||
Executable
+370
@@ -0,0 +1,370 @@
|
|||||||
|
import re
|
||||||
|
import cloudscraper # Changed from requests
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
from urllib.parse import urlparse, urljoin
|
||||||
|
|
||||||
|
class SimPCityExtractor:
|
||||||
|
def __init__(self, cookies=None):
|
||||||
|
# Use cloudscraper instead of requests.Session()
|
||||||
|
self.session = cloudscraper.create_scraper(
|
||||||
|
browser={
|
||||||
|
'browser': 'chrome',
|
||||||
|
'platform': 'windows',
|
||||||
|
'desktop': True
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Optional: Add any custom headers (cloudscraper handles most automatically)
|
||||||
|
self.session.headers.update({
|
||||||
|
'Accept-Language': 'en-US,en;q=0.9',
|
||||||
|
})
|
||||||
|
|
||||||
|
if cookies:
|
||||||
|
for name, value in cookies.items():
|
||||||
|
self.session.cookies.set(name, value, domain='.f95zone.to')
|
||||||
|
print("Cookies loaded for authenticated session.")
|
||||||
|
print(f"Total cookies loaded: {len(cookies)}")
|
||||||
|
|
||||||
|
# Test the session
|
||||||
|
self._test_session()
|
||||||
|
|
||||||
|
def _test_session(self):
|
||||||
|
"""Test if the session is properly authenticated"""
|
||||||
|
try:
|
||||||
|
print("\nTesting session authentication...")
|
||||||
|
test_url = "https://f95zone.to/"
|
||||||
|
response = self.session.get(test_url, timeout=30, allow_redirects=True)
|
||||||
|
|
||||||
|
print(f"Status Code: {response.status_code}")
|
||||||
|
print(f"Final URL: {response.url}")
|
||||||
|
|
||||||
|
if response.status_code == 403:
|
||||||
|
print("\n⚠ WARNING: Still receiving 403 Forbidden even with cloudscraper")
|
||||||
|
print("This suggests:")
|
||||||
|
print("1. Your cookies are definitely expired/invalid")
|
||||||
|
print("2. Your IP may be blocked")
|
||||||
|
print("3. The site requires CAPTCHA solving")
|
||||||
|
|
||||||
|
# Check for specific protection
|
||||||
|
if 'cloudflare' in response.text.lower() or 'cf-ray' in response.headers:
|
||||||
|
print("→ Cloudflare challenge page detected")
|
||||||
|
print(" Cloudscraper may need a delay or the challenge is too advanced")
|
||||||
|
|
||||||
|
if 'captcha' in response.text.lower():
|
||||||
|
print("→ CAPTCHA detected - cloudscraper cannot solve CAPTCHAs")
|
||||||
|
print(" You'll need to use Selenium with CAPTCHA solving service")
|
||||||
|
|
||||||
|
# Save response for debugging
|
||||||
|
with open('403_response_cloudscraper.html', 'w', encoding='utf-8') as f:
|
||||||
|
f.write(response.text)
|
||||||
|
print("→ Saved response to '403_response_cloudscraper.html'")
|
||||||
|
|
||||||
|
elif response.status_code == 200:
|
||||||
|
if 'login' in response.url.lower():
|
||||||
|
print("⚠ Redirected to login page - cookies are invalid or expired")
|
||||||
|
print(" Export fresh cookies from your browser")
|
||||||
|
else:
|
||||||
|
print("✓ Cloudscraper successfully bypassed protection!")
|
||||||
|
|
||||||
|
# Check if logged in
|
||||||
|
if 'logout' in response.text.lower() or 'account' in response.text.lower():
|
||||||
|
print("✓ Authentication confirmed - you're logged in")
|
||||||
|
else:
|
||||||
|
print("⚠ Not logged in - update your cookies")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ Error testing session: {e}")
|
||||||
|
|
||||||
|
def get_thread_pages(self, base_url, max_pages=50):
|
||||||
|
"""Discover all pages in a thread by scanning links containing '/page-'."""
|
||||||
|
pages = []
|
||||||
|
try:
|
||||||
|
print(f"\nDiscovering pages for thread: {base_url}")
|
||||||
|
|
||||||
|
response = self.session.get(base_url, timeout=30, allow_redirects=True)
|
||||||
|
|
||||||
|
print(f"Status: {response.status_code}, URL: {response.url}")
|
||||||
|
|
||||||
|
if response.status_code == 403:
|
||||||
|
print("\n✗ 403 Forbidden - Cannot access thread")
|
||||||
|
print("Even with cloudscraper, getting 403. This means:")
|
||||||
|
print("1. Cookies are expired - export fresh ones")
|
||||||
|
print("2. IP is blocked - try different IP/VPN")
|
||||||
|
print("3. CAPTCHA required - need Selenium solution")
|
||||||
|
|
||||||
|
with open('thread_403_cloudscraper.html', 'w', encoding='utf-8') as f:
|
||||||
|
f.write(response.text)
|
||||||
|
print("→ Saved response to 'thread_403_cloudscraper.html'")
|
||||||
|
return pages
|
||||||
|
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
soup = BeautifulSoup(response.text, 'html.parser')
|
||||||
|
page_links = soup.find_all('a', href=True)
|
||||||
|
|
||||||
|
page_numbers = set()
|
||||||
|
for link in page_links:
|
||||||
|
href = link['href']
|
||||||
|
match = re.search(r'/page-(\d+)', href)
|
||||||
|
if match:
|
||||||
|
page_numbers.add(int(match.group(1)))
|
||||||
|
|
||||||
|
if page_numbers:
|
||||||
|
max_page = min(max(page_numbers), max_pages)
|
||||||
|
print(f"Found {max_page} pages in thread")
|
||||||
|
pages.append(base_url)
|
||||||
|
for page_num in range(2, max_page + 1):
|
||||||
|
if base_url.endswith('/'):
|
||||||
|
pages.append(f"{base_url}page-{page_num}")
|
||||||
|
else:
|
||||||
|
pages.append(f"{base_url}/page-{page_num}")
|
||||||
|
else:
|
||||||
|
print("No pagination found, defaulting to single page")
|
||||||
|
pages.append(base_url)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error discovering pages: {e}")
|
||||||
|
if pages:
|
||||||
|
return pages
|
||||||
|
pages.append(base_url)
|
||||||
|
|
||||||
|
return pages
|
||||||
|
|
||||||
|
def fetch_all_pages_to_file(self, page_urls, output_file):
|
||||||
|
"""Fetch all thread pages and append them into a single HTML file."""
|
||||||
|
if not page_urls:
|
||||||
|
print("No pages to fetch")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"\nSaving all pages into: {output_file}")
|
||||||
|
|
||||||
|
successful_pages = 0
|
||||||
|
with open(output_file, 'w', encoding='utf-8') as out_file:
|
||||||
|
for i, url in enumerate(page_urls, 1):
|
||||||
|
print(f"\nFetching page {i}/{len(page_urls)}: {url}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = self.session.get(url, timeout=30, allow_redirects=True)
|
||||||
|
|
||||||
|
print(f" Status: {response.status_code}")
|
||||||
|
|
||||||
|
if response.status_code == 403:
|
||||||
|
print(f" ✗ 403 Forbidden on page {i}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
if 'login' in response.url.lower():
|
||||||
|
print(" ✗ Redirected to login page")
|
||||||
|
continue
|
||||||
|
|
||||||
|
out_file.write(f"\n<!-- PAGE {i}: {url} -->\n")
|
||||||
|
out_file.write(response.text + "\n\n")
|
||||||
|
successful_pages += 1
|
||||||
|
print(f" ✓ Successfully saved page {i}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Error fetching page {i}: {e}")
|
||||||
|
|
||||||
|
# Be polite with delays
|
||||||
|
if i < len(page_urls):
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
print(f"\n✓ Successfully saved {successful_pages}/{len(page_urls)} pages")
|
||||||
|
|
||||||
|
def resolve_turbovid(self, url):
|
||||||
|
"""Resolve Turbovid URLs using their sign API endpoint."""
|
||||||
|
try:
|
||||||
|
match = re.search(r'/(v|d|embed)/([a-zA-Z0-9]+)', url)
|
||||||
|
if not match:
|
||||||
|
print(f" ✗ Could not extract video ID from: {url}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
video_id = match.group(2)
|
||||||
|
print(f" Resolving Turbovid ID: {video_id}")
|
||||||
|
|
||||||
|
embed_url = f"https://turbo.cr/embed/{video_id}"
|
||||||
|
|
||||||
|
sign_urls = [
|
||||||
|
f"https://turbo.cr/api/sign?v={video_id}",
|
||||||
|
f"https://turbo.cr/sign?v={video_id}",
|
||||||
|
]
|
||||||
|
|
||||||
|
for sign_url in sign_urls:
|
||||||
|
try:
|
||||||
|
response = self.session.get(
|
||||||
|
sign_url,
|
||||||
|
headers={'Referer': embed_url},
|
||||||
|
timeout=30
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
if data.get('success') and data.get('url'):
|
||||||
|
signed_url = data['url']
|
||||||
|
|
||||||
|
original_name = data.get('original_filename')
|
||||||
|
if original_name and 'fn=' not in signed_url:
|
||||||
|
delimiter = '&' if '?' in signed_url else '?'
|
||||||
|
signed_url += f"{delimiter}fn={original_name}"
|
||||||
|
|
||||||
|
print(f" ✓ Resolved to: {signed_url[:80]}...")
|
||||||
|
return signed_url
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = self.session.get(embed_url, headers={'Referer': embed_url}, timeout=30)
|
||||||
|
soup = BeautifulSoup(response.text, 'html.parser')
|
||||||
|
|
||||||
|
source_tag = soup.find('source', src=True)
|
||||||
|
if source_tag:
|
||||||
|
return source_tag['src']
|
||||||
|
|
||||||
|
video_tag = soup.find('video', src=True)
|
||||||
|
if video_tag:
|
||||||
|
return video_tag['src']
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Error resolving Turbovid: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Rest of the functions remain the same...
|
||||||
|
def extract_links(file_path, resolve_turbovid=False, extractor=None):
|
||||||
|
"""Extract links from an HTML file using regex."""
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
print(f"File not found: {file_path}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
html = f.read()
|
||||||
|
|
||||||
|
if len(html) < 1000 and '403' in html:
|
||||||
|
print("⚠ Warning: HTML file appears to contain 403 error page")
|
||||||
|
return []
|
||||||
|
|
||||||
|
patterns = [
|
||||||
|
r'https?://\S*bunkr\.\S*',
|
||||||
|
r'https?://[a-zA-Z0-9\-]+\.jpg5\.su/images3/[^\s"\'<>]+?\.md\.jpg',
|
||||||
|
r'https?://jpg6\.su/img/[a-zA-Z0-9]+',
|
||||||
|
r'https?://jpg6\.su/a/[^\s"\'<>]+',
|
||||||
|
r'https?://saint2\.cr/embed/[a-zA-Z0-9]+',
|
||||||
|
r'https?://(?:www\.)?redgifs\.com/watch/[a-zA-Z0-9]+',
|
||||||
|
r'//redgifs\.com/ifr/[a-zA-Z0-9]+',
|
||||||
|
r'https?://gofile\.io/d/[a-zA-Z0-9]+',
|
||||||
|
r'https?://pixeldrain\.com/u/[a-zA-Z0-9]+',
|
||||||
|
r'https?://cyberdrop\.me/a/[a-zA-Z0-9]+',
|
||||||
|
r'https?://cyberdrop\.cr/f/[a-zA-Z0-9]+',
|
||||||
|
r'https?://(?:[\w-]+\.)?turbo(?:vid)?\.cr/(?:v|d|embed)/[a-zA-Z0-9]+',
|
||||||
|
r'https?://goonbox\.cr/img/[a-zA-Z0-9]+',
|
||||||
|
r'https?://goonbox\.ce/a/[^\s"\'<>]+',
|
||||||
|
r'https?://attachments\.f95zone\.to(?:/[a-zA-Z0-9]+)+'
|
||||||
|
r'https?://mega\.nz/file/[a-zA-Z0-9]+',
|
||||||
|
r'https?://drive\.google\.come/file/d/[a-zA-Z0-9]+',
|
||||||
|
r'https?://f95zone\.to/attachments/[a-zA-Z0-9]+',
|
||||||
|
]
|
||||||
|
|
||||||
|
clean_links = []
|
||||||
|
for pattern in patterns:
|
||||||
|
matches = re.findall(pattern, html)
|
||||||
|
for match in matches:
|
||||||
|
clean_link = match.strip().rstrip('"\'<>')
|
||||||
|
clean_links.append(clean_link)
|
||||||
|
|
||||||
|
unique_links = list(set(clean_links))
|
||||||
|
print(f"\nFound {len(unique_links)} unique links total")
|
||||||
|
|
||||||
|
if resolve_turbovid and extractor:
|
||||||
|
print("\n--- Resolving Turbovid Links ---")
|
||||||
|
resolved_links = []
|
||||||
|
turbovid_count = 0
|
||||||
|
failed_count = 0
|
||||||
|
for link in unique_links:
|
||||||
|
if 'turbo' in link.lower() and '.cr' in link.lower():
|
||||||
|
turbovid_count += 1
|
||||||
|
print(f"\nProcessing Turbovid link {turbovid_count}: {link}")
|
||||||
|
resolved = extractor.resolve_turbovid(link)
|
||||||
|
if resolved:
|
||||||
|
resolved_links.append(resolved)
|
||||||
|
else:
|
||||||
|
failed_count += 1
|
||||||
|
time.sleep(1)
|
||||||
|
else:
|
||||||
|
resolved_links.append(link)
|
||||||
|
print(f"\nResolved {turbovid_count - failed_count}/{turbovid_count} Turbovid links")
|
||||||
|
if failed_count > 0:
|
||||||
|
print(f"Failed: {failed_count} Turbovid link(s)")
|
||||||
|
return resolved_links
|
||||||
|
|
||||||
|
return unique_links
|
||||||
|
|
||||||
|
def save_links_to_file(links, output_file):
|
||||||
|
if not links:
|
||||||
|
print("No links found to save.")
|
||||||
|
return
|
||||||
|
|
||||||
|
existing = set()
|
||||||
|
if os.path.exists(output_file):
|
||||||
|
with open(output_file, 'r', encoding='utf-8') as f:
|
||||||
|
existing = set(line.strip() for line in f if line.strip())
|
||||||
|
|
||||||
|
new_links = [l for l in links if l not in existing]
|
||||||
|
|
||||||
|
if not new_links:
|
||||||
|
print("No new unique links found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(output_file, 'a', encoding='utf-8') as f:
|
||||||
|
for link in new_links:
|
||||||
|
f.write(link + "\n")
|
||||||
|
|
||||||
|
print(f"✓ Saved {len(new_links)} new links to {output_file}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("="*70)
|
||||||
|
print("SimPCity Link Extractor - Cloudscraper Version")
|
||||||
|
print("="*70)
|
||||||
|
print("\nMake sure you have cloudscraper installed:")
|
||||||
|
print(" pip install cloudscraper\n")
|
||||||
|
|
||||||
|
base_thread_url = "https://f95zone.to/threads/qiandai-collection-2026-01-04-qiandaiyiyu-qiandai.246056/"
|
||||||
|
output_html = "page_source.html"
|
||||||
|
output_links = "links.txt"
|
||||||
|
|
||||||
|
# CRITICAL: Export FRESH cookies from your browser while logged in
|
||||||
|
cookies = {
|
||||||
|
"__ddg1_": "ztu3bAWXt1yNTQLx4anD",
|
||||||
|
"__ddg2_": "XITPIP1OKNx5qhiT",
|
||||||
|
"__ddg8_": "oWldvDW5w2JAjymf",
|
||||||
|
"__ddg9_": "217.138.213.52",
|
||||||
|
"__ddg10_": "1781612477",
|
||||||
|
"__ddgid_": "yhSli2A9nG5Xkwcu",
|
||||||
|
"__ddgmark_": "pVXsbrKqDemwPHiu",
|
||||||
|
"oMased": "b4",
|
||||||
|
"oMasid": "9e19ba410603e03b1286baca7c2917ef56b9c760415db5e2b9574c87eb092e7e",
|
||||||
|
"ogaddgmetaprof_csrf": "",
|
||||||
|
"yMziCv8BrCZz1o7_csrf": "vGZEMX5-P-XSKuG_",
|
||||||
|
"yMziCv8BrCZz1o7_session": "upTVlbK2kspfKlRGyD74rOh_PacNF7DI",
|
||||||
|
"yMziCv8BrCZz1o7_user": "3944332%2Cr8xH2AcnE_hg0kkeNSSsi3luzSkW6odfKX21CHdk",
|
||||||
|
"yMziCv8BrCZz1o7_dbWriteForced": "1781612424"
|
||||||
|
}
|
||||||
|
|
||||||
|
extractor = SimPCityExtractor(cookies=cookies)
|
||||||
|
pages = extractor.get_thread_pages(base_thread_url)
|
||||||
|
|
||||||
|
if pages:
|
||||||
|
extractor.fetch_all_pages_to_file(pages, output_html)
|
||||||
|
links = extract_links(output_html, resolve_turbovid=True, extractor=extractor)
|
||||||
|
save_links_to_file(links, output_links)
|
||||||
|
print("\n" + "="*70)
|
||||||
|
print("Process completed!")
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
https://goonbox.cr/img/FAcymt
|
||||||
|
https://goonbox.cr/img/YMATKPH
|
||||||
|
https://goonbox.cr/img/YSEp9vW
|
||||||
|
https://goonbox.cr/img/Clyat6
|
||||||
|
https://goonbox.cr/img/YMAixVf
|
||||||
|
https://goonbox.cr/img/YMATvUy
|
||||||
|
https://goonbox.cr/img/tnAGtou
|
||||||
|
//redgifs.com/ifr/illegalidioticseaslug
|
||||||
|
https://goonbox.cr/img/tnABhwu
|
||||||
|
https://goonbox.cr/img/CMGfeo
|
||||||
|
https://goonbox.cr/img/CMGrO5
|
||||||
|
https://goonbox.cr/img/YMATFO5
|
||||||
|
https://goonbox.cr/img/tnABjJI
|
||||||
|
https://goonbox.cr/img/YMATHpK
|
||||||
|
https://goonbox.cr/img/FAccxh
|
||||||
|
https://goonbox.cr/img/ClsAgK
|
||||||
|
https://goonbox.cr/img/Yd96wX5
|
||||||
|
https://goonbox.cr/img/jCydec
|
||||||
|
https://dl100.turbocdn.st/turbo/data/dfdab4c0482e06bbf97a4f031f794fcd.mp4?exp=1784628166&token=972212f7a0a53ec1f5a2a1be5ff87f5b1db74547aa8c6d49e72bd86488bff1c3&fn=dfdab4c0482e06bbf97a4f031f794fcd.mp4
|
||||||
|
https://goonbox.cr/img/ClsdAw
|
||||||
|
https://goonbox.cr/img/aZ46s5u
|
||||||
|
https://goonbox.cr/img/Yd96haS
|
||||||
|
https://goonbox.cr/img/YUYZ1Vm
|
||||||
|
//redgifs.com/ifr/tiredrowdystagbeetle
|
||||||
|
https://goonbox.cr/img/wRJ60P
|
||||||
|
https://dl100.turbocdn.st/turbo/data/9085b3cbd1d9abdd6fa0701aed5ad613.m4v?exp=1784628167&token=c255685c4c91513b17bdf29806c8b56f979abf236880d4641d96e49be3b92a9c&fn=9085b3cbd1d9abdd6fa0701aed5ad613.m4v
|
||||||
|
https://goonbox.cr/img/YUYZnH7
|
||||||
|
https://goonbox.cr/img/YSOeM9A
|
||||||
|
https://goonbox.cr/img/YMATe0e
|
||||||
|
https://goonbox.cr/img/atlKUNp
|
||||||
|
https://goonbox.cr/img/YSOeO1u
|
||||||
|
https://goonbox.cr/img/FAcuQW
|
||||||
|
https://goonbox.cr/img/aZ46yxI
|
||||||
|
https://dl100.turbocdn.st/turbo/data/b466c20357814a6c65bfdd6fe72dcc5a.mp4?exp=1784628171&token=b2024b1cc9114b5c268406da069bef4250bc0b41ef1afd408e383986dfed8d7c&fn=b466c20357814a6c65bfdd6fe72dcc5a.mp4
|
||||||
|
https://dl100.turbocdn.st/turbo/data/Ni3GRf1ZIoc.mp4?exp=1784628172&token=9a874d136b438328aefd44e64668276c72e813121bea38cc95642d98e5ee92d8&fn=Ni3GRf1ZIoc.mp4
|
||||||
|
https://goonbox.cr/img/tnArRV1
|
||||||
|
https://goonbox.cr/img/Yd96jXW
|
||||||
|
https://goonbox.cr/img/Cly9Fe
|
||||||
|
https://goonbox.cr/img/Clswwd
|
||||||
|
https://goonbox.cr/img/YMATELa
|
||||||
|
//redgifs.com/ifr/standardfewvelvetcrab
|
||||||
|
https://goonbox.cr/img/Yd96Uy9
|
||||||
|
https://goonbox.cr/img/MTQUsy
|
||||||
|
https://goonbox.cr/img/ClyLBD
|
||||||
|
//redgifs.com/ifr/hatefulfreeswift
|
||||||
|
https://dl100.turbocdn.st/turbo/data/uLmFi1iE7uEvL.mp4?exp=1784628173&token=3f0918cac7853339ef8014d0c34849785c4582166ad584ac31b7ae8b19e28c1d&fn=BlackPerkyAsianelephant.mp4
|
||||||
|
https://goonbox.cr/img/wRJtR5
|
||||||
|
https://goonbox.cr/img/YUP3Jeu
|
||||||
|
https://goonbox.cr/img/YLLS30h
|
||||||
|
https://goonbox.cr/img/Yd96d4p
|
||||||
|
https://goonbox.cr/img/CMV3vh
|
||||||
|
https://goonbox.cr/img/tnArje6
|
||||||
|
https://goonbox.cr/img/Yd96OZE
|
||||||
|
https://goonbox.cr/img/wRDxLe
|
||||||
|
https://goonbox.cr/img/CMGuci
|
||||||
|
https://bunkr.cr/a/hojeA11a</a></div>Might
|
||||||
|
https://goonbox.cr/img/FAsYHn
|
||||||
|
https://goonbox.cr/img/Cls1Zg
|
||||||
|
https://goonbox.cr/img/ClsOI7
|
||||||
|
//redgifs.com/ifr/bossyfrankcurassow
|
||||||
|
https://goonbox.cr/img/Y0lt6Vh
|
||||||
|
https://goonbox.cr/img/YUfKbMh
|
||||||
|
https://goonbox.cr/img/wRDJun
|
||||||
|
https://goonbox.cr/img/aZ462Go
|
||||||
|
//redgifs.com/ifr/ellipticalstripedgavial
|
||||||
|
https://goonbox.cr/img/Cly6Mg
|
||||||
|
https://goonbox.cr/img/Cls8y6
|
||||||
|
https://goonbox.cr/img/YUfKAiG
|
||||||
|
https://goonbox.cr/img/wRJYp9
|
||||||
|
https://goonbox.cr/img/ClshXh
|
||||||
|
https://goonbox.cr/img/FAcf3D
|
||||||
|
https://goonbox.cr/img/YMATRpG
|
||||||
|
https://dl100.turbocdn.st/turbo/data/HdoYYJY0th2XX.mp4?exp=1784628176&token=a4ed4ede09d01cf863519ce2766160220e247663d0b021faa8e2db420276e104&fn=PrivateHoarseKagu.mp4
|
||||||
|
https://goonbox.cr/img/Clyvic
|
||||||
|
https://dl100.turbocdn.st/turbo/data/4f90c3c90b67165e5d56c96a050d5f6a.mp4?exp=1784628177&token=355b48a76bc1116a4b166ade2b6c1c4642e01a76ab1a6ead63dc30000b2a7412&fn=4f90c3c90b67165e5d56c96a050d5f6a.mp4
|
||||||
|
https://goonbox.cr/img/Clssbe
|
||||||
|
https://www.redgifs.com/watch/putridfloralwhitebaldeagle
|
||||||
|
//redgifs.com/ifr/wronghopefulsnake
|
||||||
|
https://goonbox.cr/img/ClsxnA
|
||||||
|
https://goonbox.cr/img/YUYZhlg
|
||||||
|
https://bunkr.cr/v/9MKkiy7cwee8S</a></div></div
|
||||||
|
https://goonbox.cr/img/ClyKTE
|
||||||
|
https://goonbox.cr/img/FAsNVy
|
||||||
|
https://goonbox.cr/img/tnArY3W
|
||||||
|
https://goonbox.cr/img/ClsQZp
|
||||||
|
https://goonbox.cr/img/MTQka9
|
||||||
|
//redgifs.com/ifr/instructivelimppanther
|
||||||
|
https://goonbox.cr/img/Clyt2h
|
||||||
|
https://goonbox.cr/img/Cls2JE
|
||||||
|
https://goonbox.cr/img/ClsVBa
|
||||||
|
https://dl100.turbocdn.st/turbo/data/p6cSN41GTPk3g.mp4?exp=1784628179&token=9913297db5aa531cfb3dca67779ff52e09a4d1a5abcf6477133c65bae82a972c&fn=NearWateryVelvetworm.mp4
|
||||||
|
https://www.redgifs.com/watch/smughungrynorthernhairynosedwombat
|
||||||
|
https://bunkr.cr/v/9MKkiy7cwee8S
|
||||||
|
https://goonbox.cr/img/FAcl9S
|
||||||
|
https://goonbox.cr/img/YMAT37n
|
||||||
|
https://goonbox.cr/img/YUP3oRI
|
||||||
|
https://dl100.turbocdn.st/turbo/data/itHlE264iGCgy.mp4?exp=1784628181&token=60a4cbd50ecc6afbb7be41fd9bb3be58b749c8d99a32dbf67112359ebb71ca8b&fn=PlaintiveClutteredKentrosaurus.mp4
|
||||||
|
https://goonbox.cr/img/YUfKpo6
|
||||||
|
//redgifs.com/ifr/navybluereflectinghumpbackwhale
|
||||||
|
//redgifs.com/ifr/uprightinstructivesidewinder
|
||||||
|
https://dl100.turbocdn.st/turbo/data/2Rkf576ZJ5eNj.mp4?exp=1784628182&token=8e9dac702d9fbdfbcb1bbbbc0799ad10970f302f688bd13fb073900590f3407b&fn=EnchantedOlivedrabSnowmonkey.mp4
|
||||||
|
https://goonbox.cr/img/ClsICm
|
||||||
|
https://goonbox.cr/img/FAcAVm
|
||||||
|
https://goonbox.cr/img/ClsnDc
|
||||||
|
https://bunkr.cr/a/xDIsT70G</a
|
||||||
|
https://goonbox.cr/img/YMAT9d6
|
||||||
|
https://goonbox.cr/img/YMATZRP
|
||||||
|
//redgifs.com/ifr/filthyagreeableeyelashpitviper
|
||||||
|
https://dl100.turbocdn.st/turbo/data/216c266eed23b3f8964e9490f3dc9f18.m4v?exp=1784628183&token=f539b9e931b5653c9ca5523174003c43242a9979c8c6841bf18159cce6d42a55&fn=216c266eed23b3f8964e9490f3dc9f18.m4v
|
||||||
|
https://goonbox.cr/img/ClsX6A
|
||||||
|
https://goonbox.cr/img/YUP3xcH
|
||||||
|
https://goonbox.cr/img/YSOekmG
|
||||||
|
//redgifs.com/ifr/dishonestbasicgreatdane
|
||||||
|
https://goonbox.cr/img/ClyT2f
|
||||||
|
https://goonbox.cr/img/wRJ3cK
|
||||||
|
https://goonbox.cr/img/ClsBCy
|
||||||
|
https://goonbox.cr/img/YSOewUh
|
||||||
|
https://www.redgifs.com/watch/deadlivelyhorsechestnutleafminer
|
||||||
|
https://goonbox.cr/img/Clsgj1
|
||||||
|
https://goonbox.cr/img/aZ46pl1
|
||||||
|
https://goonbox.cr/img/aZ46AH6
|
||||||
|
https://goonbox.cr/img/aKv3wkg
|
||||||
|
https://goonbox.cr/img/FAsaOe
|
||||||
|
https://goonbox.cr/img/CMVad6
|
||||||
|
https://goonbox.cr/img/YMATYed
|
||||||
|
https://bunkr.cr/a/hojeA11a
|
||||||
|
https://dl100.turbocdn.st/turbo/data/a9FjxpoLa64WK.mp4?exp=1784628184&token=73ff88e4f8b1286a804f2c6e8041880be97ade4fbf684f1c5746ae7b79ce1d94&fn=WatchfulFirmChinesecrocodilelizard.mp4
|
||||||
|
https://bunkr.cr/a/4IpIC7ft
|
||||||
|
https://goonbox.cr/img/YMATaRE
|
||||||
|
https://goonbox.cr/img/YUfKuEc
|
||||||
|
https://goonbox.cr/img/CMGJ0I
|
||||||
|
https://goonbox.cr/img/gyyowd
|
||||||
|
https://goonbox.cr/img/YMATNQp
|
||||||
|
https://goonbox.cr/img/tnAp3AA
|
||||||
|
https://goonbox.cr/img/YUPeNP6
|
||||||
|
https://goonbox.cr/img/FAcJmd
|
||||||
|
https://goonbox.cr/img/YSOedVI
|
||||||
|
https://goonbox.cr/img/YUP3zpi
|
||||||
|
https://goonbox.cr/img/YMAioOW
|
||||||
|
https://goonbox.cr/img/YMAT6u9
|
||||||
|
https://goonbox.cr/img/atlKk2e
|
||||||
|
https://goonbox.cr/img/Yd96kNa
|
||||||
|
https://bunkr.cr/a/jVQHrc1j
|
||||||
|
https://bunkr.cr/a/jVQHrc1j</a></div>I
|
||||||
|
https://goonbox.cr/img/wRJNva
|
||||||
|
https://dl100.turbocdn.st/turbo/data/Xy6gIjCcs6y.mp4?exp=1784628186&token=f7b20207f25671f9952f6120e92afb4e459fdfef516c5fb8cd3c763dd52e2a51&fn=Xy6gIjCcs6y.mp4
|
||||||
|
https://goonbox.cr/img/aZ46Q3P
|
||||||
|
https://goonbox.cr/img/Clsjwt
|
||||||
|
https://goonbox.cr/img/tnArPVD
|
||||||
|
https://goonbox.cr/img/YSOenlP
|
||||||
|
https://goonbox.cr/img/YSOeIeH
|
||||||
|
https://goonbox.cr/img/YLLSYR1
|
||||||
|
https://goonbox.cr/img/YLLSt7G
|
||||||
|
https://dl100.turbocdn.st/turbo/data/b8788e03ed39b15cc722c802e6aaba44.mp4?exp=1784628187&token=ec512b4482e8d4d0b381183485b54aa84d04b54f998eed305b6be990896af4ce&fn=b8788e03ed39b15cc722c802e6aaba44.mp4
|
||||||
|
https://goonbox.cr/img/YUP3lHo
|
||||||
|
https://goonbox.cr/img/aKv32D7
|
||||||
|
https://goonbox.cr/img/FAcGlg
|
||||||
|
https://goonbox.cr/img/tnAGN5i
|
||||||
|
https://dl100.turbocdn.st/turbo/data/byYinLjWWZI.mp4?exp=1784628188&token=9760ec8cca4534a122083cccde9496e9c58213d23ffa1a113fce6902d0b6f872&fn=byYinLjWWZI.mp4
|
||||||
|
https://goonbox.cr/img/ClskXf
|
||||||
|
https://goonbox.cr/img/ClsRaG
|
||||||
|
https://goonbox.cr/img/YUfKfft
|
||||||
|
https://goonbox.cr/img/aZ46GmH
|
||||||
|
https://dl100.turbocdn.st/turbo/data/P1HJbAxIswHhs.mp4?exp=1784628190&token=bb2bbbf6912da64d7387142136f885914d8648d0c0c98a26fc9a7f40c1b6bd76&fn=ExtrovertedFaintWhitepelican.mp4
|
||||||
|
https://goonbox.cr/img/FAcBSc
|
||||||
|
https://goonbox.cr/img/YUP3uOP
|
||||||
|
https://goonbox.cr/img/Cls0AH
|
||||||
|
https://goonbox.cr/img/YUYZd3D
|
||||||
|
https://goonbox.cr/img/tnArz7o
|
||||||
|
https://bunkr.cr/a/xDIsT70G
|
||||||
|
https://goonbox.cr/img/ClsMjD
|
||||||
|
https://goonbox.cr/img/Yd962wK
|
||||||
|
https://goonbox.cr/img/ClsSyS
|
||||||
|
https://goonbox.cr/img/wRDDUp
|
||||||
|
https://goonbox.cr/img/atlKPgn
|
||||||
|
https://goonbox.cr/img/Clyi8W
|
||||||
|
https://goonbox.cr/img/YSOe1Hi
|
||||||
|
https://goonbox.cr/img/YUfKV21
|
||||||
|
https://goonbox.cr/img/YMAT00I
|
||||||
|
https://www.redgifs.com/watch/pungentdamagedmorpho
|
||||||
|
https://goonbox.cr/img/YUPea01
|
||||||
|
https://goonbox.cr/img/wRJCPi
|
||||||
|
https://goonbox.cr/img/YMATWeo
|
||||||
|
https://goonbox.cr/img/FAcpH7
|
||||||
|
//redgifs.com/ifr/idlewrathfulcornsnake
|
||||||
|
https://goonbox.cr/img/YLLS7eA
|
||||||
|
https://goonbox.cr/img/CMGxuA
|
||||||
|
https://goonbox.cr/img/Yd96MCe
|
||||||
|
https://bunkr.cr/a/4IpIC7ft</a></div></div
|
||||||
|
https://goonbox.cr/img/FAcxlp
|
||||||
|
https://goonbox.cr/img/YMAiJHS
|
||||||
|
https://goonbox.cr/img/ClsPNW
|
||||||
|
https://goonbox.cr/img/ClszIu
|
||||||
|
https://goonbox.cr/img/YSOeP76
|
||||||
|
https://goonbox.cr/img/ClyFEw
|
||||||
|
https://dl100.turbocdn.st/turbo/data/6ece23a7e5625b23c22ed7f8296af6f6.mp4?exp=1784628194&token=ddf17a362530aea08e48516a35179b1cc259e186139845d6c4bd9e477204db23&fn=6ece23a7e5625b23c22ed7f8296af6f6.mp4
|
||||||
|
https://dl100.turbocdn.st/turbo/data/13264d3bf41f3f952c2eb4f207e4b55e.m4v?exp=1784628195&token=b9aabe3ee04c0d9b36f3ee7233a8be23bae88d6b19503e688fd21fd9a2e96e20&fn=13264d3bf41f3f952c2eb4f207e4b55e.m4v
|
||||||
|
https://goonbox.cr/img/wRJv7o
|
||||||
|
https://goonbox.cr/img/YUPeY7A
|
||||||
|
https://goonbox.cr/img/tnAri5o
|
||||||
|
https://goonbox.cr/img/YUfKzqg
|
||||||
|
https://dl100.turbocdn.st/turbo/data/19aa66817df66c1502bed3fa230aab0e.mp4?exp=1784628196&token=090b8fa778f87a32352de4058098c073638e9a4d966bead53bf6e16954f9f434&fn=19aa66817df66c1502bed3fa230aab0e.mp4
|
||||||
|
https://www.redgifs.com/watch/euphoricsandybrownbandicoot
|
||||||
|
//redgifs.com/ifr/lostaptbluebottlejellyfish
|
||||||
|
https://goonbox.cr/img/FAcr1w
|
||||||
|
https://goonbox.cr/img/tnArvSn
|
||||||
|
https://goonbox.cr/img/tnArpOy
|
||||||
|
https://dl100.turbocdn.st/turbo/data/7d0b3c6c30a5a2a365b071f82b33ad5b.mp4?exp=1784628197&token=142189fa6e731c88bc1dbea395296b479f12c772ffd87ce8d5e29b4bdedcde81&fn=7d0b3c6c30a5a2a365b071f82b33ad5b.mp4
|
||||||
|
https://goonbox.cr/img/aZ46b1G
|
||||||
|
https://dl100.turbocdn.st/turbo/data/fa23b69e3cfe943e733e29a28f6ae79c.mp4?exp=1784628198&token=e9f7fbb46989d7aa87db6ab32da007dcd3e5967ce2315561e973353331fd8822&fn=fa23b69e3cfe943e733e29a28f6ae79c.mp4
|
||||||
|
https://goonbox.cr/img/FAcoUE
|
||||||
|
https://goonbox.cr/img/YUYZq1w
|
||||||
|
https://goonbox.cr/img/ClsfJP
|
||||||
|
https://goonbox.cr/img/wRJ7Oy
|
||||||
|
https://goonbox.cr/img/YUYZ49S
|
||||||
|
https://goonbox.cr/img/ClscIn
|
||||||
|
//redgifs.com/ifr/hollowfemininechick
|
||||||
Executable
+25745
File diff suppressed because one or more lines are too long
Executable
+1288
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user