creek

The AI Image Editor of 2030

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}