creek
The AI Image Editor of 2030git clone https://github.com/maydayv7/creek
lib/services/download_service.dart (4937B)
1import 'dart:io';
2import 'package:flutter/material.dart';
3import 'package:http/http.dart' as http;
4import 'package:path_provider/path_provider.dart';
5import 'package:uuid/uuid.dart';
6import 'package:html/parser.dart' as parser;
7
8class DownloadService {
9 final _uuid = const Uuid();
10
11 String _unescapeUrl(String s) {
12 if (s.isEmpty) return s;
13 // unescape common JS/HTML escapes: \xNN, \uNNNN, \/, &
14 try {
15 s = s.replaceAll('\\/', '/');
16 s = s.replaceAll('&', '&');
17
18 s = s.replaceAllMapped(RegExp(r"\\x([0-9A-Fa-f]{2})"), (m) {
19 final code = int.parse(m.group(1)!, radix: 16);
20 return String.fromCharCode(code);
21 });
22
23 s = s.replaceAllMapped(RegExp(r"\\u([0-9A-Fa-f]{4})"), (m) {
24 final code = int.parse(m.group(1)!, radix: 16);
25 return String.fromCharCode(code);
26 });
27
28 // decode percent-encoding if present
29 try {
30 s = Uri.decodeFull(s);
31 } catch (_) {}
32 } catch (_) {}
33 return s;
34 }
35
36 Future<String?> downloadAndSaveImage(String url) async {
37 debugPrint("START DOWNLOAD: $url");
38
39 try {
40 // Fetch URL
41 var response = await http.get(
42 Uri.parse(url),
43 headers: {
44 'User-Agent':
45 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
46 },
47 );
48
49 if (response.statusCode != 200) {
50 debugPrint("❌ HTTP Error: ${response.statusCode}");
51 return null;
52 }
53
54 var contentType = response.headers['content-type'];
55 debugPrint("Type: $contentType");
56
57 // CASE A → HTML webpage (NOT a direct image)
58 if (contentType != null && !contentType.startsWith('image/')) {
59 debugPrint("It's a website. Extracting real image...");
60 final document = parser.parse(response.body);
61
62 // 1️1. GOOGLE PHOTOS / GOOGLEUSERCONTENT.COM
63 RegExp googlePhotosRegex = RegExp(
64 r'https:\/\/lh3\.googleusercontent\.com\/[a-zA-Z0-9\-\._=]+',
65 );
66
67 var matchPhotos = googlePhotosRegex.firstMatch(response.body);
68 if (matchPhotos != null) {
69 String cdn = matchPhotos.group(0)!;
70 // Force highest resolution
71 cdn = _unescapeUrl(cdn);
72 cdn = "${cdn.split("=").first}=s0";
73 debugPrint("Google Photos Image Found: $cdn");
74 return downloadAndSaveImage(cdn);
75 }
76
77 // 2️2. GOOGLE IMAGE SEARCH
78 RegExp googleImageRegex = RegExp(
79 "https:\\/\\/(?:encrypted\\-tbn\\d\\.gstatic\\.com|(?:\\w+\\.)?gstatic\\.com)\\/[^\"'\\s<>]+",
80 );
81
82 var matchGImg = googleImageRegex.firstMatch(response.body);
83 if (matchGImg != null) {
84 String imgUrl = matchGImg.group(0)!;
85 imgUrl = _unescapeUrl(imgUrl);
86 debugPrint("Google Images Real URL: $imgUrl");
87 return downloadAndSaveImage(imgUrl);
88 }
89
90 // 3️3. GOOGLE VIEWER
91 RegExp viewerImageRegex = RegExp(r"imageUrl='(https:\/\/[^']+)'");
92
93 var viewerMatch = viewerImageRegex.firstMatch(response.body);
94 if (viewerMatch != null) {
95 String imgUrl = viewerMatch.group(1)!;
96 imgUrl = _unescapeUrl(imgUrl);
97 debugPrint("Google Viewer Direct Image: $imgUrl");
98 return downloadAndSaveImage(imgUrl);
99 }
100
101 // 4️4. OG IMAGE → Pinterest / Instagram / Wikipedia
102 final metaTags = document.getElementsByTagName('meta');
103 for (var meta in metaTags) {
104 if (meta.attributes['property'] == 'og:image') {
105 String? ogImg = meta.attributes['content'];
106 if (ogImg != null) {
107 ogImg = _unescapeUrl(ogImg);
108 debugPrint("OG Image Found: $ogImg");
109 return downloadAndSaveImage(ogImg);
110 }
111 }
112 }
113
114 debugPrint("No valid image found inside this page.");
115 return null;
116 }
117
118 // CASE B → DIRECT IMAGE FILE (content-type starts with image/)
119 final dir = await getApplicationDocumentsDirectory();
120 final imagesDir = Directory('${dir.path}/images');
121
122 if (!await imagesDir.exists()) {
123 await imagesDir.create(recursive: true);
124 }
125
126 // Detect extension
127 String extension = "png";
128 if (contentType != null) {
129 if (contentType.contains("jpeg") || contentType.contains("jpg")) {
130 extension = "jpg";
131 } else if (contentType.contains("gif")) {
132 extension = "gif";
133 } else if (contentType.contains("webp")) {
134 extension = "webp";
135 }
136 }
137
138 final imageId = _uuid.v4();
139 final filePath = "${imagesDir.path}/$imageId.$extension";
140
141 final file = File(filePath);
142 await file.writeAsBytes(response.bodyBytes);
143
144 debugPrint("Saved Successfully! → $filePath");
145 return filePath;
146 } catch (e) {
147 debugPrint("Error: $e");
148 return null;
149 }
150 }
151}