File size: 6,200 Bytes
1722101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import os
import threading
import subprocess
import requests
import time
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

# Lokasi Dasar
HOME_DIR = os.path.expanduser('~')
BASE_PICTURES = os.path.join(HOME_DIR, 'Pictures')

# Status Global
status_data = {
    'text': 'Siap...',
    'percent': 0,
    'status': 'idle'
}

# --- SCAN URL ---
@app.route('/scan', methods=['POST'])
def scan_url():
    raw_url = request.json.get('url')
    if not raw_url: return jsonify({'status': 'error', 'message': 'URL kosong'})

    # TIKTOK: Bypass Preview
    if "tiktok.com" in raw_url:
        return jsonify({
            'status': 'success',
            'mode': 'bulk_tiktok',
            'message': 'TikTok Slide Terdeteksi (Mode API)'
        })

    # INSTAGRAM: Pakai Gallery-DL
    try:
        command = ["gallery-dl", "-g", "--cookies-from-browser", "brave", raw_url]
        result = subprocess.run(command, capture_output=True, text=True)

        if result.returncode == 0:
            raw_links = result.stdout.strip().split('\n')
            valid_links = [link for link in raw_links if link.startswith('http')]
            if not valid_links:
                 return jsonify({'status': 'error', 'message': 'Tidak ada gambar ditemukan.'})
            return jsonify({
                'status': 'success',
                'mode': 'select_ig',
                'images': valid_links,
                'count': len(valid_links)
            })
        else:
            return jsonify({'status': 'error', 'message': "Gagal Scan IG (Cek Login Brave)"})

    except Exception as e:
        return jsonify({'status': 'error', 'message': str(e)})


# --- EKSEKUTOR TIKTOK (JALUR BELAKANG / API) ---
def run_tiktok_api(url):
    global status_data
    status_data['status'] = 'downloading'

    TARGET_FOLDER = os.path.join(BASE_PICTURES, 'TikTok')
    if not os.path.exists(TARGET_FOLDER): os.makedirs(TARGET_FOLDER)

    try:
        status_data['percent'] = 10
        status_data['text'] = "Menghubungi Server TikWM..."

        # 1. TEMBAK KE API PUBLIK (TikWM)
        # Ini akan mengembalikan JSON berisi link gambar yang bersih
        api_url = "https://www.tikwm.com/api/"
        payload = {'url': url, 'hd': 1}

        req = requests.post(api_url, data=payload)
        resp = req.json()

        image_urls = []

        # 2. AMBIL LIST GAMBAR DARI RESPON
        if resp.get('code') == 0:
            data = resp.get('data', {})
            if 'images' in data:
                image_urls = data['images']
            else:
                # Kalau ternyata bukan slide, tapi video single (ambil covernya)
                if 'cover' in data: image_urls.append(data['cover'])
        else:
            raise Exception("Gagal mengambil data dari API (Link Private/Salah).")

        if not image_urls:
            raise Exception("Tidak ada gambar ditemukan.")

        # 3. DOWNLOAD MANUAL
        total = len(image_urls)
        print(f"API Berhasil: Ditemukan {total} slide.")

        # Headers standar
        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"
        }

        success_count = 0
        for i, img_url in enumerate(image_urls):
            current = i + 1
            status_data['percent'] = (current / total) * 100
            status_data['text'] = f"Menyimpan Slide {current} dari {total}..."

            try:
                response = requests.get(img_url, headers=headers, stream=True)
                if response.status_code == 200:
                    filename = f"TK_{int(time.time())}_{current}.jpg"
                    full_path = os.path.join(TARGET_FOLDER, filename)

                    with open(full_path, 'wb') as f:
                        for chunk in response.iter_content(1024):
                            f.write(chunk)
                    success_count += 1
            except: pass

        status_data['status'] = 'finished'
        status_data['percent'] = 100
        status_data['text'] = f"Selesai! {success_count} slide tersimpan."

    except Exception as e:
        print(f"Error TikTok API: {e}")
        status_data['status'] = 'error'
        status_data['text'] = "Gagal memproses (Server API sibuk/Link salah)"


# --- EKSEKUTOR IG ---
def run_ig_manual(selected_urls):
    global status_data
    status_data['status'] = 'downloading'
    total = len(selected_urls)
    TARGET_FOLDER = os.path.join(BASE_PICTURES, 'Instagram')
    if not os.path.exists(TARGET_FOLDER): os.makedirs(TARGET_FOLDER)

    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"}

    for i, img_url in enumerate(selected_urls):
        try:
            current = i + 1
            status_data['percent'] = (current / total) * 100
            status_data['text'] = f"Menyimpan ke Instagram ({current}/{total})..."
            response = requests.get(img_url, headers=headers, stream=True)
            if response.status_code == 200:
                filename = f"IG_{int(time.time())}_{current}.jpg"
                full_path = os.path.join(TARGET_FOLDER, filename)
                with open(full_path, 'wb') as f:
                    for chunk in response.iter_content(1024):
                        f.write(chunk)
        except: pass

    status_data['status'] = 'finished'
    status_data['percent'] = 100
    status_data['text'] = "Selesai! Cek folder Pictures/Instagram"


@app.route('/')
def home():
    return render_template('index.html')

@app.route('/action', methods=['POST'])
def action():
    data = request.json
    mode = data.get('mode')

    if mode == 'tiktok':
        url = data.get('url')
        t = threading.Thread(target=run_tiktok_api, args=(url,))
        t.start()
    elif mode == 'instagram':
        urls = data.get('urls')
        t = threading.Thread(target=run_ig_manual, args=(urls,))
        t.start()

    return jsonify({'status': 'started'})

@app.route('/status')
def status():
    return jsonify(status_data)

if __name__ == '__main__':
    app.run(debug=True, port=5001, host='0.0.0.0')