로컬변경

This commit is contained in:
R5600U_PC 2024-04-08 10:16:17 +09:00
commit 25b6e7ba63
16 changed files with 542 additions and 68 deletions

View File

@ -5,7 +5,7 @@ from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from tqdm import tqdm
# from tqdm import tqdm
from selenium_stealth import stealth
from fake_useragent import UserAgent
import random

View File

@ -1,4 +1,5 @@
from playwright.sync_api import sync_playwright
<<<<<<< HEAD
import random
import logging
@ -72,3 +73,5 @@ def trans_text(original_text):
logger.info("playwright Browser 닫힘.")
return translated_text
=======
>>>>>>> 4b4ff58484a1cc6a2080061367ea02ec8d38e8b7

View File

@ -55,7 +55,10 @@ class ImageDescriptionGenerator:
self.fill_product_info_lists(product_info)
prompt = f'''
주어진 상품 이미지에 대한 정보를 줄께.
나는 타오바오에서 상품을 가져와서 한국의 온라인 쇼핑몰에서 구매대행업을 하는 사업가야.
너는 온라인 쇼핑몰 상세페이지 제작 전문가야. 니가 만든 상품페이지는 모두를 감동시키고, 구매로 이어지는 마법같은 능력이 있어.
이제 주어진 이미지와 내가 원하는 상세페이지에 대한 정보를 줄께.
하나씩 차근차근 진행해보자.
[정보]
A. 해당상품의 타오바오 상품명은 '{product_info.tao_title}'
B. 해당상품의 키워드는 '{product_info.keyword_title}'
@ -79,7 +82,7 @@ class ImageDescriptionGenerator:
4. 상품의 사용상 주의점을 자세히 알려줘
5. 상품의 도움이 될만한 다른 추가정보를 자세하게 알려줘
6. 위의 모든 정보를 바탕으로 상품을 설명한 상품명을 만들어줘 1 만들어줘.
6-1. 상품명 제작 권장 사항 1: 키워드, 용도, 재질, 용량, 형식, 모양,특징등의 단어를 콤마를 제외하고 띄어쓰기로 나열해(용량과 스펙등은 뒤쪽으로 배치).
6-2. 상품명 제작 권장 사항 2: 타오바오 상품명과 옵션이름들에서 상품의 특징을 가져와서 상품명에 사용해야해.

View File

@ -151,10 +151,11 @@ class AutoPercentyProductsDB:
'tag_modification': 'complete',
'option_modification': 'complete',
'detail_page_modification': 'complete',
'thumbnail_modification': 'complete'
# 'thumbnail_modification': 'complete',
'thumbnail_modification': 'complete',
# 'price_modification': 'complete',
# 'title_modification': 'complete'
# 'title_modification': 'complete',
# 'trans_detailImage': 'complete',
# 'upload_to_market': 'complete',
}
# 현재 시간

View File

@ -342,7 +342,7 @@ def create_product_card(product_name, image_url, price, rank, purchase, review):
# return product_info_md
def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver_codes):
def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver_codes, login_info):
detail_css = ".ant-tabs-tab:nth-child(6)"
@ -625,27 +625,33 @@ def modify_detail_page(driver, product_info, gemini, delv_collection, json_naver
logger.error(f"AI 컨텐츠 입력 중 에러발생 : {e}", exc_info=True)
# logger.debug("상세페이지 이미지 번역 시작")
# try:
# for i, detail_image in enumerate(detail_images):
# logger.debug(f"상세페이지 {i+1}번째 이미지 번역 시작")
# logger.debug(f"이미지 타입 : {type(detail_image)}")
# returned_img = image_trans(detail_image, 'translate')
# image_to_clipboard(returned_img)
# logger.debug("번역 완료 및 부텨넣기")
# detail_content.send_keys(Keys.CONTROL, 'v')
# detail_content.send_keys(Keys.ENTER)
# logger.debug(f"{i}번째 이미지 붙여넣기 완료")
# # translated_image_urls.append(returned_img_path)
# logger.debug("이미지 번역 완료")
# except Exception as e:
# logger.error(f"이미지 번역 중 에러발생 : {e}", exc_info=True)
if login_info.whether_modifyImageTanslation:
logger.debug("상세페이지 이미지 번역 시작")
try:
for i, detail_image in enumerate(detail_images):
logger.debug(f"상세페이지 {i+1}번째 이미지 번역 시작")
logger.debug(f"이미지 타입 : {type(detail_image)}")
returned_img = image_trans(detail_image, 'translate')
image_to_clipboard(returned_img)
logger.debug("번역 완료 및 부텨넣기")
detail_content.send_keys(Keys.CONTROL, 'v')
detail_content.send_keys(Keys.ENTER)
logger.debug(f"{i}번째 이미지 붙여넣기 완료")
# translated_image_urls.append(returned_img_path)
logger.debug("이미지 번역 완료")
except Exception as e:
logger.error(f"이미지 번역 중 에러발생 : {e}", exc_info=True)
# logger.debug("====번역이미지 붙여넣기 완료=====")
logger.debug("====번역이미지 붙여넣기 완료=====")
logger.debug("상세페이지 편집 저장")

17
edit/trans_image.py Normal file
View File

@ -0,0 +1,17 @@
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
import time, re, random
from edit.action_elements import click_element, return_element, click_and_confirm_tab
from edit.price_cal import calculate_margin_and_price
# from ai.compare import find_most_similar_image_by_one
import logging
# 로거 인스턴스 가져오기
logger = logging.getLogger('default_logger')
def tran_detail_image(driver, product_infos):
return None

17
edit/uploadMarket.py Normal file
View File

@ -0,0 +1,17 @@
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
import time, re, random
from edit.action_elements import click_element, return_element, click_and_confirm_tab
from edit.price_cal import calculate_margin_and_price
# from ai.compare import find_most_similar_image_by_one
import logging
# 로거 인스턴스 가져오기
logger = logging.getLogger('default_logger')
def upload_to_market(driver, product_infos):
return None

View File

@ -8,6 +8,7 @@ import numpy as np
from img_trans.src.text_detection_with_paddle import detect_text
from img_trans.src.removal import process_image_based_on_text_area
from img_trans.src.translation import translate_texts_translatepy
from img_trans.src.translation import translate_texts_deepl
from img_trans.src.text_insertion import insert_text
from img_trans.src.mini_crop_process import resize_and_crop_image
from img_trans.src.rotate_img import flip_and_rotate_image
@ -68,6 +69,8 @@ def image_trans(image_url, convert_type):
texts_to_translate = [text for _, text, _, _, _ in detected_texts]
logger.debug(f"원본 텍스트: {texts_to_translate}")
translated_texts = translate_texts_translatepy(texts_to_translate)
if not translated_texts: # 빈 리스트 체크
translated_texts = translate_texts_translatepy(texts_to_translate)
logger.debug(f"번역 텍스트: {texts_to_translate}")
# translated_image = insert_text(inpainted_image_path, translated_texts, detected_texts)
translated_image = insert_text(inpainted_image, translated_texts, detected_texts)

View File

@ -1,18 +1,23 @@
from googletrans import Translator
from img_trans.src.deepl import trans
# from img_trans.src.deepl_ori import trans
from ai.deepl import trans
from translatepy import Translator
import logging
# 로거 인스턴스 가져오기
logger = logging.getLogger('default_logger')
def translate_texts_google(texts, src_lang='zh-cn', dest_lang='ko'):
"""텍스트 리스트를 지정된 언어에서 다른 언어로 번역"""
translated_texts = []
translator = Translator()
print(f"texts ======== {texts}")
print(f"texts number ======== {len(texts)}")
logger.debug(f"texts ======== {texts}")
logger.debug(f"texts number ======== {len(texts)}")
try:
translations = translator.translate(texts, src=src_lang, dest=dest_lang)
translated_texts = [translation.text for translation in translations]
except AttributeError as e:
print(f"번역 실패: Google 번역 API의 내부 변경으로 인해 번역을 수행할 수 없습니다. : {e}")
logger.error(f"번역 실패: Google 번역 API의 내부 변경으로 인해 번역을 수행할 수 없습니다. : {e}")
return translated_texts
@ -20,7 +25,8 @@ def translate_texts_deepl(texts):
"""텍스트 리스트를 지정된 언어에서 다른 언어로 번역"""
# 텍스트 리스트를 엔터로 구분된 하나의 문자열로 합침
combined_text = "\n".join(texts)
translated_texts = []
# DeepL로 전체 텍스트 번역
try:
translated_combined_text = trans(combined_text)
@ -30,7 +36,7 @@ def translate_texts_deepl(texts):
# 번역된 전체 텍스트를 엔터를 기준으로 분리하여 리스트로 만듦
translated_texts = translated_combined_text.split("\n")
except AttributeError as e:
print(f"번역 실패: {e}")
logger.error(f"번역 실패: {e}")
translated_texts = []
return translated_texts
@ -40,8 +46,8 @@ def translate_texts_translatepy(texts, src_lang='zh-cn', dest_lang='ko'):
"""translatepy 라이브러리를 사용하여 텍스트 리스트를 번역합니다."""
translator = Translator()
translated_texts = []
print(f"번역대상 텍스트 숫자 ======== {len(texts)}")
print(f"번역대상 텍스트 ======== {texts}")
logger.debug(f"번역대상 텍스트 숫자 ======== {len(texts)}")
logger.debug(f"번역대상 텍스트 ======== {texts}")
for text in texts:
result = translator.translate(text, source_language=src_lang, destination_language=dest_lang)
@ -49,7 +55,7 @@ def translate_texts_translatepy(texts, src_lang='zh-cn', dest_lang='ko'):
# "가격"이 포함된 경우 빈 문자열로 대체
translated_texts.append(translation if "가격" not in translation else "")
print(f"번역된 감지 텍스트 \n {translated_texts}")
logger.debug(f"번역된 감지 텍스트 \n {translated_texts}")
return translated_texts
@ -57,8 +63,8 @@ def translate_texts_translatepy(texts, src_lang='zh-cn', dest_lang='ko'):
# texts = ["Hello, world!", "This is a test translation."]
# translated_texts = translate_texts_translatepy(texts, src_lang='en', dest_lang='ko')
# for text, translated in zip(texts, translated_texts):
# print(f'{text} => {translated}')
# logger.debug(f'{text} => {translated}')
# text='老顾客多次回购'
# trans_ted = translate_texts_deepl(text)
# print(f"trans_ted : {trans_ted}")
# logger.debug(f"trans_ted : {trans_ted}")

View File

@ -3,6 +3,8 @@ from PyQt5.QtCore import Qt, QSettings
from PyQt5 import QtWidgets, QtCore, QtWidgets
from datetime import datetime
from credentials import load_credentials, save_credentials
from src.toggleSwitch import ToggleSwitch # toggle_switch.py에서 ToggleSwitch 클래스를 import
import sys
import logging
@ -30,14 +32,43 @@ class LoginWidget(QtWidgets.QWidget):
self.per_mode = False
self.set_num_modify = 0
self.alwaysOnTopSwitch = True
self.whether_shutdownAfterComplete = False
self.whether_modifyProductName = False
self.whether_modifyProductOptions = True
self.whether_modifyProductTag = True
self.whether_modifyProductPrice = False
self.whether_modifyProductThumb = True
self.whether_modifyProductDetail = True
self.whether_modifyImageTanslation = False
self.whether_uploadToMarket = False
self.check_for_updates(self.login_db, self.CURRENT_VERSION)
def initUI(self):
self.setGeometry(780, 420, 240, 200)
# self.setGeometry(780, 420, 240, 200)
layout = QtWidgets.QVBoxLayout()
# 위젯의 크기를 설정합니다.
self.resize(800, 800)
self.center() # 화면 가운데에 위치시키는 메서드
# 레이아웃 설정
layout = QtWidgets.QHBoxLayout()
login_info_frame = QtWidgets.QFrame()
login_layout = QtWidgets.QVBoxLayout()
login_info_frame.setLayout(login_layout)
# 선택사항 영역
setting_frame = QtWidgets.QFrame()
setting_layout = QtWidgets.QVBoxLayout()
setting_frame.setLayout(setting_layout)
# 레이아웃 설정
layout.addWidget(login_info_frame)
layout.addWidget(setting_frame)
self.signupButton = QtWidgets.QPushButton("회원 가입")
self.signupButton.clicked.connect(self.showSignUpWindow)
@ -76,7 +107,7 @@ class LoginWidget(QtWidgets.QWidget):
self.infoLabel3 = QtWidgets.QLabel("=====================================")
# 토글 버튼 추가
self.changeModeButton = QtWidgets.QPushButton("관리자용모드")
self.changeModeButton = QtWidgets.QPushButton("관리자용 모드")
self.changeModeButton.setCheckable(True)
self.changeModeButton.clicked.connect(self.toggleMode)
# 초기 토글 상태 설정
@ -94,27 +125,204 @@ class LoginWidget(QtWidgets.QWidget):
self.loginButton = QtWidgets.QPushButton("로그인")
self.loginButton.clicked.connect(self.login)
self.alwaysOnTopSwitch = ToggleSwitch(self)
self.alwaysOnTopSwitch.move(10, 10)
self.alwaysOnTopSwitch.setChecked(True) # 기본 상태는 ON
self.alwaysOnTopSwitch.clicked.connect(self.toggleAlwaysOnTop)
self.alwaysOnTopSwitch_layout = self.create_label_and_switch("항상 위에 표시", self.alwaysOnTopSwitch)
self.shutdownSwitch = ToggleSwitch(self)
self.shutdownSwitch.move(10, 50)
self.shutdownSwitch.setChecked(False) # 기본 상태는 OFF
self.shutdownSwitch.clicked.connect(self.shutdownAfterComplete)
self.shutdownSwitch_layout = self.create_label_and_switch("작업 종료 후 PC 종료", self.shutdownSwitch)
self.modifyProductNameSwitch = ToggleSwitch(self)
self.modifyProductNameSwitch.move(10, 90)
self.modifyProductNameSwitch.setChecked(False) # 기본 상태는 OFF
self.modifyProductNameSwitch.clicked.connect(self.modifyProductName)
self.modifyProductNameSwitch_layout = self.create_label_and_switch("상품명 수정", self.modifyProductNameSwitch)
self.modifyProductOptionsSwitch = ToggleSwitch(self)
self.modifyProductOptionsSwitch.move(10, 90)
self.modifyProductOptionsSwitch.setChecked(True) # 기본 상태는 OFF
self.modifyProductOptionsSwitch.clicked.connect(self.modifyProductOptions)
self.modifyProductOptionsSwitch_layout = self.create_label_and_switch("옵션명 수정", self.modifyProductOptionsSwitch)
self.modifyProductTagSwitch = ToggleSwitch(self)
self.modifyProductTagSwitch.move(10, 90)
self.modifyProductTagSwitch.setChecked(True) # 기본 상태는 OFF
self.modifyProductTagSwitch.clicked.connect(self.modifyProductTag)
self.modifyProductTagSwitch_layout = self.create_label_and_switch("태그 수정", self.modifyProductTagSwitch)
self.modifyProductPriceSwitch = ToggleSwitch(self)
self.modifyProductPriceSwitch.move(10, 90)
self.modifyProductPriceSwitch.setChecked(False) # 기본 상태는 OFF
self.modifyProductPriceSwitch.clicked.connect(self.modifyProductPrice)
self.modifyProductPriceSwitch_layout = self.create_label_and_switch("가격 수정", self.modifyProductPriceSwitch)
self.modifyProductThumbSwitch = ToggleSwitch(self)
self.modifyProductThumbSwitch.move(10, 90)
self.modifyProductThumbSwitch.setChecked(True) # 기본 상태는 OFF
self.modifyProductThumbSwitch.clicked.connect(self.modifyProductThumb)
self.modifyProductThumbSwitch_layout = self.create_label_and_switch("썸네일 수정", self.modifyProductThumbSwitch)
self.modifyProductDetailSwitch = ToggleSwitch(self)
self.modifyProductDetailSwitch.move(10, 90)
self.modifyProductDetailSwitch.setChecked(True) # 기본 상태는 OFF
self.modifyProductDetailSwitch.clicked.connect(self.modifyProductDetail)
self.modifyProductDetailSwitch_layout = self.create_label_and_switch("상세페이지 수정", self.modifyProductDetailSwitch)
self.modifyImageTranslationSwitch = ToggleSwitch(self)
self.modifyImageTranslationSwitch.move(10, 90)
self.modifyImageTranslationSwitch.setChecked(False) # 기본 상태는 OFF
self.modifyImageTranslationSwitch.clicked.connect(self.modifyImageTranslation)
self.modifyImageTranslationSwitch_layout = self.create_label_and_switch("이미지 번역", self.modifyImageTranslationSwitch)
self.uploadToMarketSwitch = ToggleSwitch(self)
self.uploadToMarketSwitch.move(10, 90)
self.uploadToMarketSwitch.setChecked(False) # 기본 상태는 OFF
self.uploadToMarketSwitch.clicked.connect(self.uploadToMarket)
self.uploadToMarketSwitch_layout = self.create_label_and_switch("마켓 업로드", self.uploadToMarketSwitch)
self.infoLabel4 = QtWidgets.QLabel(" 퍼센티 자동화 by 리앤수Int.")
layout.addWidget(self.signupButton)
layout.addWidget(self.infoLabel)
layout.addWidget(self.emailInput)
layout.addWidget(self.passwordInput)
layout.addWidget(self.infoLabel2)
layout.addWidget(self.per_emailInput)
layout.addWidget(self.per_em_emailInput)
layout.addWidget(self.per_em_passwordInput)
layout.addWidget(self.per_passwordInput)
layout.addWidget(self.changeModeButton)
layout.addWidget(self.set_num_modifyInput)
layout.addWidget(self.infoLabel5)
layout.addWidget(self.infoLabel3)
layout.addWidget(self.showPasswordCheckBox)
layout.addWidget(self.loginButton)
layout.addWidget(self.infoLabel4)
login_layout.addWidget(self.infoLabel)
login_layout.addWidget(self.signupButton)
login_layout.addWidget(self.infoLabel)
login_layout.addWidget(self.emailInput)
login_layout.addWidget(self.passwordInput)
login_layout.addWidget(self.infoLabel2)
login_layout.addWidget(self.per_emailInput)
login_layout.addWidget(self.per_em_emailInput)
login_layout.addWidget(self.per_em_passwordInput)
login_layout.addWidget(self.per_passwordInput)
login_layout.addWidget(self.changeModeButton)
login_layout.addWidget(self.set_num_modifyInput)
login_layout.addWidget(self.infoLabel5)
login_layout.addWidget(self.infoLabel3)
login_layout.addWidget(self.showPasswordCheckBox)
login_layout.addWidget(self.loginButton)
login_layout.addWidget(self.infoLabel4)
# labels = ["항상 위", "작업완료 후 PC종료", "상품명 수정", "옵션 수정", "가격 수정", "태그 수정", "썸네일 수정", "상세페이지 수정", "이미지 번역", "마켓 업로드"]
# for i, label_text in enumerate(labels, start = 1):
# label = QtWidgets.QLabel(label_text)
# setting_layout.addWidget(label) # 설명 라벨은 2열(인덱스 1)에 배치
setting_layout.addLayout(self.modifyProductNameSwitch_layout)
setting_layout.addLayout(self.modifyProductOptionsSwitch_layout)
setting_layout.addLayout(self.modifyProductPriceSwitch_layout)
setting_layout.addLayout(self.modifyProductTagSwitch_layout)
setting_layout.addLayout(self.modifyProductThumbSwitch_layout)
setting_layout.addLayout(self.modifyProductDetailSwitch_layout)
setting_layout.addLayout(self.modifyImageTranslationSwitch_layout)
setting_layout.addLayout(self.uploadToMarketSwitch_layout)
setting_layout.addLayout(self.alwaysOnTopSwitch_layout)
setting_layout.addLayout(self.shutdownSwitch_layout)
self.setLayout(layout)
self.setWindowTitle('AutoPercenty')
def create_label_and_switch(self, label_text, target_switch):
layout = QtWidgets.QHBoxLayout()
label = QtWidgets.QLabel(label_text)
layout.addWidget(label)
layout.addWidget(target_switch)
return layout
def center(self):
# 화면 중앙에 위치시키기 위한 계산
qr = self.frameGeometry() # 위젯의 직사각형 정보를 얻습니다.
cp = QtWidgets.QDesktopWidget().availableGeometry().center() # 사용 가능한 화면의 중앙 위치를 얻습니다.
qr.moveCenter(cp) # 직사각형의 중심을 화면의 중심 위치로 이동시킵니다.
self.move(qr.topLeft()) # 위젯의 시작점을 직사각형의 시작점으로 이동시켜 화면 중앙에 위치시킵니다.
def toggleAlwaysOnTop(self, checked):
if checked:
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
else:
self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
def shutdownAfterComplete(self, checked):
if checked:
self.whether_shutdownAfterComplete = True
else:
self.whether_shutdownAfterComplete = False
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
def modifyProductName(self, checked):
if checked:
self.whether_modifyProductName = True
else:
self.whether_modifyProductName = False
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
def modifyProductOptions(self, checked):
if checked:
self.whether_modifyProductOptions = True
else:
self.whether_modifyProductOptions = False
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
def modifyProductTag(self, checked):
if checked:
self.whether_modifyProductTag = True
else:
self.whether_modifyProductTag = False
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
def modifyProductPrice(self, checked):
if checked:
self.whether_modifyProductPrice = True
else:
self.whether_modifyProductPrice = False
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
def modifyProductThumb(self, checked):
if checked:
self.whether_modifyProductThumb = True
else:
self.whether_modifyProductThumb = False
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
def modifyProductDetail(self, checked):
if checked:
self.whether_modifyProductDetail = True
else:
self.whether_modifyProductDetail = False
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
def modifyImageTranslation(self, checked):
if checked:
self.whether_modifyImageTanslation = True
else:
self.whether_modifyImageTanslation = False
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
def uploadToMarket(self, checked):
if checked:
self.whether_uploadToMarket = True
else:
self.whether_uploadToMarket = False
self.show() # 변경된 윈도우 플래그를 적용하기 위해 위젯을 다시 보여줘야 함
def togglePasswordVisibility(self):
if self.showPasswordCheckBox.isChecked():

44
main.py
View File

@ -5,8 +5,10 @@ from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service #웨일
# from webdriver_manager.chrome import ChromeDriverManager #웨일
import time
import datetime
import ctypes
import atexit
import platform, os, sys
from login import login
import sys
@ -56,6 +58,27 @@ def send_exit_message():
# 이 함수에서는 사용자에게 프로그램 종료 메시지를 보내는 로직을 구현해야 합니다.
# 여기서는 예시로 로깅만 수행합니다.
logger.info("프로그램이 종료되었습니다. 안녕히 가세요.")
def shutdown_system():
"""
시스템을 종료시키는 메서드. 운영 체제를 확인하고 적절한 종료 명령을 실행합니다.
"""
logger.info("프로그램이 종료되었습니다. 1초 후 컴퓨터가 종료됩니다. 안녕히 가세요.")
try:
operating_system = platform.system()
if operating_system == "Windows":
os.system("shutdown /s /t 1") # Windows에서 시스템 종료
elif operating_system == "Linux" or operating_system == "Darwin":
os.system("shutdown -h now") # Linux와 macOS에서 시스템 종료
else:
print("Unsupported operating system.")
sys.exit(1)
print("System shutdown command executed.")
except Exception as e:
print(f"Failed to shutdown the system: {e}")
sys.exit(1)
def DB_setting():
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts)
@ -79,22 +102,35 @@ def DB_setting():
"per_em_password": login_widget.per_em_password,
"per_mode": login_widget.per_mode,
"set_num_modify": login_widget.set_num_modify,
"login_result": login_widget.result # 로그인 결과도 함께 반환
"alwaysOnTopSwitch": login_widget.alwaysOnTopSwitch,
"whether_shutdownAfterComplete" : login_widget.whether_shutdownAfterComplete,
"whether_modifyProductName": login_widget.whether_modifyProductName,
"whether_modifyProductOptions": login_widget.whether_modifyProductOptions,
"whether_modifyProductTag": login_widget.whether_modifyProductTag,
"whether_modifyProductPrice": login_widget.whether_modifyProductPrice,
"whether_modifyProductThumb": login_widget.whether_modifyProductThumb,
"whether_modifyProductDetail": login_widget.whether_modifyProductDetail,
"whether_modifyImageTanslation": login_widget.whether_modifyImageTanslation,
"whether_uploadToMarket": login_widget.whether_uploadToMarket,
"login_result": login_widget.result,
}
return login_info, result, mongo_config
def main():
login_info, app_result, mongo_config = DB_setting() # 로그인 정보와 QApplication 실행 결과를 받음
# 화면 꺼짐과 절전 모드 방지 기능 활성화
prevent_sleep_mode()
# 프로그램 종료 시 호출될 함수 등록
atexit.register(restore_sleep_mode)
atexit.register(record_logout_time)
atexit.register(send_exit_message)
login_info, app_result, mongo_config = DB_setting() # 로그인 정보와 QApplication 실행 결과를 받음
if login_info.whether_shutdownAfterComplete:
atexit.register(shutdown_system)
atexit.register(send_exit_message)
if not login_info["login_result"]:
logger.debug("사용자 인증 실패로 프로그램을 종료합니다.")

71
mainwindow.py Normal file
View File

@ -0,0 +1,71 @@
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QLabel, QPushButton, QTextEdit
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service #웨일
# from webdriver_manager.chrome import ChromeDriverManager #웨일
import time
import ctypes
import atexit
from login import login
import sys
from navigate import navigate_to_new_product_registration
from modify_products import modify_products
from database import setup_database
from utils import log
from config import WEBSITE_URL
from credentials import load_credentials, save_credentials
from ai.gemini import ImageDescriptionGenerator
from login_widget import LoginWidget
from mongo_config import MongoConfig
from PyQt5 import QtCore, QtWidgets
from logger_module import setup_logger
import logging
class MainWindow(QWidget):
def __init__(self, mongo_config, logger, CURRENT_VERSION):
super().__init__()
self.mongo_config = mongo_config
self.logger = logger
self.CURRENT_VERSION = CURRENT_VERSION
self.initUI()
def initUI(self):
self.setWindowTitle('AutoPercenty by 리앤수인터')
self.setGeometry(300, 300, 600, 500) # 위치와 크기 설정
grid = QGridLayout()
self.setLayout(grid)
# 로그인 정보와 작업 상태 정보 라벨 추가
self.loginInfoLabel = QLabel('로그인 정보가 여기 표시됩니다.')
grid.addWidget(self.loginInfoLabel, 0, 0, 1, 2)
self.workStatusLabel = QLabel('작업 상태 정보가 여기 표시됩니다.')
grid.addWidget(self.workStatusLabel, 0, 2, 1, 1)
# 로그인 버튼 추가
self.loginButton = QPushButton('로그인')
self.loginButton.clicked.connect(self.openLoginWidget)
grid.addWidget(self.loginButton, 1, 0)
# 로그 박스 추가
self.logBox = QTextEdit()
self.logBox.setReadOnly(True)
grid.addWidget(self.logBox, 2, 0, 3, 3) # 2행 0열부터 4행 2열까지
def openLoginWidget(self):
# 여기서 LoginWidget 인스턴스를 생성하고 표시합니다.
self.login_widget = LoginWidget(self.mongo_config, self.CURRENT_VERSION)
self.login_widget.show()
def main():
CURRENT_VERSION = "1.0.1"
app = QApplication(sys.argv)
mongo_config = MongoConfig()
logger = setup_logger('default_logger', 'application.log', level=logging.DEBUG)
main_window = MainWindow(mongo_config, logger,CURRENT_VERSION)
main_window.show()
sys.exit(app.exec_())

View File

@ -14,6 +14,8 @@ from edit.options import modify_option_page
from edit.price import modify_price_page
from edit.title import modify_product_title
from edit.thumbnail import modify_thumb_page
from edit.trans_image import *
from edit.uploadMarket import *
from edit.action_elements import click_element, return_element, wait_element
import logging
@ -63,6 +65,20 @@ logger = logging.getLogger('default_logger')
# 'title_modification': modify_product_title,
# }
def should_execute_step(step_name, login_info):
if step_name == 'tag_modification':
return login_info.whether_modifyProductTag
elif step_name == 'thumbnail_modification':
return login_info.whether_modifyProductThumb
elif step_name == 'option_modification':
return login_info.whether_modifyProductOptions
elif step_name == 'detail_page_modification':
return login_info.whether_modifyProductDetail
elif step_name == 'price_modification':
return login_info.whether_modifyProductPrice
else:
return True
def perform_step(db, step_name, action, current_user, *args):
"""
단계별 작업을 수행하는 함수.
@ -170,11 +186,25 @@ def modify_products(driver, gemini, mongo_config, login_info, set_num_modify):
('tag_modification', edit_tag, (driver, product_infos[i-1])),
('thumbnail_modification', modify_thumb_page, (driver, product_infos[i-1])),
('option_modification', modify_option_page, (driver, product_infos[i-1])),
('detail_page_modification', modify_detail_page, (driver, product_infos[i-1], gemini, delv_collection, json_naver_codes)),
# ('price_modification', modify_price_page, (driver, product_infos[i-1])),
# 'title_modification' 단계와 관련된 함수 호출은 여기에 추가합니다.
('detail_page_modification', modify_detail_page, (driver, product_infos[i-1], gemini, delv_collection, json_naver_codes, login_info)),
('price_modification', modify_price_page, (driver, product_infos[i-1])),
('title_modification', modify_product_title, (driver, product_infos[i-1])),
('trans_detailImage', tran_detail_image, (driver, product_infos[i-1])),
('upload_to_market', upload_to_market, (driver, product_infos[i-1])),
]
# 상품 수정 관련 작업을 조건에 따라 수행하는 로직
step_conditions = {
'tag_modification': login_info.whether_modifyProductTag,
'thumbnail_modification': login_info.whether_modifyProductThumb,
'option_modification': login_info.whether_modifyProductOptions,
'detail_page_modification': login_info.whether_modifyProductDetail,
'price_modification': login_info.whether_modifyProductPrice,
'title_modification': login_info.whether_modifyProductName,
'trans_detailImage': login_info.whether_modifyImageTanslation,
'upload_to_market': login_info.whether_uploadToMarket,
}
# 상품ID 복사
try:
product_id_element = return_element(driver,"XPATH",f"//div[{i}]/li/div/div/div[2]/div/div/div/div[3]/div[3]/span[2]/span",10)
@ -205,9 +235,11 @@ def modify_products(driver, gemini, mongo_config, login_info, set_num_modify):
time.sleep(2)
for step_name, action, args in steps_and_actions:
if step_name in incomplete_steps:
perform_step(autoPercentyProductsDB, step_name, action, current_user, *args)
autoPercentyProductsDB.finalize_product_processing(product_id, current_user, product_infos[i-1])
logger.info(f"상품 ID {product_id}의 미완성 목록을 완성했습니다.")
# 각 단계별 실행 여부 판단
if step_conditions.get(step_name, False):
perform_step(autoPercentyProductsDB, step_name, action, current_user, *args)
autoPercentyProductsDB.finalize_product_processing(product_id, current_user, product_infos[i-1])
logger.info(f"상품 ID {product_id}의 미완성 목록을 완성했습니다.")
pass
else:
# 여기에는 incomplete_steps가 False이거나 리스트의 길이가 6인 경우.
@ -356,7 +388,9 @@ def modify_products(driver, gemini, mongo_config, login_info, set_num_modify):
# 각 단계별로 수정 작업 수행
for step_name, action, args in steps_and_actions:
perform_step(autoPercentyProductsDB, step_name, action, current_user, *args)
# 각 단계별 실행 여부 판단
if step_conditions.get(step_name, False):
perform_step(autoPercentyProductsDB, step_name, action, current_user, *args)
# 모든 단계가 완료되었다면, 상품 처리 최종화
autoPercentyProductsDB.finalize_product_processing(product_infos[i-1].id, current_user, product_infos[i-1])

0
src/_init.py Normal file
View File

69
src/toggleSwitch.py Normal file
View File

@ -0,0 +1,69 @@
from PyQt5.QtCore import Qt, QRect, QPropertyAnimation, pyqtProperty, pyqtSignal, QPoint
from PyQt5.QtGui import QPainter, QColor
from PyQt5.QtWidgets import QWidget
class ToggleSwitch(QWidget):
clicked = pyqtSignal(bool)
def __init__(self, parent=None):
super(ToggleSwitch, self).__init__(parent)
self.setFixedSize(60, 30)
self._checked = False
self._circle_color_checked = QColor('red')
self._circle_color_unchecked = QColor('gray')
self._background_color = QColor('white')
self._circle_pos = QPoint(0, 0) # Circle's initial position.
self.animation = QPropertyAnimation(self, b"circle_pos")
self.animation.setDuration(250)
self._init_position()
@pyqtProperty(QPoint)
def circle_pos(self):
return self._circle_pos
@circle_pos.setter
def circle_pos(self, pos):
self._circle_pos = pos
self.update()
def _init_position(self):
if self._checked:
self._circle_pos.setX(30)
else:
self._circle_pos.setX(0)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self._checked = not self._checked
self.clicked.emit(self._checked)
self._update_animation()
self.update()
super(ToggleSwitch, self).mousePressEvent(event)
def _update_animation(self):
if self._checked:
self.animation.setStartValue(QPoint(0, 0))
self.animation.setEndValue(QPoint(30, 0))
else:
self.animation.setStartValue(QPoint(30, 0))
self.animation.setEndValue(QPoint(0, 0))
self.animation.start()
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setPen(Qt.NoPen)
painter.setBrush(self._background_color)
painter.drawRoundedRect(QRect(0, 0, 60, 30), 15, 15)
circle_color = self._circle_color_checked if self._checked else self._circle_color_unchecked
painter.setBrush(circle_color)
painter.drawEllipse(self._circle_pos.x(), self._circle_pos.y(), 30, 30)
def setChecked(self, checked):
if self._checked != checked:
self._checked = checked
self._update_animation()
self.update()