creek
The AI Image Editor of 2030git clone https://github.com/maydayv7/creek
commit eb038cb8050e02f99fc80904b9985f717ee7bafd parent bfa770ef10c8d33e979114fbc40de9c06d8fb83c Author: Krish-2512 <155168478+Krish-2512@users.noreply.github.com> Date: Wed, 26 Nov 2025 01:05:01 +0530 Merge pull request #4 from nilotpal-n7/Krish chrome sharing added
Diffstat:
| M | lib/services/download_service.dart | | | 153 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------- |
| M | pubspec.lock | | | 30 | +++++++++++++++--------------- |
2 files changed, 132 insertions(+), 51 deletions(-)
diff --git a/lib/services/download_service.dart b/lib/services/download_service.dart @@ -4,85 +4,166 @@ import 'package:http/http.dart' as http; import 'package:path_provider/path_provider.dart'; import 'package:uuid/uuid.dart'; import 'package:adobe/data/repos/image_repo.dart'; -import 'package:html/parser.dart' as parser; // Import the parser +import 'package:html/parser.dart' as parser; class DownloadService { final _repo = ImageRepository(); final _uuid = const Uuid(); + String _unescapeUrl(String s) { + if (s.isEmpty) return s; + // unescape common JS/HTML escapes: \xNN, \uNNNN, \/, & + try { + s = s.replaceAll('\\/', '/'); + s = s.replaceAll('&', '&'); + + s = s.replaceAllMapped(RegExp(r"\\x([0-9A-Fa-f]{2})"), (m) { + final code = int.parse(m.group(1)!, radix: 16); + return String.fromCharCode(code); + }); + + s = s.replaceAllMapped(RegExp(r"\\u([0-9A-Fa-f]{4})"), (m) { + final code = int.parse(m.group(1)!, radix: 16); + return String.fromCharCode(code); + }); + + // decode percent-encoding if present + try { + s = Uri.decodeFull(s); + } catch (_) {} + } catch (_) {} + return s; + } + Future<String?> downloadAndSaveImage(String url) async { debugPrint("📥 START PROCESS: $url"); try { - // 1. Initial Request + // Fetch URL var response = await http.get( Uri.parse(url), headers: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', }, ); - if (response.statusCode != 200) return null; + if (response.statusCode != 200) { + debugPrint("❌ HTTP Error: ${response.statusCode}"); + return null; + } - // 2. Check: Is it an Image or a Website? var contentType = response.headers['content-type']; debugPrint("🔹 Type: $contentType"); - // CASE A: It is a WEBSITE (like Wikipedia, Pinterest, etc.) + + // CASE A → HTML webpage (NOT a direct image) + if (contentType != null && !contentType.startsWith('image/')) { - debugPrint("📄 It's a website. Looking for the real image inside..."); - - // Parse the HTML text + debugPrint("📄 It's a website. Extracting real image..."); final document = parser.parse(response.body); - // Try to find the "Open Graph" image (Standard used by Wiki, Pinterest, Insta) - String? realImageUrl; + + // 1️⃣ GOOGLE PHOTOS / GOOGLEUSERCONTENT.COM + + RegExp googlePhotosRegex = RegExp( + r'https:\/\/lh3\.googleusercontent\.com\/[a-zA-Z0-9\-\._=]+' + ); + + var matchPhotos = googlePhotosRegex.firstMatch(response.body); + if (matchPhotos != null) { + String cdn = matchPhotos.group(0)!; + + // Force highest resolution + cdn = _unescapeUrl(cdn); + cdn = cdn.split("=").first + "=s0"; + debugPrint("📸 Google Photos Image Found: $cdn"); + + return downloadAndSaveImage(cdn); + } + + + // 2️⃣ GOOGLE IMAGE SEARCH (encrypted-tbn / gstatic) + RegExp googleImageRegex = RegExp( + "https:\\/\\/(?:encrypted\\-tbn\\d\\.gstatic\\.com|(?:\\w+\\.)?gstatic\\.com)\\/[^\"'\\s<>]+", + ); + + + + + var matchGImg = googleImageRegex.firstMatch(response.body); + if (matchGImg != null) { + String imgUrl = matchGImg.group(0)!; + imgUrl = _unescapeUrl(imgUrl); + debugPrint("🔍 Google Images Real URL: $imgUrl"); + + return downloadAndSaveImage(imgUrl); + } + + // 3️⃣ GOOGLE VIEWER internal imageUrl='https://...' + + RegExp viewerImageRegex = + RegExp(r"imageUrl='(https:\/\/[^']+)'"); + + var viewerMatch = viewerImageRegex.firstMatch(response.body); + if (viewerMatch != null) { + String imgUrl = viewerMatch.group(1)!; + imgUrl = _unescapeUrl(imgUrl); + debugPrint("🖼️ Google Viewer Direct Image: $imgUrl"); + + return downloadAndSaveImage(imgUrl); + } + + // 4️⃣ OG IMAGE → Pinterest / Instagram / Wikipedia + final metaTags = document.getElementsByTagName('meta'); for (var meta in metaTags) { if (meta.attributes['property'] == 'og:image') { - realImageUrl = meta.attributes['content']; - break; + String? ogImg = meta.attributes['content']; + if (ogImg != null) { + ogImg = _unescapeUrl(ogImg); + debugPrint("🎯 OG Image Found: $ogImg"); + return downloadAndSaveImage(ogImg); + } } } - // If found, we must download THIS new URL - if (realImageUrl != null) { - debugPrint("🎯 Found Real Image: $realImageUrl"); - // Recursively call this function with the REAL link - return downloadAndSaveImage(realImageUrl); - } else { - debugPrint("❌ Could not find an image inside this page."); - return null; - } + debugPrint("❌ No valid image found inside this page."); + return null; } - // CASE B: It is a REAL IMAGE (content-type is image/png, image/jpeg, etc.) - // Proceed to save it normally. - + + // CASE B → DIRECT IMAGE FILE (content-type starts with image/) final dir = await getApplicationDocumentsDirectory(); final imagesDir = Directory('${dir.path}/images'); - if (!await imagesDir.exists()) await imagesDir.create(recursive: true); - // Guess extension - String extension = 'png'; + if (!await imagesDir.exists()) { + await imagesDir.create(recursive: true); + } + + // Detect extension + String extension = "png"; if (contentType != null) { - if (contentType.contains('jpg')) extension = 'jpg'; - if (contentType.contains('gif')) extension = 'gif'; - if (contentType.contains('webp')) extension = 'webp'; + if (contentType.contains("jpeg") || contentType.contains("jpg")) { + extension = "jpg"; + } else if (contentType.contains("gif")) { + extension = "gif"; + } else if (contentType.contains("webp")) { + extension = "webp"; + } } - final String imageId = _uuid.v4(); - final String filePath = '${imagesDir.path}/$imageId.$extension'; + final imageId = _uuid.v4(); + final filePath = "${imagesDir.path}/$imageId.$extension"; final file = File(filePath); await file.writeAsBytes(response.bodyBytes); - + await _repo.insertImage(imageId, filePath); - debugPrint("✅ Saved Successfully!"); + debugPrint("✅ Saved Successfully! → $filePath"); return imageId; - } catch (e) { debugPrint("❌ Error: $e"); return null; diff --git a/pubspec.lock b/pubspec.lock @@ -77,10 +77,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" ffi: dependency: transitive description: @@ -252,26 +252,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -300,10 +300,10 @@ packages: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -489,10 +489,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.7" typed_data: dependency: transitive description: @@ -513,10 +513,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -542,5 +542,5 @@ packages: source: hosted version: "1.1.0" sdks: - dart: ">=3.7.2 <4.0.0" + dart: ">=3.8.0-0 <4.0.0" flutter: ">=3.29.0"