Compare commits
10 Commits
7f790a2e82
...
a849097a47
| Author | SHA1 | Date | |
|---|---|---|---|
| a849097a47 | |||
| fbb399acfc | |||
| 7e6a23fa5d | |||
| 021d471357 | |||
| 545c5d388d | |||
| 7d2ab63dbe | |||
| fe7d0c178a | |||
| 5a622f53cd | |||
| cc336d8014 | |||
| 70ae74dcbb |
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,3 +1,6 @@
|
||||
__pycache__
|
||||
build*
|
||||
*.spec
|
||||
_dump
|
||||
*.exe
|
||||
*.spec
|
||||
/config.json
|
||||
@ -47,15 +47,15 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Century Gothic</family>
|
||||
<pointsize>20</pointsize>
|
||||
<family>Comic Sans MS</family>
|
||||
<pointsize>22</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Newgrounds Audio Downloader by H1K0</string>
|
||||
<string><strong>Newgrounds Audio Downloader</strong> by <em>H1K0</em></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignBottom|Qt::AlignHCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="input">
|
||||
@ -69,7 +69,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<family>Maiandra GD</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
@ -83,7 +83,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="dlbtn">
|
||||
<widget class="QPushButton" name="btn">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
@ -101,11 +101,14 @@
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>(Enter)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Download!</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Return</string>
|
||||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
@ -115,9 +118,33 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>21</height>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Century Gothic</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Century Gothic</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>ArrowCursor</cursorShape>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>MENU</string>
|
||||
</property>
|
||||
<addaction name="actionSettings"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionHelp"/>
|
||||
</widget>
|
||||
<addaction name="menu"/>
|
||||
</widget>
|
||||
<action name="settings">
|
||||
<property name="text">
|
||||
@ -135,6 +162,36 @@
|
||||
<string>F1</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSettings">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>../settings.ico</normaloff>../settings.ico</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Century Gothic</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Alt+S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHelp">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>../help.ico</normaloff>../help.ico</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Help</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F1</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
94
GUI/NotificationDialog.ui
Normal file
94
GUI/NotificationDialog.ui
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>150</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ACHTUNG!</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normaloff>../icon.ico</normaloff>../icon.ico</iconset>
|
||||
</property>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>30</y>
|
||||
<width>331</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Maiandra GD</family>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ACHTUNG!</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btn">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>280</x>
|
||||
<y>100</y>
|
||||
<width>81</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Cooper Black</family>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>OK!</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Return</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -39,20 +39,23 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>30</y>
|
||||
<y>20</y>
|
||||
<width>451</width>
|
||||
<height>21</height>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<family>Maiandra GD</family>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Downloading...</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QProgressBar" name="bar">
|
||||
<property name="geometry">
|
||||
@ -63,11 +66,14 @@
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>BusyCursor</cursorShape>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
<number>54</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>true</bool>
|
||||
|
||||
230
GUI/SettingsDialog.ui
Normal file
230
GUI/SettingsDialog.ui
Normal file
@ -0,0 +1,230 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>240</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>240</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>240</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normaloff>../settings.ico</normaloff>../settings.ico</iconset>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="btnx">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>190</y>
|
||||
<width>341</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Cooper Black</family>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="title">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
<width>351</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>851MkPOP</family>
|
||||
<pointsize>22</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="Line" name="hr">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>50</y>
|
||||
<width>371</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_lang">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>90</y>
|
||||
<width>351</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Century Gothic</family>
|
||||
<pointsize>14</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>120</y>
|
||||
<width>351</width>
|
||||
<height>51</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="lang_select">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbtn_en">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>(E)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>English</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>E</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbtn_ru">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Century Gothic</family>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>(R)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Русский</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>R</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbtn_jp">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Rounded Mplus 1c</family>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>(N)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>日本語</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>N</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>btnx</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>btnx</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@ -8,88 +8,189 @@ from PyQt5.Qt import QThread, pyqtSignal
|
||||
from PyQt5 import QtCore
|
||||
from requests import get as load
|
||||
from bs4 import BeautifulSoup as parse
|
||||
from time import sleep
|
||||
from langswitch import switch
|
||||
import webbrowser as web
|
||||
from configer import config
|
||||
|
||||
|
||||
class GUI(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
loadUi('GUI/MainWindow.ui',self)
|
||||
self.dlbtn.clicked.connect(self.download)
|
||||
self.inprocess=False
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
loadUi('GUI/MainWindow.ui', self)
|
||||
self.applylang()
|
||||
self.btn.clicked.connect(self.download)
|
||||
self.actionSettings.triggered.connect(self.show_settings)
|
||||
self.actionHelp.triggered.connect(self.show_help)
|
||||
|
||||
def download(self):
|
||||
self.inprocess=True
|
||||
# Validating input
|
||||
songID=self.input.text()
|
||||
page=parse(load(f'https://www.newgrounds.com/audio/listen/{songID}').text,'html.parser')
|
||||
if page.find(id='pageerror') is not None:
|
||||
self.input.clear()
|
||||
return
|
||||
songTitle=page.find('title').text
|
||||
# Getting download link
|
||||
link='http://audio.ngfiles.com/'
|
||||
page=str(page)
|
||||
i=page.find('audio.ngfiles.com')+len('audio.ngfiles.com/')
|
||||
while not link.endswith('.mp3'):
|
||||
if page[i]!='\\': link+=page[i]
|
||||
i+=1
|
||||
# Locating file
|
||||
dist=QFileDialog.getSaveFileName(self,'Save File',
|
||||
link.split('/')[-1],
|
||||
'MP3 Audio File (*.mp3)')[0]
|
||||
if not dist: return
|
||||
# Downloading
|
||||
file=load(link,stream=True)
|
||||
global progress
|
||||
progress.label.setText(f'Downloading "{songTitle}"...')
|
||||
progress.setWindowTitle(f'Downloading "{songTitle}"...')
|
||||
progress.bar.setValue(0)
|
||||
progress.show()
|
||||
self.thread=DownloadThread(file,dist)
|
||||
self.thread.got_chunk.connect(lambda done:progress.bar.setValue(done))
|
||||
self.thread.finished.connect(self.thread.finish)
|
||||
self.thread.start()
|
||||
self.input.clear()
|
||||
self.inprocess=False
|
||||
def applylang(self):
|
||||
self.title.setText(switch['title'][config["lang"]])
|
||||
chfont(self.title, switch['title'][f'font_{config["lang"]}'])
|
||||
self.input.setPlaceholderText(switch['placeholder'][config["lang"]])
|
||||
chfont(self.input, switch['placeholder'][f'font_{config["lang"]}'])
|
||||
self.btn.setText(switch['btn'][config["lang"]])
|
||||
chfont(self.btn, switch['btn'][f'font_{config["lang"]}'])
|
||||
self.menu.setTitle(switch['menu'][config["lang"]])
|
||||
chfont(self.menubar, switch['menu'][f'font_{config["lang"]}'])
|
||||
self.actionSettings.setText(switch['settings'][config["lang"]])
|
||||
self.actionHelp.setText(switch['helpbtn'][config["lang"]])
|
||||
|
||||
def download(self):
|
||||
# Validating input
|
||||
songID = self.input.text()
|
||||
if not songID:
|
||||
self.notification = NotificationDialog(
|
||||
switch['empinp'][config["lang"]])
|
||||
self.notification.exec()
|
||||
return
|
||||
elif not songID.isdigit():
|
||||
self.notification = NotificationDialog(
|
||||
switch['typerr'][config["lang"]])
|
||||
self.notification.exec()
|
||||
return
|
||||
page = parse(load('https://www.newgrounds.com/audio/listen/'
|
||||
f'{songID}').text, 'html.parser')
|
||||
if page.find(id='pageerror') is not None:
|
||||
self.notification = NotificationDialog(
|
||||
switch['404'][config["lang"]])
|
||||
self.notification.exec()
|
||||
return
|
||||
self.songTitle = page.find('title').text
|
||||
# Getting download link
|
||||
link = 'http://audio.ngfiles.com/'
|
||||
page = str(page)
|
||||
i = page.find('audio.ngfiles.com')+len('audio.ngfiles.com/')
|
||||
while not link.endswith('.mp3'):
|
||||
if page[i] != '\\':
|
||||
link += page[i]
|
||||
i += 1
|
||||
# Locating file
|
||||
self.dist = (QFileDialog.
|
||||
getSaveFileName(self, switch['savefile'][config["lang"]],
|
||||
link.split('/')[-1],
|
||||
'MP3 Audio File (*.mp3)')[0])
|
||||
if not self.dist:
|
||||
return
|
||||
# Downloading
|
||||
self.file = load(link, stream=True)
|
||||
self.progress = ProgressDialog()
|
||||
self.progress.label.setText(
|
||||
switch['downloading'][config["lang"]](self.songTitle))
|
||||
self.progress.setWindowTitle(
|
||||
switch['downloading'][config["lang"]](self.songTitle))
|
||||
self.progress.bar.setValue(0)
|
||||
self.progress.exec()
|
||||
|
||||
def show_settings(self):
|
||||
self.settings = SettingsDialog()
|
||||
self.settings.exec()
|
||||
|
||||
def show_help(self):
|
||||
if config["lang"] == 'en':
|
||||
web.open('https://github.com/H1K0/NGAudioDownloader/blob/master/'
|
||||
'README.md#newgrounds-audio-downloader--', new=2)
|
||||
else:
|
||||
web.open('https://github.com/H1K0/NGAudioDownloader/blob/master/'
|
||||
f'README-{config["lang"].upper()}.md#'
|
||||
'newgrounds-audio-downloader--', new=2)
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
if event.key() == 16777216:
|
||||
self.close()
|
||||
elif event.key() == 16777220:
|
||||
self.download()
|
||||
|
||||
|
||||
class ProgressDialog(QDialog):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
loadUi('GUI/ProgressDialog.ui',self)
|
||||
self.setWindowFlags(self.windowFlags()&~QtCore.Qt.WindowCloseButtonHint)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
loadUi('GUI/ProgressDialog.ui', self)
|
||||
chfont(self.label, switch['downloading'][f'font_{config["lang"]}'])
|
||||
self.setWindowFlags(self.windowFlags() & ~
|
||||
QtCore.Qt.WindowCloseButtonHint)
|
||||
self.thread = DownloadThread()
|
||||
self.thread.got_chunk.connect(lambda done: self.bar.setValue(done))
|
||||
self.thread.finished.connect(self.thread.finish)
|
||||
self.thread.start()
|
||||
|
||||
|
||||
class DownloadThread(QThread):
|
||||
got_chunk=pyqtSignal(object)
|
||||
got_chunk = pyqtSignal(object)
|
||||
|
||||
def __init__(self,file,dist):
|
||||
super().__init__()
|
||||
self.file,self.dist=file,dist
|
||||
def __init__(self): super().__init__()
|
||||
|
||||
def run(self):
|
||||
global progress
|
||||
total=self.file.headers.get('content-length')
|
||||
if total is None: total=-1
|
||||
else: total=int(total)
|
||||
downloaded=0
|
||||
with open(self.dist,'wb') as out:
|
||||
for data in self.file.iter_content(chunk_size=max(total//100,1024)):
|
||||
downloaded+=len(data)
|
||||
out.write(data)
|
||||
self.got_chunk.emit(100*downloaded//total)
|
||||
def run(self):
|
||||
total = ngad.file.headers.get('content-length')
|
||||
if total is None:
|
||||
total = -1
|
||||
else:
|
||||
total = int(total)
|
||||
downloaded = 0
|
||||
with open(ngad.dist, 'wb') as out:
|
||||
for data in (ngad.file.
|
||||
iter_content(chunk_size=max(total//100, 1024))):
|
||||
downloaded += len(data)
|
||||
out.write(data)
|
||||
self.got_chunk.emit(100*downloaded//total)
|
||||
|
||||
def finish(self):
|
||||
global progress
|
||||
progress.hide()
|
||||
self.deleteLater()
|
||||
def finish(self):
|
||||
global ngad
|
||||
ngad.progress.hide()
|
||||
ngad.notification = NotificationDialog(
|
||||
switch['success'][config["lang"]](ngad.songTitle))
|
||||
ngad.notification.exec()
|
||||
self.deleteLater()
|
||||
|
||||
|
||||
class NotificationDialog(QDialog):
|
||||
def __init__(self, msg):
|
||||
super().__init__()
|
||||
loadUi('GUI/NotificationDialog.ui', self)
|
||||
self.label.setText(msg)
|
||||
chfont(self.label, switch['ntf'][f'font_{config["lang"]}'])
|
||||
self.setWindowFlags(self.windowFlags() & ~
|
||||
QtCore.Qt.WindowCloseButtonHint)
|
||||
ngad.input.clear()
|
||||
self.btn.clicked.connect(self.accept)
|
||||
|
||||
def accept(self):
|
||||
self.close()
|
||||
|
||||
|
||||
class SettingsDialog(QDialog):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
loadUi('GUI/SettingsDialog.ui', self)
|
||||
self.setWindowTitle(switch['settings'][config["lang"]])
|
||||
self.title.setText(switch['settings'][config["lang"]])
|
||||
self.label_lang.setText(switch['lang'][config["lang"]])
|
||||
chfont(self.label_lang, switch['lang'][f'font_{config["lang"]}'])
|
||||
if config["lang"] == 'en':
|
||||
self.rbtn_en.setChecked(True)
|
||||
elif config["lang"] == 'ru':
|
||||
self.rbtn_ru.setChecked(True)
|
||||
elif config["lang"] == 'jp':
|
||||
self.rbtn_jp.setChecked(True)
|
||||
self.newlang = config["lang"]
|
||||
self.rbtn_en.toggled.connect(lambda: self.chlang('en'))
|
||||
self.rbtn_ru.toggled.connect(lambda: self.chlang('ru'))
|
||||
self.rbtn_jp.toggled.connect(lambda: self.chlang('jp'))
|
||||
self.accepted.connect(self.updlang)
|
||||
|
||||
def chlang(self, newlang):
|
||||
if newlang != config["lang"]:
|
||||
self.newlang = newlang
|
||||
|
||||
def updlang(self):
|
||||
config["lang"] = self.newlang
|
||||
ngad.applylang()
|
||||
|
||||
|
||||
def chfont(unit, font): unit.setStyleSheet(f'font-family:{font}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from sys import argv
|
||||
app=QApplication(argv)
|
||||
ngad=GUI()
|
||||
progress=ProgressDialog()
|
||||
app = QApplication(argv)
|
||||
ngad = GUI()
|
||||
ngad.show()
|
||||
sys.exit(app.exec_())
|
||||
sys.exit(app.exec_())
|
||||
|
||||
Binary file not shown.
43
README-JP.md
Normal file
43
README-JP.md
Normal file
@ -0,0 +1,43 @@
|
||||
# [Newgrounds](https://newgrounds.com) Audio Downloader  
|
||||
|
||||
ま、Newgroundsと言えば、普通はオーディオページに結構見付かりやすいダウンロードボタンがあるけど、そのボタンのない奴もある。それも時々、素晴らしくて絶対にダウンロードしたいーってゆ奴も出てくるよな。そうなったらどうしろってんだ?
|
||||
|
||||
**コイツ**を使うんだ。
|
||||
|
||||
後、[英語](README.md#newgrounds-audio-downloader--)と[ロシア語](README-RU.md#newgrounds-audio-downloader--)のREADMEもある。
|
||||
|
||||
## 必要な物とは?
|
||||
|
||||
- 
|
||||
- `PyQt5`ライブラリ
|
||||
- `requests`ライブラリ
|
||||
- `bs4`ライブラリ
|
||||
- `click`ライブラリ
|
||||
|
||||
それともただだけを持って、この[アーカイブ](NGAudioDownloader.zip)をダウンロードして、[exeちゃん](NGAudioDownloader.exe)を使って楽になってもいい。
|
||||
|
||||
## 早速始めたい!
|
||||
|
||||
### 一般人の方(法)
|
||||
|
||||
ま、[`NGAudioDownloader.zip`](https://github.com/H1K0/NGAudioDownloader/raw/master/NGAudioDownloader.zip)をダウンロードして、ソイツをどっかで解凍して、`NGAudioDownloader.exe`を実行させるだけ。
|
||||
|
||||
<big>※注意:</big>コイツに時計のように正常に作動して欲しいってんなら、絶対に、アーカイブから抽出されたファイルを**移動/削除したりすんじゃねえぞ**!
|
||||
|
||||
### Pythonistの方(法)
|
||||
|
||||
ま、[リポジトリ全体をダウンロード](https://github.com/H1K0/NGAudioDownloader/archive/master.zip)して、`NGAudioDownloader.py`を実行だ。はい、終了~!
|
||||
|
||||
## で、後はどうするの?
|
||||
|
||||
簡単なもんやろ。コイツを実行して、NSI(*Newgrounds song ID*)を入力して、`Enter`ボタン押して、ダウンロード開始だ!
|
||||
|
||||
### どこ押したらいい?
|
||||
|
||||
- `Enter`でダウンロード開始
|
||||
- `Alt + S`で設定画面を開く
|
||||
- `F1`でヘルプを読む
|
||||
|
||||
## あのー、なんかビデオガイドとかないんですかー?
|
||||
|
||||
Pythonistならもう分かってる筈なんだから、[一般人向けのビデオガイド](https://yadi.sk/i/9krScj2BHcr3Rg)。
|
||||
45
README-RU.md
Normal file
45
README-RU.md
Normal file
@ -0,0 +1,45 @@
|
||||
# [Newgrounds](https://newgrounds.com) Audio Downloader  
|
||||
|
||||
_Или по-славянски: качалка музлишка с ньюграундс._
|
||||
|
||||
Ну, вообще-то на нг обычно есть кнопка для скачивания, однако иногда авторы запрещают прямое скачивание, и как бы сильно тебе ни нравилась песенка, ты не сможешь ее так просто заполучить.
|
||||
|
||||
Однако времена меняются, и теперь даже забаненные песенки можно скачать с помощью **этой самой проги**.
|
||||
|
||||
При желании можно почитать [ридмишку для пендосов и инглишменов](README.md#newgrounds-audio-downloader--) или [ридмишку для япошек](README-JP.md#newgrounds-audio-downloader--).
|
||||
|
||||
## Что расчехлять?
|
||||
|
||||
- 
|
||||
- Либа `PyQt5`
|
||||
- Либа `requests`
|
||||
- Либа `bs4`
|
||||
- Либа `click`
|
||||
|
||||
Или же можно тупо скачать [архивчик](NGAudioDownloader.zip), жмыхнуть ехешник и вообще не париться, если у тебя .
|
||||
|
||||
## Ну чо, пацаны, поехали!
|
||||
|
||||
### Старт юзверя
|
||||
|
||||
Короче, скачиваешь [`NGAudioDownloader.zip`](https://github.com/H1K0/NGAudioDownloader/raw/master/NGAudioDownloader.zip), извлекаешь куда-нибудь и фигачишь `NGAudioDownloader.exe`.
|
||||
|
||||
<big>※И ДА:</big> если хочешь, чтобы качалка работала, как швейцарские часики, **не смей перемещать/удалять** какие-либо файлы, извлеченные из архива! Иначе огребешь **БАН**. <span title="Это морда пажылого борова палучаеца." style="cursor:help">;-\
|
||||
|
||||
### Старт питониста
|
||||
|
||||
Короче, [скачиваешь весь репозиторий](https://github.com/H1K0/NGAudioDownloader/archive/master.zip) и фигачишь `NGAudioDownloader.py`. Финита. :3
|
||||
|
||||
## Ок, че дальше?
|
||||
|
||||
Проще пареной репы. Тупо запускаешь код, вбиваешь айдишник трека и — вуаля! — скачивание пошло!
|
||||
|
||||
### Куды тыкать-то?
|
||||
|
||||
- `Enter` запускает скачивание
|
||||
- `Alt + S` вызывает диалог настроек
|
||||
- `F1` вызывает ~~скорую~~ помощь
|
||||
|
||||
## А видеогайда нет?
|
||||
|
||||
Ну, предполагается, что питонисты и так прошаренные, так что вот [видеогайд для юзверей](https://yadi.sk/i/9krScj2BHcr3Rg).
|
||||
32
README.md
32
README.md
@ -1,10 +1,12 @@
|
||||
# Newgrounds Audio Downloader  
|
||||
# [Newgrounds](https://newgrounds.com) Audio Downloader  
|
||||
|
||||
Well, usually there's a download button on the audio page, but what to do if direct downloads are not allowed by the creator even though you love this song too much?
|
||||
|
||||
You just use **this**.
|
||||
|
||||
## Requirements
|
||||
You can also read the [Russian README](README-RU.md#newgrounds-audio-downloader--) or [Japanese README](README-JP.md#newgrounds-audio-downloader--).
|
||||
|
||||
## So, what do I actually need?
|
||||
|
||||
- 
|
||||
- `PyQt5` library
|
||||
@ -12,14 +14,30 @@ You just use **this**.
|
||||
- `bs4` library
|
||||
- `click` library
|
||||
|
||||
Or you just use the [`NGAudioDownloader.exe`](NGAudioDownloader.exe) so all you need is .
|
||||
Or you just use the `.exe` file from [`NGAudioDownloader.zip`](NGAudioDownloader.zip) so all you need is .
|
||||
|
||||
## Usage
|
||||
## Let's get it started!
|
||||
|
||||
### I'm a civilian
|
||||
|
||||
You just download [`NGAudioDownloader.zip`](https://github.com/H1K0/NGAudioDownloader/raw/master/NGAudioDownloader.zip), extract it somewhere and run the `NGAudioDownloader.exe`.
|
||||
|
||||
<big>※NOTE:</big> if you want this downloader working correctly **DO NOT move/delete** any files extracted from the archive!
|
||||
|
||||
### I'm a pythonist
|
||||
|
||||
You just [download the whole repository](https://github.com/H1K0/NGAudioDownloader/archive/master.zip) and run `NGAudioDownloader.py`. That's all. :3
|
||||
|
||||
## What should I do then?
|
||||
|
||||
It's easy as pie. You just run the downloader, enter your song ID and your file is being downloaded!
|
||||
|
||||
## Screenshots
|
||||
### Where should I press?
|
||||
|
||||

|
||||
- `Enter` starts download
|
||||
- `Alt + S` calls settings dialog
|
||||
- `F1` calls help
|
||||
|
||||

|
||||
## Is there any video guide?
|
||||
|
||||
Well, pythonists are considered already understanding how it all works, so here's the [video guide for civilians](https://yadi.sk/i/9krScj2BHcr3Rg).
|
||||
31
configer.py
Normal file
31
configer.py
Normal file
@ -0,0 +1,31 @@
|
||||
from json import load, dump
|
||||
from os import access, F_OK
|
||||
|
||||
|
||||
default = {
|
||||
"lang": "en"
|
||||
}
|
||||
|
||||
|
||||
class Config:
|
||||
def __init__(self):
|
||||
if access('config.json', F_OK):
|
||||
with open('config.json', encoding='utf-8') as file:
|
||||
self.data = load(file)
|
||||
else:
|
||||
self.data = default
|
||||
self.update()
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.data[key]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.data[key] = value
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
with open('config.json', 'w', encoding='utf-8') as file:
|
||||
dump(self.data, file)
|
||||
|
||||
|
||||
config = Config()
|
||||
90
langswitch.py
Normal file
90
langswitch.py
Normal file
@ -0,0 +1,90 @@
|
||||
switch = {
|
||||
"title": {
|
||||
"en": "<strong>Newgrounds Audio Downloader</strong> by <em>H1K0</em>",
|
||||
"ru": "<strong>Newgrounds Audio Downloader</strong> от <em>H1K0</em>",
|
||||
"jp": "<em>H1K0</em> の <strong>Newgrounds Audio Downloader</strong>",
|
||||
"font_en": "Comic Sans MS",
|
||||
"font_ru": "Comic Sans MS",
|
||||
"font_jp": "UD Digi Kyokasho N-R"
|
||||
},
|
||||
"placeholder": {
|
||||
"en": "Enter Newgrounds song ID.",
|
||||
"ru": "Введи айдишник трека на Newgrounds.",
|
||||
"jp": "NSIを入力しよう!",
|
||||
"font_en": "Maiandra GD",
|
||||
"font_ru": "Courier New",
|
||||
"font_jp": "Rounded Mplus 1c"
|
||||
},
|
||||
"btn": {
|
||||
"en": "Download!",
|
||||
"ru": "Скачать!",
|
||||
"jp": "ダウンロード!",
|
||||
"font_en": "Cooper Black",
|
||||
"font_ru": "851CHIKARA-DZUYOKU-KANA-A",
|
||||
"font_jp": "Nagurigaki Crayon"
|
||||
},
|
||||
"ntf": {
|
||||
"font_en": "Maiandra GD",
|
||||
"font_ru": "Courier New",
|
||||
"font_jp": "Rounded Mplus 1c"
|
||||
},
|
||||
"empinp": {
|
||||
"en": "Hey-hey, don't leave the input empty!",
|
||||
"ru": "Эй, ну хоть что-нибудь напиши!",
|
||||
"jp": "おいおい、何も入力してねえんじゃねえかよ!"
|
||||
},
|
||||
"typerr": {
|
||||
"en": "Newgrounds song ID consists of digits only!",
|
||||
"ru": "Айдишник трека состоит только из цифр!",
|
||||
"jp": "NSIは数字だけだ!"
|
||||
},
|
||||
"404": {
|
||||
"en": "And there's no song with this ID!",
|
||||
"ru": "А нет песенки с таким айдишником!",
|
||||
"jp": "そのNSIの曲は存在してないな!"
|
||||
},
|
||||
"savefile": {
|
||||
"en": "Save file",
|
||||
"ru": "Сохранить файл",
|
||||
"jp": "ファイル保存"
|
||||
},
|
||||
"downloading": {
|
||||
"en": lambda songTitle: f'Downloading «{songTitle}»...',
|
||||
"ru": lambda songTitle: f'Скачивание трека «{songTitle}»...',
|
||||
"jp": lambda songTitle: f'「{songTitle}」ダウンロード中・・・',
|
||||
"font_en": "Maiandra GD",
|
||||
"font_ru": "Courier New",
|
||||
"font_jp": "Rounded Mplus 1c"
|
||||
},
|
||||
"success": {
|
||||
"en": lambda songTitle: f'«{songTitle}» has been downloaded successfully!',
|
||||
"ru": lambda songTitle: f'«{songTitle}»: скачано!',
|
||||
"jp": lambda songTitle: f'「{songTitle}」ダウンロード完了!'
|
||||
},
|
||||
"menu": {
|
||||
"en": "MENU",
|
||||
"ru": "МЕНЮ",
|
||||
"jp": "メニュー",
|
||||
"font_en": "Century Gothic",
|
||||
"font_ru": "Century Gothic",
|
||||
"font_jp": "Rounded Mplus 1c"
|
||||
},
|
||||
"settings": {
|
||||
"en": "Settings",
|
||||
"ru": "Настройки",
|
||||
"jp": "設定"
|
||||
},
|
||||
"helpbtn": {
|
||||
"en": "Help",
|
||||
"ru": "Помощь",
|
||||
"jp": "ヘルプ"
|
||||
},
|
||||
"lang": {
|
||||
"en": "Language",
|
||||
"ru": "Язык",
|
||||
"jp": "言語",
|
||||
"font_en": "Century Gothic",
|
||||
"font_ru": "Century Gothic",
|
||||
"font_jp": "Rounded Mplus 1c"
|
||||
}
|
||||
}
|
||||
BIN
settings.ico
Normal file
BIN
settings.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Reference in New Issue
Block a user