v0.1.1 윈도우 환경 지원 추가
윈도우 환경 지원 추가 다운로드 실패 시 임시파일 삭제가 안 되는 문제 수정
This commit is contained in:
@@ -9,5 +9,9 @@ SJVA에서 유튜브 등 동영상 사이트 영상을 다운로드할 수 있
|
|||||||
일단 어느 정도 코드가 정리되면 그때 화질 선택 등 옵션을 추가할 예정
|
일단 어느 정도 코드가 정리되면 그때 화질 선택 등 옵션을 추가할 예정
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
v0.1.1
|
||||||
|
* 윈도우 환경 지원 추가
|
||||||
|
* 다운로드 실패 시 임시파일 삭제가 안 되는 문제 수정
|
||||||
|
|
||||||
v0.1.0
|
v0.1.0
|
||||||
* 최초 공개
|
* 최초 공개
|
||||||
|
|||||||
22
logic.py
22
logic.py
@@ -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'])
|
||||||
|
|||||||
2
model.py
2
model.py
@@ -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
|
||||||
|
|||||||
27
plugin.py
27
plugin.py
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user