├── .gitignore ├── LICENSE.txt ├── README.md ├── app ├── __init__.py ├── compile_linux.sh ├── config.ini ├── config.py ├── favicon.ico ├── main.py ├── ui │ ├── __init__.py │ ├── about_widget.py │ ├── about_widget.ui │ ├── files_list_dialog.py │ ├── files_list_dialog.ui │ ├── icon.qrc │ ├── icon_rc.py │ ├── main_window.py │ ├── main_window.ui │ ├── proxy_dialog.py │ ├── proxy_dialog.ui │ ├── res │ │ └── favicon.ico │ ├── task_item.ui │ ├── ui_about_widget.py │ ├── ui_design.pro │ ├── ui_design.pro.user │ ├── ui_files_list_dialog.py │ ├── ui_main_window.py │ ├── ui_proxy_dialog.py │ └── ui_task_item.py ├── util │ ├── __init__.py │ ├── config_utils.py │ ├── download_thread.py │ ├── proxy.py │ └── status.py └── you_get │ ├── __init__.py │ ├── cli_wrapper │ ├── __init__.py │ ├── downloader │ │ └── __init__.py │ ├── openssl │ │ └── __init__.py │ ├── player │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── dragonplayer.py │ │ ├── gnome_mplayer.py │ │ ├── mplayer.py │ │ ├── vlc.py │ │ └── wmp.py │ └── transcoder │ │ ├── __init__.py │ │ ├── ffmpeg.py │ │ ├── libav.py │ │ └── mencoder.py │ ├── common.py │ ├── extractor.py │ ├── extractors │ ├── __init__.py │ ├── acfun.py │ ├── alive.py │ ├── archive.py │ ├── baidu.py │ ├── bandcamp.py │ ├── baomihua.py │ ├── bigthink.py │ ├── bilibili.py │ ├── bokecc.py │ ├── cbs.py │ ├── ckplayer.py │ ├── cntv.py │ ├── dailymotion.py │ ├── dilidili.py │ ├── douban.py │ ├── douyutv.py │ ├── ehow.py │ ├── embed.py │ ├── facebook.py │ ├── fc2video.py │ ├── flickr.py │ ├── freesound.py │ ├── funshion.py │ ├── google.py │ ├── heavymusic.py │ ├── huaban.py │ ├── huomaotv.py │ ├── icourses.py │ ├── ifeng.py │ ├── imgur.py │ ├── infoq.py │ ├── instagram.py │ ├── interest.py │ ├── iqilu.py │ ├── iqiyi.py │ ├── joy.py │ ├── khan.py │ ├── ku6.py │ ├── kugou.py │ ├── kuwo.py │ ├── le.py │ ├── lizhi.py │ ├── magisto.py │ ├── metacafe.py │ ├── mgtv.py │ ├── miaopai.py │ ├── miomio.py │ ├── mixcloud.py │ ├── mtv81.py │ ├── musicplayon.py │ ├── nanagogo.py │ ├── naver.py │ ├── netease.py │ ├── nicovideo.py │ ├── panda.py │ ├── pinterest.py │ ├── pixnet.py │ ├── pptv.py │ ├── qie.py │ ├── qq.py │ ├── quanmin.py │ ├── showroom.py │ ├── sina.py │ ├── sohu.py │ ├── soundcloud.py │ ├── suntv.py │ ├── ted.py │ ├── theplatform.py │ ├── tucao.py │ ├── tudou.py │ ├── tumblr.py │ ├── twitter.py │ ├── universal.py │ ├── veoh.py │ ├── videomega.py │ ├── vidto.py │ ├── vimeo.py │ ├── vine.py │ ├── vk.py │ ├── w56.py │ ├── wanmen.py │ ├── xiami.py │ ├── yinyuetai.py │ ├── yixia.py │ ├── youku.py │ ├── youtube.py │ └── zhanqi.py │ ├── json_output.py │ ├── processor │ ├── __init__.py │ ├── ffmpeg.py │ ├── join_flv.py │ ├── join_mp4.py │ ├── join_ts.py │ └── rtmpdump.py │ ├── util │ ├── __init__.py │ ├── fs.py │ ├── git.py │ ├── log.py │ ├── strings.py │ └── term.py │ └── version.py ├── command.txt ├── screenshot ├── fileDialog.png └── mainWindow.png └── version.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *,cover 48 | .hypothesis/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | 58 | # Flask instance folder 59 | instance/ 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # IPython Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # dotenv 80 | .env 81 | 82 | # virtualenv 83 | venv/ 84 | ENV/ 85 | 86 | # Spyder project settings 87 | .spyderproject 88 | 89 | # Rope project settings 90 | .ropeproject 91 | 92 | .idea/ 93 | app/tmp.py 94 | app/build/ 95 | app/dist/ 96 | app/*.log 97 | *.mp4 98 | *.flv 99 | *.xml 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | ============================================== 2 | This is a copy of the MIT license. 3 | ============================================== 4 | Copyright (C) 2016 InG_byr 5 | Copyright (C) 2012, 2013, 2014, 2015, 2016 Mort Yao 6 | Copyright (C) 2012 Boyu Guo 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | this software and associated documentation files (the "Software"), to deal in 10 | the Software without restriction, including without limitation the rights to 11 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | of the Software, and to permit persons to whom the Software is furnished to do 13 | so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import logging 5 | import app.config 6 | 7 | __author__ = 'InG_byr' 8 | 9 | mconfig = app.config 10 | 11 | logging.basicConfig(filename='GUI-YouGet.log', 12 | level=logging.DEBUG, 13 | format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s >>> %(message)s', 14 | datefmt='%b%d %Y %H:%M:%S', 15 | filemode='w') 16 | mlog = logging 17 | -------------------------------------------------------------------------------- /app/compile_linux.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | pyinstaller main.py -F --hiddenimport app.you_get.extractors --noconsole -n YouGet-0.1.1Linux --icon /home/ing/PycharmProjects/GUI-YouGet/app/favicon.ico 3 | -------------------------------------------------------------------------------- /app/config.ini: -------------------------------------------------------------------------------- 1 | [General] 2 | version = 0.1.2 3 | you-get = 0.4.652 4 | 5 | -------------------------------------------------------------------------------- /app/config.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | import configparser 4 | import json 5 | from datetime import date 6 | import os 7 | 8 | from PyQt5.QtCore import QSettings 9 | 10 | from app.you_get.version import script_name, __version__ 11 | 12 | __author__ = 'InG_byr' 13 | 14 | version = '0.1.2' 15 | 16 | buildtime = date.today() 17 | 18 | data = {'version': version, 19 | 'build time': str(buildtime), 20 | script_name: __version__} 21 | 22 | base_dir = os.getcwd() 23 | 24 | kwargs = {'output_dir': base_dir, 25 | 'merge': True, 26 | 'json_output': False, 27 | 'caption': True, 28 | 'playlist': False} 29 | 30 | urls = '' 31 | 32 | streams = [] 33 | 34 | file_path = 'file_path' 35 | 36 | 37 | def set_default(): 38 | global kwargs 39 | global urls 40 | global streams 41 | streams = [] 42 | kwargs['stream_id'] = '' 43 | urls = '' 44 | 45 | 46 | def set_file_path(path): 47 | global kwargs 48 | kwargs['output_dir'] = path 49 | 50 | 51 | def get_file_path(): 52 | global kwargs 53 | return kwargs['output_dir'] 54 | 55 | 56 | def set_file_itag(stream_id): 57 | global kwargs 58 | kwargs['stream_id'] = stream_id 59 | 60 | 61 | def get_file_itag(): 62 | global kwargs 63 | return kwargs['stream_id'] 64 | 65 | 66 | def get_urls(): 67 | global urls 68 | return urls 69 | 70 | 71 | def set_urls(data): 72 | global urls 73 | urls = data 74 | 75 | 76 | def add_stream(data): 77 | global streams 78 | streams.append(data) 79 | 80 | 81 | def get_streams(): 82 | global streams 83 | return streams 84 | 85 | 86 | if __name__ == '__main__': 87 | # 保存版本信息 88 | with open('../version.json', 'w') as f: 89 | f.write(json.dumps(data)) 90 | 91 | config = 'config.ini' 92 | 93 | file = open(config, 'w') 94 | 95 | setting = configparser.ConfigParser() 96 | setting.read('config.ini') 97 | setting.add_section('General') 98 | setting.set('General', 'version', version) 99 | setting.set('General', script_name, __version__) 100 | 101 | setting.write(file) 102 | file.close() 103 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/favicon.ico -------------------------------------------------------------------------------- /app/main.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | import sys 6 | from PyQt5.QtWidgets import QApplication 7 | from app.ui.main_window import MainWindow 8 | 9 | from app.ui.icon_rc import * 10 | 11 | __author__ = 'InG_byr' 12 | 13 | if __name__ == '__main__': 14 | app = QApplication(sys.argv) 15 | font = app.font() 16 | font.setPointSize(11) 17 | app.setFont(font) 18 | ui = MainWindow() 19 | ui.main_window.show() 20 | sys.exit(app.exec_()) 21 | -------------------------------------------------------------------------------- /app/ui/__init__.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | 6 | __author__ = 'InG_byr' -------------------------------------------------------------------------------- /app/ui/about_widget.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | from PyQt5.QtWidgets import QWidget 4 | 5 | from app.ui.ui_about_widget import Ui_AboutForm 6 | from app import mconfig 7 | from app.ui.icon_rc import * 8 | 9 | __author__ = 'InG_byr' 10 | 11 | 12 | class AboutWdiget(Ui_AboutForm): 13 | def __init__(self): 14 | super().__init__() 15 | self.about_widget = QWidget() 16 | self.setupUi(self.about_widget) 17 | self.about_widget.setFixedSize(self.about_widget.width(),self.about_widget.height()) 18 | self.set_version() 19 | self.label_info.setOpenExternalLinks(True) 20 | 21 | def set_version(self): 22 | self.label_version.setText('Version ' + mconfig.version) 23 | -------------------------------------------------------------------------------- /app/ui/about_widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AboutForm 4 | 5 | 6 | 7 | 0 8 | 0 9 | 450 10 | 200 11 | 12 | 13 | 14 | About 15 | 16 | 17 | 18 | :/res/favicon.ico:/res/favicon.ico 19 | 20 | 21 | 22 | 23 | 20 24 | 60 25 | 131 26 | 121 27 | 28 | 29 | 30 | image: url(:/res/favicon.ico); 31 | 32 | 33 | <html><head/><body><p><br/></p></body></html> 34 | 35 | 36 | 37 | 38 | 39 | 180 40 | 50 41 | 251 42 | 141 43 | 44 | 45 | 46 | <html><head/><body><p>GitHub Repository: <a href="https://github.com/ingbyr/GUI-YouGet"><span style=" text-decoration: underline; color:#0000ff;">GUI-YouGet</span></a></p><p>License: <a href="https://raw.githubusercontent.com/ingbyr/GUI-YouGet/master/LICENSE.txt"><span style=" text-decoration: underline; color:#0000ff;">MIT</span></a> | Based on: <a href="https://github.com/soimort/you-get"><span style=" text-decoration: underline; color:#0000ff;">you-get</span></a></p><p>Coder: ingbyr ( <a href="http://www.ingbyr.tk"><span style=" text-decoration: underline; color:#0000ff;">Blog</span></a> | <a href="http://www.weibo.com/zwkv5"><span style=" text-decoration: underline; color:#0000ff;">Weibo</span></a> )</p><p>UI Designer: Nobody</p></body></html> 47 | 48 | 49 | Qt::RichText 50 | 51 | 52 | 53 | 54 | 55 | 170 56 | 0 57 | 111 58 | 41 59 | 60 | 61 | 62 | 63 | 16 64 | 65 | 66 | 67 | GUI-YouGet 68 | 69 | 70 | Qt::PlainText 71 | 72 | 73 | -1 74 | 75 | 76 | 77 | 78 | 79 | 300 80 | 20 81 | 131 82 | 20 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 121 92 | 121 93 | 121 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 121 103 | 121 104 | 121 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 159 114 | 158 115 | 158 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /app/ui/files_list_dialog.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | from PyQt5.QtGui import QIcon 4 | 5 | from app.ui.ui_files_list_dialog import Ui_FilesListDialog 6 | from app import mlog, mconfig 7 | from app.util import status 8 | from app.util.download_thread import DownloadThread 9 | from PyQt5.QtWidgets import QDialog, QMessageBox, QProgressDialog 10 | from PyQt5.QtCore import QThread, Qt 11 | from app.ui.icon_rc import * 12 | 13 | __author__ = 'InG_byr' 14 | 15 | 16 | class FilesListDialog(Ui_FilesListDialog): 17 | def __init__(self): 18 | super().__init__() 19 | self.files_list_dialog = QDialog() 20 | self.setupUi(self.files_list_dialog) 21 | self.files_list_dialog.setFixedSize(self.files_list_dialog.width(), self.files_list_dialog.height()) 22 | self.files_list_dialog.show() 23 | self.msg = QMessageBox() 24 | self.set_slot() 25 | self.set_combo_box() 26 | 27 | def set_slot(self): 28 | self.push_button_confirm.clicked.connect(self.start_download_files) 29 | self.push_button_cancel.clicked.connect(self.files_list_dialog.close) 30 | 31 | def set_combo_box(self): 32 | options = mconfig.get_streams() 33 | if options: 34 | self.combo_box_options.addItems(options) 35 | else: 36 | self.combo_box_options.addItem('default') 37 | 38 | def update_files_list(self, files_list): 39 | self.text_files_list.setHtml(files_list) 40 | 41 | def start_download_files(self): 42 | status.set_default() 43 | self.push_button_confirm.setEnabled(False) 44 | option = self.combo_box_options.currentText() 45 | mconfig.set_file_itag(option) 46 | mlog.debug('option is ' + option) 47 | 48 | self.download_thread = DownloadThread(mconfig.get_urls(), **mconfig.kwargs) 49 | self.download_thread.finish_signal.connect(self.finish_download) 50 | self.download_thread.start() 51 | self.show_progress_bar() 52 | 53 | def show_msg(self, icon, title, text): 54 | self.msg.setWindowTitle(title) 55 | self.msg.setWindowIcon(QIcon(':/res/favicon.ico')) 56 | self.msg.setIcon(icon) 57 | self.msg.setText(text) 58 | self.msg.setStandardButtons(QMessageBox.Ok) 59 | self.msg.show() 60 | 61 | def finish_download(self, is_succeed): 62 | self.push_button_confirm.setEnabled(True) 63 | if is_succeed: 64 | if self.result: 65 | self.show_msg(QMessageBox.Information, 'Tip', 66 | self.result + '\n\nFiles path: ' + mconfig.get_file_path()) 67 | else: 68 | self.show_msg(QMessageBox.Information, 'Completed', 69 | 'Download completed (ง •̀_•́)ง\n\nFiles path: ' + mconfig.get_file_path()) 70 | else: 71 | self.show_msg(QMessageBox.Critical, 'Failed', 'Download failed (╯°Д°)╯︵ ┻━┻') 72 | 73 | def show_progress_bar(self): 74 | percent = 0 75 | is_exits = False 76 | self.result = None 77 | progressDialog = QProgressDialog(self.files_list_dialog) 78 | progressDialog.setAutoReset(True) 79 | progressDialog.setWindowModality(Qt.WindowModal) 80 | progressDialog.setMinimumDuration(5) 81 | progressDialog.setWindowTitle('Downloading') 82 | progressDialog.setWindowIcon(QIcon(':/res/favicon.ico')) 83 | progressDialog.setLabelText('Current speed: ') 84 | progressDialog.setCancelButtonText('Cancel') 85 | progressDialog.setRange(0, 100) 86 | progressDialog.setValue(0) 87 | progressDialog.show() 88 | 89 | while percent < 100 and not is_exits: 90 | percent = status.get_percent() 91 | is_exits = status.get_exist() 92 | if is_exits: 93 | self.result = 'Files already exists (..•˘_˘•..)' 94 | progressDialog.close() 95 | break 96 | progressDialog.setValue(percent) 97 | progressDialog.setLabelText('Current speed: ' + str(status.get_speed())) 98 | QThread.msleep(100) 99 | if progressDialog.wasCanceled(): 100 | status.set_stop_thread(True) 101 | self.download_thread.wait() 102 | mlog.debug('stop the download thread') 103 | mlog.debug('download_thread.isRunning ' + str(self.download_thread.isRunning())) 104 | progressDialog.close() 105 | self.result = 'Paused Σ(っ °Д °;)っ' 106 | break 107 | -------------------------------------------------------------------------------- /app/ui/files_list_dialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | FilesListDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 400 11 | 12 | 13 | 14 | Files List 15 | 16 | 17 | 18 | :/res/favicon.ico:/res/favicon.ico 19 | 20 | 21 | 22 | 23 | 20 24 | 20 25 | 361 26 | 291 27 | 28 | 29 | 30 | true 31 | 32 | 33 | 34 | 35 | 36 | 20 37 | 310 38 | 361 39 | 51 40 | 41 | 42 | 43 | Choose one to download. 44 | 45 | 46 | 47 | 48 | 49 | 20 50 | 360 51 | 51 52 | 20 53 | 54 | 55 | 56 | Select 57 | 58 | 59 | 60 | 61 | 62 | 300 63 | 360 64 | 80 65 | 22 66 | 67 | 68 | 69 | Download 70 | 71 | 72 | 73 | 74 | 75 | 210 76 | 360 77 | 80 78 | 22 79 | 80 | 81 | 82 | Cancel 83 | 84 | 85 | 86 | 87 | 88 | 78 89 | 360 90 | 101 91 | 22 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /app/ui/icon.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | res/download.png 4 | res/favicon.ico 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/ui/proxy_dialog.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | from PyQt5.QtCore import QSettings 4 | from PyQt5.QtWidgets import QButtonGroup 5 | from PyQt5.QtWidgets import QDialog 6 | 7 | from app.ui.ui_proxy_dialog import Ui_Dialog 8 | from app.util.config_utils import s2b 9 | 10 | __author__ = "ingbyr" 11 | 12 | 13 | class ProxyDialog(Ui_Dialog): 14 | def __init__(self): 15 | super().__init__() 16 | self.proxy_dialog = QDialog() 17 | self.setupUi(self.proxy_dialog) 18 | self.set_slot() 19 | self.proxy_dialog.show() 20 | 21 | self.config = QSettings('config.ini', QSettings.IniFormat) 22 | self.init_config() 23 | 24 | self.group = QButtonGroup() 25 | self.group.addButton(self.socks5_checkbox) 26 | self.group.addButton(self.http_checkbox) 27 | 28 | def set_slot(self): 29 | self.button_box.accepted.connect(self.save_config) 30 | 31 | def init_config(self): 32 | ip = self.config.value('ip', '127.0.0.1') 33 | port = self.config.value('port', '1080') 34 | self.ip_text_edit.setText(ip) 35 | self.port_text_edit.setText(port) 36 | 37 | is_socks_proxy = self.config.value('is_socks_proxy', 'true') 38 | is_http_proxy = self.config.value('is_http_proxy', 'false') 39 | self.socks5_checkbox.setChecked(s2b(is_socks_proxy)) 40 | self.http_checkbox.setChecked(s2b(is_http_proxy)) 41 | 42 | def save_config(self): 43 | ip = self.ip_text_edit.text() 44 | port = self.port_text_edit.text() 45 | is_socks_proxy = self.socks5_checkbox.isChecked() 46 | is_http_proxy = self.http_checkbox.isChecked() 47 | self.config.setValue('ip', ip) 48 | self.config.setValue('port', port) 49 | self.config.setValue('is_socks_proxy', is_socks_proxy) 50 | self.config.setValue('is_http_proxy', is_http_proxy) 51 | self.proxy_dialog.close() 52 | -------------------------------------------------------------------------------- /app/ui/proxy_dialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 19 | 30 20 | 240 21 | 341 22 | 32 23 | 24 | 25 | 26 | Qt::Horizontal 27 | 28 | 29 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 30 | 31 | 32 | 33 | 34 | 35 | 10 36 | 10 37 | 371 38 | 31 39 | 40 | 41 | 42 | 43 | 14 44 | 45 | 46 | 47 | Proxy Setting 48 | 49 | 50 | Qt::AlignCenter 51 | 52 | 53 | 54 | 55 | 56 | 30 57 | 70 58 | 31 59 | 41 60 | 61 | 62 | 63 | IP 64 | 65 | 66 | 67 | 68 | 69 | 30 70 | 134 71 | 31 72 | 31 73 | 74 | 75 | 76 | Port 77 | 78 | 79 | 80 | 81 | 82 | 40 83 | 190 84 | 141 85 | 30 86 | 87 | 88 | 89 | HTTP proxy 90 | 91 | 92 | 93 | 94 | 95 | 200 96 | 190 97 | 141 98 | 30 99 | 100 | 101 | 102 | Socks5 proxy 103 | 104 | 105 | 106 | 107 | 108 | 70 109 | 70 110 | 311 111 | 37 112 | 113 | 114 | 115 | 116 | 117 | 118 | 70 119 | 130 120 | 311 121 | 37 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | button_box 130 | accepted() 131 | Dialog 132 | accept() 133 | 134 | 135 | 248 136 | 254 137 | 138 | 139 | 157 140 | 274 141 | 142 | 143 | 144 | 145 | button_box 146 | rejected() 147 | Dialog 148 | reject() 149 | 150 | 151 | 316 152 | 260 153 | 154 | 155 | 286 156 | 274 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /app/ui/res/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/ui/res/favicon.ico -------------------------------------------------------------------------------- /app/ui/task_item.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | TaskItem 4 | 5 | 6 | 7 | 0 8 | 0 9 | 330 10 | 100 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 50 20 | 10 21 | 261 22 | 21 23 | 24 | 25 | 26 | 27 | 14 28 | 75 29 | true 30 | 31 | 32 | 33 | media name 34 | 35 | 36 | 37 | 38 | 39 | 50 40 | 40 41 | 211 42 | 23 43 | 44 | 45 | 46 | 24 47 | 48 | 49 | 50 | 51 | 52 | 270 53 | 40 54 | 51 55 | 21 56 | 57 | 58 | 59 | speed 60 | 61 | 62 | 63 | 64 | 65 | 50 66 | 70 67 | 91 68 | 16 69 | 70 | 71 | 72 | fomat 73 | 74 | 75 | 76 | 77 | 78 | 150 79 | 70 80 | 141 81 | 16 82 | 83 | 84 | 85 | time 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /app/ui/ui_about_widget.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'about_widget.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.6 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_AboutForm(object): 12 | def setupUi(self, AboutForm): 13 | AboutForm.setObjectName("AboutForm") 14 | AboutForm.resize(450, 200) 15 | icon = QtGui.QIcon() 16 | icon.addPixmap(QtGui.QPixmap(":/res/favicon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 17 | AboutForm.setWindowIcon(icon) 18 | self.label_logo = QtWidgets.QLabel(AboutForm) 19 | self.label_logo.setGeometry(QtCore.QRect(20, 60, 131, 121)) 20 | self.label_logo.setStyleSheet("image: url(:/res/favicon.ico);") 21 | self.label_logo.setObjectName("label_logo") 22 | self.label_info = QtWidgets.QLabel(AboutForm) 23 | self.label_info.setGeometry(QtCore.QRect(180, 50, 251, 141)) 24 | self.label_info.setTextFormat(QtCore.Qt.RichText) 25 | self.label_info.setObjectName("label_info") 26 | self.label_title = QtWidgets.QLabel(AboutForm) 27 | self.label_title.setGeometry(QtCore.QRect(170, 0, 111, 41)) 28 | font = QtGui.QFont() 29 | font.setPointSize(16) 30 | self.label_title.setFont(font) 31 | self.label_title.setTextFormat(QtCore.Qt.PlainText) 32 | self.label_title.setIndent(-1) 33 | self.label_title.setObjectName("label_title") 34 | self.label_version = QtWidgets.QLabel(AboutForm) 35 | self.label_version.setGeometry(QtCore.QRect(300, 20, 131, 20)) 36 | palette = QtGui.QPalette() 37 | brush = QtGui.QBrush(QtGui.QColor(121, 121, 121)) 38 | brush.setStyle(QtCore.Qt.SolidPattern) 39 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush) 40 | brush = QtGui.QBrush(QtGui.QColor(121, 121, 121)) 41 | brush.setStyle(QtCore.Qt.SolidPattern) 42 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush) 43 | brush = QtGui.QBrush(QtGui.QColor(159, 158, 158)) 44 | brush.setStyle(QtCore.Qt.SolidPattern) 45 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush) 46 | self.label_version.setPalette(palette) 47 | self.label_version.setText("") 48 | self.label_version.setObjectName("label_version") 49 | 50 | self.retranslateUi(AboutForm) 51 | QtCore.QMetaObject.connectSlotsByName(AboutForm) 52 | 53 | def retranslateUi(self, AboutForm): 54 | _translate = QtCore.QCoreApplication.translate 55 | AboutForm.setWindowTitle(_translate("AboutForm", "About")) 56 | self.label_logo.setText(_translate("AboutForm", "


")) 57 | self.label_info.setText(_translate("AboutForm", "

GitHub Repository: GUI-YouGet

License: MIT | Based on: you-get

Coder: ingbyr ( Blog | Weibo )

UI Designer: Nobody

")) 58 | self.label_title.setText(_translate("AboutForm", "GUI-YouGet")) 59 | -------------------------------------------------------------------------------- /app/ui/ui_design.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2016-05-19T18:45:36 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = ui_design 12 | TEMPLATE = app 13 | 14 | 15 | SOURCES += main.cpp\ 16 | mainwindow.cpp 17 | 18 | HEADERS += mainwindow.h 19 | 20 | FORMS += main_window.ui \ 21 | about_widget.ui \ 22 | files_list_dialog.ui \ 23 | task_item.ui 24 | 25 | RESOURCES += \ 26 | icon.qrc 27 | -------------------------------------------------------------------------------- /app/ui/ui_files_list_dialog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'files_list_dialog.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.5.1 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_FilesListDialog(object): 12 | def setupUi(self, FilesListDialog): 13 | FilesListDialog.setObjectName("FilesListDialog") 14 | FilesListDialog.resize(400, 400) 15 | icon = QtGui.QIcon() 16 | icon.addPixmap(QtGui.QPixmap(":/res/favicon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 17 | FilesListDialog.setWindowIcon(icon) 18 | self.text_files_list = QtWidgets.QTextEdit(FilesListDialog) 19 | self.text_files_list.setGeometry(QtCore.QRect(20, 20, 361, 291)) 20 | self.text_files_list.setReadOnly(True) 21 | self.text_files_list.setObjectName("text_files_list") 22 | self.label = QtWidgets.QLabel(FilesListDialog) 23 | self.label.setGeometry(QtCore.QRect(20, 310, 361, 51)) 24 | self.label.setObjectName("label") 25 | self.label_2 = QtWidgets.QLabel(FilesListDialog) 26 | self.label_2.setGeometry(QtCore.QRect(20, 360, 51, 20)) 27 | self.label_2.setObjectName("label_2") 28 | self.push_button_confirm = QtWidgets.QPushButton(FilesListDialog) 29 | self.push_button_confirm.setGeometry(QtCore.QRect(300, 360, 80, 22)) 30 | self.push_button_confirm.setObjectName("push_button_confirm") 31 | self.push_button_cancel = QtWidgets.QPushButton(FilesListDialog) 32 | self.push_button_cancel.setGeometry(QtCore.QRect(210, 360, 80, 22)) 33 | self.push_button_cancel.setObjectName("push_button_cancel") 34 | self.combo_box_options = QtWidgets.QComboBox(FilesListDialog) 35 | self.combo_box_options.setGeometry(QtCore.QRect(78, 360, 101, 22)) 36 | self.combo_box_options.setObjectName("combo_box_options") 37 | 38 | self.retranslateUi(FilesListDialog) 39 | QtCore.QMetaObject.connectSlotsByName(FilesListDialog) 40 | 41 | def retranslateUi(self, FilesListDialog): 42 | _translate = QtCore.QCoreApplication.translate 43 | FilesListDialog.setWindowTitle(_translate("FilesListDialog", "Files List")) 44 | self.label.setText(_translate("FilesListDialog", "Choose one to download.")) 45 | self.label_2.setText(_translate("FilesListDialog", "Select")) 46 | self.push_button_confirm.setText(_translate("FilesListDialog", "Download")) 47 | self.push_button_cancel.setText(_translate("FilesListDialog", "Cancel")) 48 | 49 | -------------------------------------------------------------------------------- /app/ui/ui_proxy_dialog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'proxy_dialog.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.6 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_Dialog(object): 12 | def setupUi(self, Dialog): 13 | Dialog.setObjectName("Dialog") 14 | Dialog.resize(400, 300) 15 | self.button_box = QtWidgets.QDialogButtonBox(Dialog) 16 | self.button_box.setGeometry(QtCore.QRect(30, 240, 341, 32)) 17 | self.button_box.setOrientation(QtCore.Qt.Horizontal) 18 | self.button_box.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) 19 | self.button_box.setObjectName("button_box") 20 | self.title = QtWidgets.QLabel(Dialog) 21 | self.title.setGeometry(QtCore.QRect(10, 10, 371, 31)) 22 | font = QtGui.QFont() 23 | font.setPointSize(14) 24 | self.title.setFont(font) 25 | self.title.setAlignment(QtCore.Qt.AlignCenter) 26 | self.title.setObjectName("title") 27 | self.label_ip = QtWidgets.QLabel(Dialog) 28 | self.label_ip.setGeometry(QtCore.QRect(30, 70, 31, 41)) 29 | self.label_ip.setObjectName("label_ip") 30 | self.label_port = QtWidgets.QLabel(Dialog) 31 | self.label_port.setGeometry(QtCore.QRect(30, 134, 31, 31)) 32 | self.label_port.setObjectName("label_port") 33 | self.http_checkbox = QtWidgets.QCheckBox(Dialog) 34 | self.http_checkbox.setGeometry(QtCore.QRect(40, 190, 141, 30)) 35 | self.http_checkbox.setObjectName("http_checkbox") 36 | self.socks5_checkbox = QtWidgets.QCheckBox(Dialog) 37 | self.socks5_checkbox.setGeometry(QtCore.QRect(200, 190, 141, 30)) 38 | self.socks5_checkbox.setObjectName("socks5_checkbox") 39 | self.ip_text_edit = QtWidgets.QLineEdit(Dialog) 40 | self.ip_text_edit.setGeometry(QtCore.QRect(70, 70, 311, 37)) 41 | self.ip_text_edit.setObjectName("ip_text_edit") 42 | self.port_text_edit = QtWidgets.QLineEdit(Dialog) 43 | self.port_text_edit.setGeometry(QtCore.QRect(70, 130, 311, 37)) 44 | self.port_text_edit.setObjectName("port_text_edit") 45 | 46 | self.retranslateUi(Dialog) 47 | self.button_box.accepted.connect(Dialog.accept) 48 | self.button_box.rejected.connect(Dialog.reject) 49 | QtCore.QMetaObject.connectSlotsByName(Dialog) 50 | 51 | def retranslateUi(self, Dialog): 52 | _translate = QtCore.QCoreApplication.translate 53 | Dialog.setWindowTitle(_translate("Dialog", "Dialog")) 54 | self.title.setText(_translate("Dialog", "Proxy Setting")) 55 | self.label_ip.setText(_translate("Dialog", "IP")) 56 | self.label_port.setText(_translate("Dialog", "Port")) 57 | self.http_checkbox.setText(_translate("Dialog", "HTTP proxy")) 58 | self.socks5_checkbox.setText(_translate("Dialog", "Socks5 proxy")) 59 | 60 | -------------------------------------------------------------------------------- /app/ui/ui_task_item.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'tast_item.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.5.1 6 | # 7 | # WARNING! All changes made in this file will be lost! 8 | 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | class Ui_TaskItem(object): 12 | def setupUi(self, TaskItem): 13 | TaskItem.setObjectName("TaskItem") 14 | TaskItem.resize(330, 100) 15 | self.task_name = QtWidgets.QLabel(TaskItem) 16 | self.task_name.setGeometry(QtCore.QRect(50, 10, 261, 21)) 17 | font = QtGui.QFont() 18 | font.setPointSize(14) 19 | font.setBold(True) 20 | font.setWeight(75) 21 | self.task_name.setFont(font) 22 | self.task_name.setObjectName("task_name") 23 | self.task_progress_bar = QtWidgets.QProgressBar(TaskItem) 24 | self.task_progress_bar.setGeometry(QtCore.QRect(50, 40, 211, 23)) 25 | self.task_progress_bar.setProperty("value", 24) 26 | self.task_progress_bar.setObjectName("task_progress_bar") 27 | self.task_speed = QtWidgets.QLabel(TaskItem) 28 | self.task_speed.setGeometry(QtCore.QRect(270, 40, 51, 21)) 29 | self.task_speed.setObjectName("task_speed") 30 | self.task_format = QtWidgets.QLabel(TaskItem) 31 | self.task_format.setGeometry(QtCore.QRect(50, 70, 91, 16)) 32 | self.task_format.setObjectName("task_format") 33 | self.task_time = QtWidgets.QLabel(TaskItem) 34 | self.task_time.setGeometry(QtCore.QRect(150, 70, 141, 16)) 35 | self.task_time.setObjectName("task_time") 36 | 37 | self.retranslateUi(TaskItem) 38 | QtCore.QMetaObject.connectSlotsByName(TaskItem) 39 | 40 | def retranslateUi(self, TaskItem): 41 | _translate = QtCore.QCoreApplication.translate 42 | TaskItem.setWindowTitle(_translate("TaskItem", "Form")) 43 | self.task_name.setText(_translate("TaskItem", "media name")) 44 | self.task_speed.setText(_translate("TaskItem", "speed")) 45 | self.task_format.setText(_translate("TaskItem", "fomat")) 46 | self.task_time.setText(_translate("TaskItem", "time")) 47 | 48 | -------------------------------------------------------------------------------- /app/util/__init__.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | 6 | __author__ = 'InG_byr' -------------------------------------------------------------------------------- /app/util/config_utils.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | __author__ = "ingbyr" 5 | 6 | 7 | def s2b(str): 8 | if isinstance(str, bool): 9 | return str 10 | 11 | if str == 'false': 12 | return False 13 | elif str == 'true': 14 | return True 15 | else: 16 | return None 17 | -------------------------------------------------------------------------------- /app/util/download_thread.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import time 5 | from PyQt5 import QtCore 6 | from PyQt5.QtCore import QSettings 7 | 8 | from app import mlog, mconfig 9 | from app.util.config_utils import s2b 10 | from app.util.proxy import m_set_http_proxy, m_set_socks_proxy, disable_proxy 11 | from app.util.status import get_buffer 12 | 13 | from app.you_get.common import any_download_playlist, any_download, download_main 14 | 15 | __author__ = 'InG_byr' 16 | 17 | 18 | class GetVideoInfoThread(QtCore.QThread): 19 | """ 20 | show the information of video 21 | """ 22 | 23 | finish_signal = QtCore.pyqtSignal(str, bool) 24 | 25 | def __init__(self, urls, parent=None, **kwargs): 26 | super(GetVideoInfoThread, self).__init__(parent) 27 | self.urls = urls 28 | self.kwargs = kwargs 29 | self.config = QSettings('config.ini', QSettings.IniFormat) 30 | 31 | if s2b(self.config.value('enable_proxy', 'false')): 32 | if s2b(self.config.value('is_http_proxy', 'false')): 33 | m_set_http_proxy(self.config.value('ip', '127.0.0.1'), self.config.value('port', '1080')) 34 | mlog.debug("enable http proxy") 35 | if s2b(self.config.value('is_socks_proxy', 'false')): 36 | m_set_socks_proxy(self.config.value('ip', '127.0.0.1'), self.config.value('port', '1080')) 37 | mlog.debug("enable socks proxy") 38 | else: 39 | mlog.debug('disable the proxy') 40 | disable_proxy() 41 | 42 | def run(self): 43 | try: 44 | self.kwargs['info_only'] = True 45 | download_main(any_download, any_download_playlist, self.urls, **self.kwargs) 46 | result = ''.join(get_buffer()) 47 | can_download = True 48 | except Exception as e: 49 | mlog.exception(e) 50 | result = "Get information failed." 51 | can_download = False 52 | finally: 53 | self.finish_signal.emit(result, can_download) 54 | 55 | 56 | class DownloadThread(QtCore.QThread): 57 | """ 58 | start a thread to download the video 59 | """ 60 | 61 | finish_signal = QtCore.pyqtSignal(bool) 62 | 63 | def __init__(self, urls, parent=None, **kwargs): 64 | super(DownloadThread, self).__init__(parent) 65 | self.urls = urls 66 | self.kwargs = kwargs 67 | self.config = QSettings('config.ini', QSettings.IniFormat) 68 | 69 | if s2b(self.config.value('enable_proxy', 'false')): 70 | if s2b(self.config.value('is_http_proxy', 'false')): 71 | m_set_http_proxy(self.config.value('ip', '127.0.0.1'), self.config.value('port', '1080')) 72 | mlog.debug("enable http proxy") 73 | if s2b(self.config.value('is_socks_proxy', 'false')): 74 | m_set_socks_proxy(self.config.value('ip', '127.0.0.1'), self.config.value('port', '1080')) 75 | mlog.debug("enable socks proxy") 76 | else: 77 | mlog.debug('disable the proxy') 78 | disable_proxy() 79 | 80 | def run(self): 81 | """ 82 | Download the video 83 | :return: nothing 84 | """ 85 | is_succeed = False 86 | try: 87 | self.kwargs['info_only'] = False 88 | mlog.debug(mconfig.get_file_itag) 89 | download_main(any_download, any_download_playlist, self.urls, **self.kwargs) 90 | is_succeed = True 91 | except Exception as e: 92 | mlog.exception(e) 93 | is_succeed = False 94 | finally: 95 | self.finish_signal.emit(is_succeed) 96 | -------------------------------------------------------------------------------- /app/util/proxy.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import socks 5 | import socket 6 | 7 | from app.you_get.common import set_http_proxy 8 | 9 | __author__ = "ingbyr" 10 | 11 | 12 | def m_set_socks_proxy(address, port): 13 | socks.set_default_proxy(socks.SOCKS5, address, int(port)) 14 | socket.socket = socks.socksocket 15 | 16 | 17 | def m_set_http_proxy(address, port): 18 | set_http_proxy(address + ':' + port) 19 | 20 | 21 | def disable_proxy(): 22 | set_http_proxy(None) 23 | socks.set_default_proxy() 24 | socket.socket = socks.socksocket 25 | -------------------------------------------------------------------------------- /app/util/status.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | from app.config import add_stream 4 | 5 | __author__ = "ingbyr" 6 | 7 | SPEED = '' 8 | PERCENT = 0.0 9 | EXIST = False 10 | STOP_THREAD = False 11 | 12 | buffer = [] 13 | 14 | 15 | def set_default(): 16 | global SPEED 17 | global PERCENT 18 | global EXIST 19 | global STOP_THREAD 20 | SPEED = '' 21 | PERCENT = 0.0 22 | EXIST = False 23 | STOP_THREAD = False 24 | 25 | global buffer 26 | buffer = [] 27 | 28 | 29 | def set_percent(data): 30 | global PERCENT 31 | PERCENT = data 32 | 33 | 34 | def get_percent(): 35 | global PERCENT 36 | return PERCENT 37 | 38 | 39 | def set_exist(data): 40 | global EXIST 41 | EXIST = data 42 | 43 | 44 | def get_exist(): 45 | global EXIST 46 | return EXIST 47 | 48 | 49 | def set_stop_thread(data): 50 | global STOP_THREAD 51 | STOP_THREAD = data 52 | 53 | 54 | def get_stop_thread(): 55 | global STOP_THREAD 56 | return STOP_THREAD 57 | 58 | 59 | def set_speed(data): 60 | global SPEED 61 | SPEED = data 62 | 63 | 64 | def get_speed(): 65 | global SPEED 66 | return SPEED 67 | 68 | 69 | def print_gui(*arg, **kwargs): 70 | global buffer 71 | if arg: 72 | for item in arg: 73 | if str(item).startswith(' # download-with:'): 74 | index = item.find('=') 75 | options = item[(index + 1):-6] 76 | add_stream(options) 77 | item = 'The option is [ ' + options + ' ]

' 78 | buffer.append(str(item) + '
') 79 | else: 80 | buffer.append('
') 81 | 82 | 83 | def get_buffer(): 84 | global buffer 85 | return buffer 86 | 87 | def clear_buffer(): 88 | global buffer 89 | buffer = [] 90 | -------------------------------------------------------------------------------- /app/you_get/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # This file is Python 2 compliant. 3 | 4 | -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/__init__.py -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/downloader/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/downloader/__init__.py -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/openssl/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/openssl/__init__.py -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/player/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from .mplayer import * 4 | -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/player/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | def main(): 4 | script_main('you-get', any_download, any_download_playlist) 5 | 6 | if __name__ == "__main__": 7 | main() 8 | -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/player/dragonplayer.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/player/dragonplayer.py -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/player/gnome_mplayer.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/player/gnome_mplayer.py -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/player/mplayer.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/player/mplayer.py -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/player/vlc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/player/wmp.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/player/wmp.py -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/transcoder/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/transcoder/__init__.py -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/transcoder/ffmpeg.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/transcoder/ffmpeg.py -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/transcoder/libav.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/transcoder/libav.py -------------------------------------------------------------------------------- /app/you_get/cli_wrapper/transcoder/mencoder.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/share23/GUI-YouGet/ec2cd7e88061045a210aee2b6c817df82b7146c0/app/you_get/cli_wrapper/transcoder/mencoder.py -------------------------------------------------------------------------------- /app/you_get/extractors/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from .acfun import * 4 | from .alive import * 5 | from .archive import * 6 | from .baidu import * 7 | from .bandcamp import * 8 | from .bigthink import * 9 | from .bilibili import * 10 | from .bokecc import * 11 | from .cbs import * 12 | from .ckplayer import * 13 | from .cntv import * 14 | from .dailymotion import * 15 | from .dilidili import * 16 | from .douban import * 17 | from .douyutv import * 18 | from .ehow import * 19 | from .facebook import * 20 | from .fc2video import * 21 | from .flickr import * 22 | from .freesound import * 23 | from .funshion import * 24 | from .google import * 25 | from .heavymusic import * 26 | from .huaban import * 27 | from .icourses import * 28 | from .ifeng import * 29 | from .imgur import * 30 | from .infoq import * 31 | from .instagram import * 32 | from .interest import * 33 | from .iqilu import * 34 | from .iqiyi import * 35 | from .joy import * 36 | from .ku6 import * 37 | from .kugou import * 38 | from .kuwo import * 39 | from .le import * 40 | from .lizhi import * 41 | from .magisto import * 42 | from .metacafe import * 43 | from .mgtv import * 44 | from .miaopai import * 45 | from .miomio import * 46 | from .mixcloud import * 47 | from .mtv81 import * 48 | from .musicplayon import * 49 | from .nanagogo import * 50 | from .naver import * 51 | from .netease import * 52 | from .nicovideo import * 53 | from .panda import * 54 | from .pinterest import * 55 | from .pixnet import * 56 | from .pptv import * 57 | from .qie import * 58 | from .qq import * 59 | from .showroom import * 60 | from .sina import * 61 | from .sohu import * 62 | from .soundcloud import * 63 | from .suntv import * 64 | from .theplatform import * 65 | from .tucao import * 66 | from .tudou import * 67 | from .tumblr import * 68 | from .twitter import * 69 | from .veoh import * 70 | from .videomega import * 71 | from .vimeo import * 72 | from .vine import * 73 | from .vk import * 74 | from .w56 import * 75 | from .wanmen import * 76 | from .xiami import * 77 | from .yinyuetai import * 78 | from .yixia import * 79 | from .youku import * 80 | from .youtube import * 81 | from .ted import * 82 | from .khan import * 83 | from .zhanqi import * 84 | -------------------------------------------------------------------------------- /app/you_get/extractors/acfun.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['acfun_download'] 4 | 5 | from ..common import * 6 | 7 | from .le import letvcloud_download_by_vu 8 | from .qq import qq_download_by_vid 9 | from .sina import sina_download_by_vid 10 | from .tudou import tudou_download_by_iid 11 | from .youku import youku_download_by_vid, youku_open_download_by_vid 12 | 13 | import json, re 14 | 15 | def get_srt_json(id): 16 | url = 'http://danmu.aixifan.com/V2/%s' % id 17 | return get_html(url) 18 | 19 | def acfun_download_by_vid(vid, title, output_dir='.', merge=True, info_only=False, **kwargs): 20 | """str, str, str, bool, bool ->None 21 | 22 | Download Acfun video by vid. 23 | 24 | Call Acfun API, decide which site to use, and pass the job to its 25 | extractor. 26 | """ 27 | 28 | #first call the main parasing API 29 | info = json.loads(get_html('http://www.acfun.tv/video/getVideo.aspx?id=' + vid)) 30 | 31 | sourceType = info['sourceType'] 32 | 33 | #decide sourceId to know which extractor to use 34 | if 'sourceId' in info: sourceId = info['sourceId'] 35 | # danmakuId = info['danmakuId'] 36 | 37 | #call extractor decided by sourceId 38 | if sourceType == 'sina': 39 | sina_download_by_vid(sourceId, title, output_dir=output_dir, merge=merge, info_only=info_only) 40 | elif sourceType == 'youku': 41 | youku_download_by_vid(sourceId, title=title, output_dir=output_dir, merge=merge, info_only=info_only, **kwargs) 42 | elif sourceType == 'tudou': 43 | tudou_download_by_iid(sourceId, title, output_dir=output_dir, merge=merge, info_only=info_only) 44 | elif sourceType == 'qq': 45 | qq_download_by_vid(sourceId, title, output_dir=output_dir, merge=merge, info_only=info_only) 46 | elif sourceType == 'letv': 47 | letvcloud_download_by_vu(sourceId, '2d8c027396', title, output_dir=output_dir, merge=merge, info_only=info_only) 48 | elif sourceType == 'zhuzhan': 49 | #As in Jul.28.2016, Acfun is using embsig to anti hotlink so we need to pass this 50 | embsig = info['encode'] 51 | a = 'http://api.aixifan.com/plays/%s' % vid 52 | s = json.loads(get_content(a, headers={'deviceType': '2'})) 53 | if s['data']['source'] == "zhuzhan-youku": 54 | sourceId = s['data']['sourceId'] 55 | youku_open_download_by_vid(client_id='908a519d032263f8', vid=sourceId, title=title, output_dir=output_dir,merge=merge, info_only=info_only, embsig = embsig, **kwargs) 56 | else: 57 | raise NotImplementedError(sourceType) 58 | 59 | if not info_only and not dry_run: 60 | if not kwargs['caption']: 61 | print_gui('Skipping danmaku.') 62 | return 63 | try: 64 | title = get_filename(title) 65 | print_gui('Downloading %s ...\n' % (title + '.cmt.json')) 66 | cmt = get_srt_json(vid) 67 | with open(os.path.join(output_dir, title + '.cmt.json'), 'w', encoding='utf-8') as x: 68 | x.write(cmt) 69 | except: 70 | pass 71 | 72 | def acfun_download(url, output_dir='.', merge=True, info_only=False, **kwargs): 73 | assert re.match(r'http://[^\.]+.acfun.[^\.]+/\D/\D\D(\d+)', url) 74 | html = get_html(url) 75 | 76 | title = r1(r'data-title="([^"]+)"', html) 77 | title = unescape_html(title) 78 | title = escape_file_path(title) 79 | assert title 80 | if match1(url, r'_(\d+)$'): # current P 81 | title = title + " " + r1(r'active">([^<]*)', html) 82 | 83 | vid = r1('data-vid="(\d+)"', html) 84 | up = r1('data-name="([^"]+)"', html) 85 | title = title + ' - ' + up 86 | acfun_download_by_vid(vid, title, 87 | output_dir=output_dir, 88 | merge=merge, 89 | info_only=info_only, 90 | **kwargs) 91 | 92 | site_info = "AcFun.tv" 93 | download = acfun_download 94 | download_playlist = playlist_not_supported('acfun') 95 | -------------------------------------------------------------------------------- /app/you_get/extractors/alive.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['alive_download'] 4 | 5 | from ..common import * 6 | 7 | def alive_download(url, output_dir = '.', merge = True, info_only = False, **kwargs): 8 | html = get_html(url) 9 | 10 | title = r1(r'(.*)', html) 26 | assert title 27 | id = r1(r'flvid\s*=\s*(\d+)', html) 28 | assert id 29 | baomihua_download_by_id(id, title, output_dir=output_dir, merge=merge, info_only=info_only) 30 | 31 | site_info = "baomihua.com" 32 | download = baomihua_download 33 | download_playlist = playlist_not_supported('baomihua') 34 | -------------------------------------------------------------------------------- /app/you_get/extractors/bigthink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from ..common import * 4 | from ..extractor import VideoExtractor 5 | 6 | import json 7 | 8 | class Bigthink(VideoExtractor): 9 | name = "Bigthink" 10 | 11 | stream_types = [ #this is just a sample. Will make it in prepare() 12 | # {'id': '1080'}, 13 | # {'id': '720'}, 14 | # {'id': '360'}, 15 | # {'id': '288'}, 16 | # {'id': '190'}, 17 | # {'id': '180'}, 18 | 19 | ] 20 | 21 | @staticmethod 22 | def get_streams_by_id(account_number, video_id): 23 | """ 24 | int, int->list 25 | 26 | Get the height of the videos. 27 | 28 | Since brightcove is using 3 kinds of links: rtmp, http and https, 29 | we will be using the HTTPS one to make it secure. 30 | 31 | If somehow akamaihd.net is blocked by the Great Fucking Wall, 32 | change the "startswith https" to http. 33 | """ 34 | endpoint = 'https://edge.api.brightcove.com/playback/v1/accounts/{account_number}/videos/{video_id}'.format(account_number = account_number, video_id = video_id) 35 | fake_header_id = fake_headers 36 | #is this somehow related to the time? Magic.... 37 | fake_header_id['Accept'] ='application/json;pk=BCpkADawqM1cc6wmJQC2tvoXZt4mrB7bFfi6zGt9QnOzprPZcGLE9OMGJwspQwKfuFYuCjAAJ53JdjI8zGFx1ll4rxhYJ255AXH1BQ10rnm34weknpfG-sippyQ' 38 | 39 | html = get_content(endpoint, headers= fake_header_id) 40 | html_json = json.loads(html) 41 | 42 | link_list = [] 43 | 44 | for i in html_json['sources']: 45 | if 'src' in i: #to avoid KeyError 46 | if i['src'].startswith('https'): 47 | link_list.append((str(i['height']), i['src'])) 48 | 49 | return link_list 50 | 51 | def prepare(self, **kwargs): 52 | 53 | html = get_content(self.url) 54 | 55 | self.title = match1(html, r'None 19 | 20 | Keyword arguments: 21 | self: self 22 | vid: The video ID for BokeCC cloud, something like 23 | FE3BB999594978049C33DC5901307461 24 | 25 | Calls the prepare() to download the video. 26 | 27 | If no title is provided, this method shall try to find a proper title 28 | with the information providin within the 29 | returned content of the API.""" 30 | 31 | assert vid 32 | 33 | self.prepare(vid = vid, title = title, **kwargs) 34 | 35 | self.extract(**kwargs) 36 | 37 | self.download(output_dir = output_dir, 38 | merge = merge, 39 | info_only = info_only, **kwargs) 40 | 41 | def prepare(self, vid = '', title = None, **kwargs): 42 | assert vid 43 | 44 | api_url = self.API_ENDPOINT + \ 45 | 'servlet/playinfo?vid={vid}&m=0'.format(vid = vid) #return XML 46 | 47 | html = get_content(api_url) 48 | self.tree = ET.ElementTree(ET.fromstring(html)) 49 | 50 | if self.tree.find('result').text != '1': 51 | log.wtf('API result says failed!') 52 | raise 53 | 54 | if title is None: 55 | self.title = '_'.join([i.text for i in tree.iterfind('video/videomarks/videomark/markdesc')]) 56 | else: 57 | self.title = title 58 | 59 | for i in self.tree.iterfind('video/quality'): 60 | quality = i.attrib ['value'] 61 | url = i[0].attrib['playurl'] 62 | self.stream_types.append({'id': quality, 63 | 'video_profile': i.attrib ['desp']}) 64 | self.streams[quality] = {'url': url, 65 | 'video_profile': i.attrib ['desp']} 66 | self.streams_sorted = [dict([('id', stream_type['id'])] + list(self.streams[stream_type['id']].items())) for stream_type in self.__class__.stream_types if stream_type['id'] in self.streams] 67 | 68 | 69 | def extract(self, **kwargs): 70 | for i in self.streams: 71 | s = self.streams[i] 72 | _, s['container'], s['size'] = url_info(s['url']) 73 | s['src'] = [s['url']] 74 | if 'stream_id' in kwargs and kwargs['stream_id']: 75 | # Extract the stream 76 | stream_id = kwargs['stream_id'] 77 | 78 | if stream_id not in self.streams: 79 | log.e('[Error] Invalid video format.') 80 | log.e('Run \'-i\' command with no specific video format to view all available formats.') 81 | exit(2) 82 | else: 83 | # Extract stream with the best quality 84 | stream_id = self.streams_sorted[0]['id'] 85 | _, s['container'], s['size'] = url_info(s['url']) 86 | s['src'] = [s['url']] 87 | 88 | site = BokeCC() 89 | 90 | # I don't know how to call the player directly so I just put it here 91 | # just in case anyone touchs it -- Beining@Aug.24.2016 92 | #download = site.download_by_url 93 | #download_playlist = site.download_by_url 94 | 95 | bokecc_download_by_id = site.download_by_id 96 | -------------------------------------------------------------------------------- /app/you_get/extractors/cbs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['cbs_download'] 4 | 5 | from ..common import * 6 | 7 | from .theplatform import theplatform_download_by_pid 8 | 9 | def cbs_download(url, output_dir='.', merge=True, info_only=False, **kwargs): 10 | """Downloads CBS videos by URL. 11 | """ 12 | 13 | html = get_content(url) 14 | pid = match1(html, r'video\.settings\.pid\s*=\s*\'([^\']+)\'') 15 | title = match1(html, r'video\.settings\.title\s*=\s*\"([^\"]+)\"') 16 | 17 | theplatform_download_by_pid(pid, title, output_dir=output_dir, merge=merge, info_only=info_only) 18 | 19 | site_info = "CBS.com" 20 | download = cbs_download 21 | download_playlist = playlist_not_supported('cbs') 22 | -------------------------------------------------------------------------------- /app/you_get/extractors/ckplayer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #coding:utf-8 3 | # Author: Beining -- 4 | # Purpose: A general extractor for CKPlayer 5 | # Created: 03/15/2016 6 | 7 | __all__ = ['ckplayer_download'] 8 | 9 | from xml.etree import cElementTree as ET 10 | from copy import copy 11 | from ..common import * 12 | 13 | #---------------------------------------------------------------------- 14 | def ckplayer_get_info_by_xml(ckinfo): 15 | """str->dict 16 | Information for CKPlayer API content.""" 17 | e = ET.XML(ckinfo) 18 | video_dict = {'title': '', 19 | #'duration': 0, 20 | 'links': [], 21 | 'size': 0, 22 | 'flashvars': '',} 23 | if '_text' in dictify(e)['ckplayer']['info'][0]['title'][0]: #title 24 | video_dict['title'] = dictify(e)['ckplayer']['info'][0]['title'][0]['_text'].strip() 25 | 26 | #if dictify(e)['ckplayer']['info'][0]['title'][0]['_text'].strip(): #duration 27 | #video_dict['title'] = dictify(e)['ckplayer']['info'][0]['title'][0]['_text'].strip() 28 | 29 | if '_text' in dictify(e)['ckplayer']['video'][0]['size'][0]: #size exists for 1 piece 30 | video_dict['size'] = sum([int(i['size'][0]['_text']) for i in dictify(e)['ckplayer']['video']]) 31 | 32 | if '_text' in dictify(e)['ckplayer']['video'][0]['file'][0]: #link exist 33 | video_dict['links'] = [i['file'][0]['_text'].strip() for i in dictify(e)['ckplayer']['video']] 34 | 35 | if '_text' in dictify(e)['ckplayer']['flashvars'][0]: 36 | video_dict['flashvars'] = dictify(e)['ckplayer']['flashvars'][0]['_text'].strip() 37 | 38 | return video_dict 39 | 40 | #---------------------------------------------------------------------- 41 | #helper 42 | #https://stackoverflow.com/questions/2148119/how-to-convert-an-xml-string-to-a-dictionary-in-python 43 | def dictify(r,root=True): 44 | if root: 45 | return {r.tag : dictify(r, False)} 46 | d=copy(r.attrib) 47 | if r.text: 48 | d["_text"]=r.text 49 | for x in r.findall("./*"): 50 | if x.tag not in d: 51 | d[x.tag]=[] 52 | d[x.tag].append(dictify(x,False)) 53 | return d 54 | 55 | #---------------------------------------------------------------------- 56 | def ckplayer_download_by_xml(ckinfo, output_dir = '.', merge = False, info_only = False, **kwargs): 57 | #Info XML 58 | video_info = ckplayer_get_info_by_xml(ckinfo) 59 | 60 | try: 61 | title = kwargs['title'] 62 | except: 63 | title = '' 64 | type_ = '' 65 | size = 0 66 | 67 | if len(video_info['links']) > 0: #has link 68 | type_, _ext, size = url_info(video_info['links'][0]) #use 1st to determine type, ext 69 | 70 | if 'size' in video_info: 71 | size = int(video_info['size']) 72 | else: 73 | for i in video_info['links'][1:]: #save 1st one 74 | size += url_info(i)[2] 75 | 76 | print_gui_info(site_info, title, type_, size) 77 | if not info_only: 78 | download_urls(video_info['links'], title, _ext, size, output_dir=output_dir, merge=merge) 79 | 80 | #---------------------------------------------------------------------- 81 | def ckplayer_download(url, output_dir = '.', merge = False, info_only = False, is_xml = True, **kwargs): 82 | if is_xml: #URL is XML URL 83 | try: 84 | title = kwargs['title'] 85 | except: 86 | title = '' 87 | try: 88 | headers = kwargs['headers'] #headers provided 89 | ckinfo = get_content(url, headers = headers) 90 | except NameError: 91 | ckinfo = get_content(url) 92 | 93 | ckplayer_download_by_xml(ckinfo, output_dir, merge, 94 | info_only, title = title) 95 | 96 | site_info = "CKPlayer General" 97 | download = ckplayer_download 98 | download_playlist = playlist_not_supported('ckplayer') 99 | -------------------------------------------------------------------------------- /app/you_get/extractors/cntv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['cntv_download', 'cntv_download_by_id'] 4 | 5 | from ..common import * 6 | 7 | import json 8 | import re 9 | 10 | 11 | def cntv_download_by_id(id, title = None, output_dir = '.', merge = True, info_only = False): 12 | assert id 13 | info = json.loads(get_html('http://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid=' + id)) 14 | title = title or info['title'] 15 | video = info['video'] 16 | alternatives = [x for x in video.keys() if x.endswith('hapters')] 17 | #assert alternatives in (['chapters'], ['lowChapters', 'chapters'], ['chapters', 'lowChapters']), alternatives 18 | chapters = video['chapters'] if 'chapters' in video else video['lowChapters'] 19 | urls = [x['url'] for x in chapters] 20 | ext = r1(r'\.([^.]+)$', urls[0]) 21 | assert ext in ('flv', 'mp4') 22 | size = 0 23 | for url in urls: 24 | _, _, temp = url_info(url) 25 | size += temp 26 | 27 | print_gui_info(site_info, title, ext, size) 28 | if not info_only: 29 | # avoid corrupted files - don't merge 30 | download_urls(urls, title, ext, size, output_dir = output_dir, merge = False) 31 | 32 | def cntv_download(url, output_dir = '.', merge = True, info_only = False, **kwargs): 33 | if re.match(r'http://tv\.cntv\.cn/video/(\w+)/(\w+)', url): 34 | id = match1(url, r'http://tv\.cntv\.cn/video/\w+/(\w+)') 35 | elif re.match(r'http://\w+\.cntv\.cn/(\w+/\w+/(classpage/video/)?)?\d+/\d+\.shtml', url) or \ 36 | re.match(r'http://\w+.cntv.cn/(\w+/)*VIDE\d+.shtml', url) or \ 37 | re.match(r'http://(\w+).cntv.cn/(\w+)/classpage/video/(\d+)/(\d+).shtml', url) or \ 38 | re.match(r'http://\w+.cctv.com/\d+/\d+/\d+/\w+.shtml', url) or \ 39 | re.match(r'http://\w+.cntv.cn/\d+/\d+/\d+/\w+.shtml', url): 40 | id = r1(r'videoCenterId","(\w+)"', get_html(url)) 41 | elif re.match(r'http://xiyou.cntv.cn/v-[\w-]+\.html', url): 42 | id = r1(r'http://xiyou.cntv.cn/v-([\w-]+)\.html', url) 43 | else: 44 | raise NotImplementedError(url) 45 | 46 | cntv_download_by_id(id, output_dir = output_dir, merge = merge, info_only = info_only) 47 | 48 | site_info = "CNTV.com" 49 | download = cntv_download 50 | download_playlist = playlist_not_supported('cntv') 51 | -------------------------------------------------------------------------------- /app/you_get/extractors/dailymotion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['dailymotion_download'] 4 | 5 | from ..common import * 6 | 7 | def extract_m3u(url): 8 | content = get_content(url) 9 | m3u_url = re.findall(r'http://.*', content)[0] 10 | return match1(m3u_url, r'([^#]+)') 11 | 12 | def dailymotion_download(url, output_dir = '.', merge = True, info_only = False, **kwargs): 13 | """Downloads Dailymotion videos by URL. 14 | """ 15 | 16 | html = get_content(url) 17 | info = json.loads(match1(html, r'qualities":({.+?}),"')) 18 | title = match1(html, r'"video_title"\s*:\s*"([^"]+)"') or \ 19 | match1(html, r'"title"\s*:\s*"([^"]+)"') 20 | 21 | for quality in ['1080','720','480','380','240','auto']: 22 | try: 23 | real_url = info[quality][0]["url"] 24 | if real_url: 25 | break 26 | except KeyError: 27 | pass 28 | 29 | m3u_url = extract_m3u(real_url) 30 | mime, ext, size = 'video/mp4', 'mp4', 0 31 | 32 | print_gui_info(site_info, title, mime, size) 33 | if not info_only: 34 | download_url_ffmpeg(m3u_url, title, ext, output_dir=output_dir, merge=merge) 35 | 36 | site_info = "Dailymotion.com" 37 | download = dailymotion_download 38 | download_playlist = playlist_not_supported('dailymotion') 39 | -------------------------------------------------------------------------------- /app/you_get/extractors/dilidili.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['dilidili_download'] 4 | 5 | from ..common import * 6 | from .ckplayer import ckplayer_download 7 | 8 | headers = { 9 | 'DNT': '1', 10 | 'Accept-Encoding': 'gzip, deflate, sdch, br', 11 | 'Accept-Language': 'en-CA,en;q=0.8,en-US;q=0.6,zh-CN;q=0.4,zh;q=0.2', 12 | 'Upgrade-Insecure-Requests': '1', 13 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36', 14 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 15 | 'Cache-Control': 'max-age=0', 16 | 'Referer': 'http://www.dilidili.com/', 17 | 'Connection': 'keep-alive', 18 | 'Save-Data': 'on', 19 | } 20 | 21 | #---------------------------------------------------------------------- 22 | def dilidili_parser_data_to_stream_types(typ ,vid ,hd2 ,sign, tmsign, ulk): 23 | """->list""" 24 | parse_url = 'http://player.005.tv/parse.php?xmlurl=null&type={typ}&vid={vid}&hd={hd2}&sign={sign}&tmsign={tmsign}&userlink={ulk}'.format(typ = typ, vid = vid, hd2 = hd2, sign = sign, tmsign = tmsign, ulk = ulk) 25 | html = get_content(parse_url, headers=headers) 26 | 27 | info = re.search(r'(\{[^{]+\})(\{[^{]+\})(\{[^{]+\})(\{[^{]+\})(\{[^{]+\})', html).groups() 28 | info = [i.strip('{}').split('->') for i in info] 29 | info = {i[0]: i [1] for i in info} 30 | 31 | stream_types = [] 32 | for i in zip(info['deft'].split('|'), info['defa'].split('|')): 33 | stream_types.append({'id': str(i[1][-1]), 'container': 'mp4', 'video_profile': i[0]}) 34 | return stream_types 35 | 36 | #---------------------------------------------------------------------- 37 | def dilidili_download(url, output_dir = '.', merge = False, info_only = False, **kwargs): 38 | if re.match(r'http://www.dilidili.com/watch\S+', url): 39 | html = get_content(url) 40 | title = match1(html, r'(.+)丨(.+)') #title 41 | 42 | # player loaded via internal iframe 43 | frame_url = re.search(r'