v0.1.1 윈도우 환경 지원 추가

윈도우 환경 지원 추가
다운로드 실패 시 임시파일 삭제가 안 되는 문제 수정
This commit is contained in:
joyfuI
2020-02-06 23:43:13 +09:00
parent 3b157491c6
commit b26f25a413
5 changed files with 49 additions and 27 deletions

View File

@@ -9,5 +9,9 @@ SJVA에서 유튜브 등 동영상 사이트 영상을 다운로드할 수 있
일단 어느 정도 코드가 정리되면 그때 화질 선택 등 옵션을 추가할 예정 일단 어느 정도 코드가 정리되면 그때 화질 선택 등 옵션을 추가할 예정
## Changelog ## Changelog
v0.1.1
* 윈도우 환경 지원 추가
* 다운로드 실패 시 임시파일 삭제가 안 되는 문제 수정
v0.1.0 v0.1.0
* 최초 공개 * 최초 공개

View File

@@ -3,11 +3,13 @@
# python # python
import os import os
import traceback import traceback
import platform
import subprocess
# third-party # third-party
# sjva 공용 # sjva 공용
from framework import db, path_data from framework import db, path_app_root, path_data
from framework.util import Util from framework.util import Util
# 패키지 # 패키지
@@ -37,8 +39,11 @@ class Logic(object):
def plugin_load(): def plugin_load():
try: try:
logger.debug('%s plugin_load', package_name) logger.debug('%s plugin_load', package_name)
# DB 초기화 Logic.db_init() # DB 초기화
Logic.db_init() if platform.system() == 'Windows': # 윈도우일 때
Logic.youtube_dl_path = os.path.join(path_app_root, 'bin', 'Windows', 'youtube-dl.exe')
if not os.path.isfile(Logic.youtube_dl_path): # youtube-dl.exe가 없으면
Logic.youtube_dl_update()
# 편의를 위해 json 파일 생성 # 편의를 위해 json 파일 생성
from plugin import plugin_info from plugin import plugin_info
@@ -78,3 +83,14 @@ class Logic(object):
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
######################################################### #########################################################
youtube_dl_path = 'youtube-dl'
youtube_dl_list = []
@staticmethod
def youtube_dl_update():
if platform.system() == 'Windows': # 윈도우일 때
subprocess.call(['powershell', "(new-Object System.Net.WebClient).DownloadFile('https://yt-dl.org/latest/youtube-dl.exe', '%s')" % os.path.join(path_app_root, 'bin', 'Windows', 'youtube-dl.exe')])
else: # 나머지 Unix-like
subprocess.call(['curl', '-L', 'https://yt-dl.org/downloads/latest/youtube-dl', '-o', '/usr/local/bin/youtube-dl'])
subprocess.call(['chmod', 'a+rx', '/usr/local/bin/youtube-dl'])

View File

@@ -12,7 +12,7 @@ from framework import db, app, path_app_root
from .plugin import package_name from .plugin import package_name
db_file = os.path.join(path_app_root, 'data', 'db', '%s.db' % package_name) db_file = os.path.join(path_app_root, 'data', 'db', '%s.db' % package_name)
app.config['SQLALCHEMY_BINDS'][package_name] = 'sqlite:///%s' % (db_file) app.config['SQLALCHEMY_BINDS'][package_name] = 'sqlite:///%s' % db_file
class ModelSetting(db.Model): class ModelSetting(db.Model):
__tablename__ = 'plugin_%s_setting' % package_name __tablename__ = 'plugin_%s_setting' % package_name

View File

@@ -35,12 +35,12 @@ def plugin_unload():
Logic.plugin_unload() Logic.plugin_unload()
plugin_info = { plugin_info = {
'version': '0.1.0', 'version': '0.1.1',
'name': 'youtube-dl', 'name': 'youtube-dl',
'category_name': 'vod', 'category_name': 'vod',
'icon': '', 'icon': '',
'developer': 'joyfuI', 'developer': 'joyfuI',
'description': 'youtube-dl', 'description': '유튜브, 네이버TV 등 동영상 사이트에서 동영상 다운로드',
'home': 'https://github.com/joyfuI/youtube-dl', 'home': 'https://github.com/joyfuI/youtube-dl',
'more': '' 'more': ''
} }
@@ -54,10 +54,6 @@ menu = {
'category': 'vod' 'category': 'vod'
} }
#########################################################
youtube_dl_list = []
######################################################### #########################################################
# WEB Menu # WEB Menu
######################################################### #########################################################
@@ -73,19 +69,19 @@ def detail(sub):
setting_list = db.session.query(ModelSetting).all() setting_list = db.session.query(ModelSetting).all()
arg = Util.db_list_to_dict(setting_list) arg = Util.db_list_to_dict(setting_list)
arg['package_name'] = package_name arg['package_name'] = package_name
arg['youtube_dl_path'] = 'youtube-dl' arg['youtube_dl_path'] = Logic.youtube_dl_path
return render_template('%s_setting.html' % (package_name), arg=arg) return render_template('%s_setting.html' % package_name, arg=arg)
elif sub == 'download': elif sub == 'download':
arg = { } arg = { }
arg['package_name'] = package_name arg['package_name'] = package_name
arg['file_name'] = '%(title)s-%(id)s.%(ext)s' arg['file_name'] = '%(title)s-%(id)s.%(ext)s'
return render_template('%s_download.html' % (package_name), arg=arg) return render_template('%s_download.html' % package_name, arg=arg)
elif sub == 'list': elif sub == 'list':
arg = { } arg = { }
arg['package_name'] = package_name arg['package_name'] = package_name
return render_template('%s_list.html' % (package_name), arg=arg) return render_template('%s_list.html' % package_name, arg=arg)
elif sub == 'log': elif sub == 'log':
return render_template('log.html', package=package_name) return render_template('log.html', package=package_name)
@@ -106,12 +102,11 @@ def ajax(sub):
return jsonify(ret) return jsonify(ret)
elif sub == 'youtube_dl_version': elif sub == 'youtube_dl_version':
ret = subprocess.check_output(['youtube-dl', '--version']) ret = subprocess.check_output([Logic.youtube_dl_path, '--version'])
return jsonify(ret) return jsonify(ret)
elif sub == 'youtube_dl_update': elif sub == 'youtube_dl_update':
subprocess.call(['curl', '-L', 'https://yt-dl.org/downloads/latest/youtube-dl', '-o', '/usr/local/bin/youtube-dl']) Logic.youtube_dl_update()
subprocess.call(['chmod', 'a+rx', '/usr/local/bin/youtube-dl'])
return jsonify([]) return jsonify([])
elif sub == 'download': elif sub == 'download':
@@ -120,13 +115,13 @@ def ajax(sub):
temp_path = Logic.get_setting_value('temp_path') temp_path = Logic.get_setting_value('temp_path')
save_path = Logic.get_setting_value('save_path') save_path = Logic.get_setting_value('save_path')
youtube_dl = Youtube_dl(url, filename, temp_path, save_path) youtube_dl = Youtube_dl(url, filename, temp_path, save_path)
youtube_dl_list.append(youtube_dl) # 리스트 추가 Logic.youtube_dl_list.append(youtube_dl) # 리스트 추가
youtube_dl.start() youtube_dl.start()
return jsonify([]) return jsonify([])
elif sub == 'list': elif sub == 'list':
ret = [] ret = []
for i in youtube_dl_list: for i in Logic.youtube_dl_list:
data = { } data = { }
data['url'] = i.url data['url'] = i.url
data['filename'] = i.filename data['filename'] = i.filename
@@ -155,7 +150,7 @@ def ajax(sub):
elif sub == 'stop': elif sub == 'stop':
index = int(request.form['index']) index = int(request.form['index'])
youtube_dl_list[index].stop() Logic.youtube_dl_list[index].stop()
return jsonify([]) return jsonify([])
except Exception as e: except Exception as e:
logger.error('Exception:%s', e) logger.error('Exception:%s', e)

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# python # python
import os import os
import platform
from threading import Thread from threading import Thread
import subprocess import subprocess
import json import json
@@ -9,6 +10,7 @@ from enum import Enum
# 패키지 # 패키지
from .plugin import logger from .plugin import logger
from .logic import Logic
class Status(Enum): class Status(Enum):
READY = 0 READY = 0
@@ -53,28 +55,33 @@ class Youtube_dl(object):
def run(self): def run(self):
command = [ command = [
'youtube-dl', Logic.youtube_dl_path,
'--print-json', '--print-json',
'-o', self.temp_path + '/' + self.filename, '-o', os.path.join(self.temp_path, self.filename),
'--exec', 'mv {} ' + self.save_path + '/', '--exec', 'move /y {} ' + self.save_path + '\\' if platform.system() == 'Windows' else 'mv -f {} ' + self.save_path + '/',
self.url self.url
] ]
logger.debug(command)
self._process = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True) # youtube-dl 실행 self._process = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True) # youtube-dl 실행
data = json.loads(self._process.stdout.readline()) # 파일 정보 data = json.loads(self._process.stdout.readline()) # 파일 정보
self.filename = data['_filename'].split('/')[-1] self.filename = os.path.basename(data['_filename'])
self.duration = data['duration'] self.duration = data['duration']
self.format = data['format'] self.format = data['format']
self.status = Status.START self.status = Status.START
self.errorlevel = self._process.wait() # 실행 결과 self.errorlevel = self._process.wait() # 실행 결과
logger.debug('returncode %d', self.errorlevel)
self.end_time = datetime.now() self.end_time = datetime.now()
if self.errorlevel == 0: # 다운로드 성공 if self.errorlevel == 0: # 다운로드 성공
self.status = Status.SUCCESS self.status = Status.SUCCESS
else: # 다운로드 실패 else: # 다운로드 실패
logger.debug('returncode %d', self.errorlevel)
if self.status != Status.STOP: if self.status != Status.STOP:
self.status = Status.FAILURE self.status = Status.FAILURE
logger.debug('rm -f ' + self.temp_path + '/' + ''.join(str.split('.')[:-1]) + '*') if platform.system() == 'Windows': # 윈도우일 때
os.system('rm -f ' + self.temp_path + '/' + ''.join(str.split('.')[:-1]) + '*') # 임시 파일 삭제 logger.debug('del /q "' + self.temp_path + '\\' + ''.join(self.filename.split('.')[:-1]) + '"*')
os.system('del /q "' + self.temp_path + '\\' + ''.join(self.filename.split('.')[:-1]) + '"*') # 임시파일 삭제
else:
logger.debug('rm -f "' + self.temp_path + '/' + ''.join(self.filename.split('.')[:-1]) + '"*')
os.system('rm -f "' + self.temp_path + '/' + ''.join(self.filename.split('.')[:-1]) + '"*') # 임시파일 삭제
def stop(self): def stop(self):
self.status = Status.STOP self.status = Status.STOP