import os
import sys
import threading
import time
from tkinter import *
from tkinter import filedialog, scrolledtext, messagebox
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
# Xác định thư mục chứa Tool2 (file đang chạy)
base_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
cookie_path = os.path.join(base_dir, "cookies-okru.txt")
def center_window(root, width=800, height=500):
# Lấy kích thước màn hình
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
# Tính vị trí bắt đầu trục ngang và trục đứng
aaaxxx = (screen_width // 2) - (width // 2)
bbbyyy = (screen_height // 2) - (height // 2) - (40)
# Đặt geometry
root.geometry(f"{width}x{height}+{aaaxxx}+{bbbyyy}")
class OkRuUploader:
def __init__(self, root):
self.root = root
self.root.title("Ok.Ru Uploader - DarkCorners")
self.root.resizable(False, False)
center_window(self.root, 800, 500)
self.video_folder = StringVar()
self.output_folder = StringVar()
self.username = StringVar()
self.password = StringVar()
self.silent_mode = BooleanVar()
self.cookie_mode = StringVar(value="Đăng Nhập")
self.videos = []
self.total = 0
self.uploaded = 0
self.errors = 0
self.stop_flag = False
self.build_gui()
def build_gui(self):
# Hàng 1 : Tiêu đề phần mềm
Label(self.root, text="Ok.Ru Uploader - DarkCorners", font=("Arial", 16, "bold")).pack(pady=5)
# Hàng 2 : Khung chọn thư mục
frame_folders = Frame(self.root)
frame_folders.pack(pady=5)
# Hàng 2 : Khung chọn thư mục trái
Button(frame_folders, text="Chọn Thư Mục Video", command=self.select_video_folder).grid(row=0, column=0, padx=5)
Entry(frame_folders, textvariable=self.video_folder, width=40).grid(row=0, column=1, padx=5)
# Hàng 2 : Khung chọn thư mục phải
Button(frame_folders, text="Chọn Thư Mục Xuất File", command=self.select_output_folder).grid(row=0, column=2, padx=5)
Entry(frame_folders, textvariable=self.output_folder, width=40).grid(row=0, column=3, padx=5)
# Hàng 3 : Xác thực tài khoản
frame_row3 = Frame(self.root)
frame_row3.pack(fill=X, padx=10, pady=5)
frame_login_box = LabelFrame(frame_row3, text="XÁC THỰC TÀI KHOẢN OK.RU", font=("Arial", 10, "bold"), padx=10, pady=5)
frame_login_box.pack(fill=X)
# Hàng 3 : Kiểu cookies
Label(frame_login_box, text="Kiểu Cookies:").grid(row=0, column=0, padx=5, sticky=W)
option_frame = Frame(frame_login_box)
option_frame.grid(row=0, column=1, padx=5, sticky=W)
Radiobutton(option_frame, text="TXT File", variable=self.cookie_mode, value="TXT File", command=self.toggle_login_fields).pack(side=LEFT)
Radiobutton(option_frame, text="Đăng Nhập", variable=self.cookie_mode, value="Đăng Nhập", command=self.toggle_login_fields).pack(side=LEFT)
# Hàng 3 : Khung tài khoản
Label(frame_login_box, text="User:").grid(row=0, column=2, padx=5, sticky=E)
self.user_entry = Entry(frame_login_box, textvariable=self.username, width=20)
self.user_entry.grid(row=0, column=3, padx=5)
# Hàng 3 : Khung mật khẩu
Label(frame_login_box, text="Password:").grid(row=0, column=4, padx=5, sticky=E)
self.pass_entry = Entry(frame_login_box, textvariable=self.password, show="*", width=20)
self.pass_entry.grid(row=0, column=5, padx=5)
# Hàng 3 : Nút ẩn trình duyện chrome
Label(frame_login_box, text="Ẩn Trình Duyệt").grid(row=0, column=6, padx=(15, 2), sticky=E)
Checkbutton(frame_login_box, variable=self.silent_mode).grid(row=0, column=7, sticky=W)
# Hàng 3 : Phần ghi chú
# Dòng 1: hướng dẫn cookies
Label(frame_login_box, text="Nếu chọn TXT File thì hãy chắc chắn file cookies-okru.txt tồn tại trong thư mục.", fg="gray").grid(row=1, column=0, columnspan=8, sticky=W, pady=(5, 0))
# Dòng 2: ví dụ thêm ghi chú
Label(frame_login_box, text="Định dạng cookie phải là Netscape(.txt). Bạn có thể xuất bằng tiện ích Cookie-Editor trên Google Chrome", fg="gray").grid(row=2, column=0, columnspan=8, sticky=W, pady=(0, 5))
# Hàng 4
frame_buttons = Frame(self.root)
frame_buttons.pack(fill=X, padx=10, pady=10)
# Hàng 4 Bên trái: Thông tin trạng thái dạng label màu
frame_left = Frame(frame_buttons)
frame_left.pack(side=LEFT, expand=True, anchor=W)
self.label_total = Label(frame_left, text="Tổng Số Videos: 0", font=("Arial", 10, "bold"), fg="red")
self.label_total.pack(side=LEFT, padx=5)
self.label_uploaded = Label(frame_left, text="Đã Upload: 0", font=("Arial", 10, "bold"), fg="green")
self.label_uploaded.pack(side=LEFT, padx=5)
self.label_waiting = Label(frame_left, text="Đợi Upload: 0", font=("Arial", 10, "bold"), fg="blue")
self.label_waiting.pack(side=LEFT, padx=5)
self.label_errors = Label(frame_left, text="Lỗi Upload: 0", font=("Arial", 10, "bold"), fg="black")
self.label_errors.pack(side=LEFT, padx=5)
# Hàng 4 Bên phải: Các nút điều khiển
frame_right = Frame(frame_buttons)
frame_right.pack(side=RIGHT, anchor=E)
Button(frame_right, text="Bắt Đầu", width=12, command=self.start_upload).pack(side=LEFT, padx=5)
Button(frame_right, text="Dừng Lại", width=12, command=self.stop_upload).pack(side=LEFT, padx=5)
Button(frame_right, text="Thoát", width=12, command=self.root.quit).pack(side=LEFT, padx=5)
self.log_text = scrolledtext.ScrolledText(self.root, width=110, height=15)
self.log_text.pack(padx=10, pady=5)
self.status_var = StringVar()
self.status_var.set("Tổng Videos: 0 --- Đã Upload: 0 --- Đợi Upload: 0 --- Lỗi Upload: 0")
Label(self.root, textvariable=self.status_var, font=("Arial", 10)).pack(pady=5)
def toggle_login_fields(self):
is_txt = self.cookie_mode.get() == "TXT File"
state = DISABLED if is_txt else NORMAL
self.user_entry.config(state=state)
self.pass_entry.config(state=state)
def log(self, message):
self.log_text.insert(END, f"{message}\n")
self.log_text.see(END)
def update_status(self):
waiting = self.total - self.uploaded - self.errors
self.status_var.set(f"Tổng Videos: {self.total} --- Đã Upload: {self.uploaded} --- Đợi Upload: {waiting} --- Lỗi Upload: {self.errors}")
# Cập nhật các nhãn màu ở dòng nút
self.label_total.config(text=f"Tổng Số Videos: {self.total}")
self.label_uploaded.config(text=f"Đã Upload: {self.uploaded}")
self.label_waiting.config(text=f"Đợi Upload: {waiting}")
self.label_errors.config(text=f"Lỗi Upload: {self.errors}")
def select_video_folder(self):
path = filedialog.askdirectory()
self.video_folder.set(path)
def select_output_folder(self):
path = filedialog.askdirectory()
self.output_folder.set(path)
def start_upload(self):
self.stop_flag = False
threading.Thread(target=self.upload_videos).start()
def stop_upload(self):
self.stop_flag = True
self.log("⛔ Đã yêu cầu dừng upload sau video hiện tại.")
def upload_videos(self):
self.videos = [f for f in os.listdir(self.video_folder.get())
if f.lower().endswith(('.mp4', '.avi', '.webm', '.mkv', '.flv', '.ts', '.m2ts'))]
self.total = len(self.videos)
self.uploaded = 0
self.errors = 0
self.update_status()
if self.total == 0:
messagebox.showerror("Lỗi", "Không tìm thấy video trong thư mục đã chọn.")
return
self.log("Khởi động ChromeDriver...")
options = Options()
options.add_argument("--start-maximized")
if self.silent_mode.get():
options.add_argument("--headless=new")
options.add_argument("--disable-gpu")
options.add_argument("--no-sandbox")
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
self.log("Đăng nhập vào Ok.ru...")
try:
driver.get("https://ok.ru")
time.sleep(2)
if self.cookie_mode.get() == "TXT File":
cookies = []
try:
with open(cookie_path, "r", encoding="utf-8") as f:
for line in f:
if not line.strip() or line.startswith("#") and not line.startswith("#HttpOnly_"):
continue
if line.startswith("#HttpOnly_"):
line = line[len("#HttpOnly_"):]
parts = line.strip().split("\t")
if len(parts) < 6:
continue
try:
domain = parts[0]
flag = parts[1]
path = parts[2]
secure = parts[3]
expiration = parts[4] if len(parts) > 5 else ""
name = parts[5] if len(parts) > 6 else ""
value = parts[6] if len(parts) > 6 else parts[5] # Trường hợp chỉ có 6 trường
cookie = {
"domain": domain,
"name": name,
"value": value,
"path": path,
"secure": secure.lower() == "true"
}
if expiration.isdigit():
cookie["expiry"] = int(expiration)
cookies.append(cookie)
except Exception as cookie_error:
self.log(f"⚠️ Cookie lỗi bị bỏ qua: {line.strip()} ({cookie_error})")
for cookie in cookies:
driver.add_cookie(cookie)
driver.get("https://ok.ru/video/manager")
time.sleep(5)
except Exception as e:
self.log(f"❌ Lỗi khi tải cookies: {e}")
driver.quit()
return
else:
driver.find_element(By.NAME, "st.email").send_keys(self.username.get())
driver.find_element(By.NAME, "st.password").send_keys(self.password.get())
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, 'input[type="submit"].button-pro'))
).click()
time.sleep(5)
driver.get("https://ok.ru/video/manager")
time.sleep(5)
except Exception as e:
self.log(f"❌ Lỗi khi đăng nhập: {e}")
driver.quit()
return
output_path = os.path.join(self.output_folder.get(), "link.txt")
error_path = os.path.join(self.output_folder.get(), "upload_errors.txt")
for video_file in self.videos:
if self.stop_flag:
self.log("🛑 Dừng upload theo yêu cầu người dùng.")
break
success = False
for attempt in range(3):
try:
file_path = os.path.join(self.video_folder.get(), video_file)
self.log(f"🎞️ [{attempt+1}/3] Upload: {video_file}")
upload_input = driver.find_element(By.CSS_SELECTOR, 'input[type="file"].video-upload-input')
upload_input.send_keys(file_path)
self.log("⏳ Đợi nút Publish (tối đa 20 phút)...")
WebDriverWait(driver, 1200).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "a.js-uploader-publish-link"))
)
publish_btn = driver.find_element(By.CSS_SELECTOR,
"a.button-pro.__small.video-uploader_ac.__publish-btn")
edit_btn = driver.find_element(By.CSS_SELECTOR,
"a.button-pro.__small.__sec.video-uploader_ac.__go-to-editor-btn")
video_href = edit_btn.get_attribute("href")
self.log(f"🔎 href của nút Edit: {video_href}")
if video_href and "/video/editor/" in video_href:
video_id = video_href.split("/")[-1]
video_link = f"https://ok.ru/video/{video_id}"
else:
raise Exception(f"Không lấy được ID video: href={video_href}")
publish_btn.click()
time.sleep(3)
with open(output_path, "a", encoding="utf-8") as f:
f.write(f"{video_file}|{video_link}\n")
self.uploaded += 1
self.log(f"✅ Upload thành công: {video_link}")
success = True
driver.get("https://ok.ru/video/manager")
time.sleep(5)
break
except Exception as e:
self.log(f"⚠️ Thử lại {attempt+1}/3 thất bại: {e}")
time.sleep(3)
# ✅ CHỈ thực hiện sau khi đã thử đủ 3 lần
if not success:
self.errors += 1
self.log(f"❌ Upload thất bại: {video_file}")
with open(error_path, "a", encoding="utf-8") as ef:
ef.write(f"{video_file}\n")
self.update_status()
time.sleep(3)
driver.quit()
self.log("✅ Hoàn tất toàn bộ quá trình upload.")
# Run app
if __name__ == "__main__":
root = Tk()
app = OkRuUploader(root)
root.mainloop()