...
 
Commits (7)
V 4.0.0:
- Went over to completely rely on python's built-in logging
- Throttle value is now passed as parameter
- Logging to files now active by default
V 3.3.0:
- Added download speed progress
- Fixed slow download speeds
......
......@@ -18,59 +18,54 @@ You should have received a copy of the GNU General Public License
along with xdcc-dl. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
import logging
import argparse
from typing import List
from requests.exceptions import ConnectionError
from puffotter.init import cli_start, argparse_add_verbosity
from puffotter.prompt import selection_prompt
from xdcc_dl import sentry_dsn
from xdcc_dl.xdcc.exceptions import DownloadIncomplete
from xdcc_dl.helper import set_throttle_value, set_logging_level, prepare_packs
from xdcc_dl.helper import prepare_packs, add_xdcc_argparse_arguments
from xdcc_dl.entities import XDCCPack
from xdcc_dl.logging import Logger
from xdcc_dl.xdcc import download_packs
from xdcc_dl.pack_search.SearchEngine import SearchEngineType
def main(args: argparse.Namespace):
def main(args: argparse.Namespace, logger: logging.Logger):
"""
Conducts a XDCC pack search with the option to immediately download any
found packs
:param args: The command line arguments
:param logger: The logger to use
:return: None
"""
try:
set_logging_level(args.quiet, args.verbose, args.debug, args.silent)
set_throttle_value(args.throttle)
search_engine = SearchEngineType.resolve(args.search_engine)
results = search_engine.search(args.search_term)
for i, result in enumerate(results):
Logger().print("{}: {}".format(i + 1, result))
selection = input("Enter the packs to download: ")
parsepacks = XDCCPack.from_xdcc_message(
"/msg A xdcc send #{}".format(selection)
)
packs = []
for pack in parsepacks: # type: XDCCPack
packs.append(results[pack.packnumber - 1])
# noinspection PyTypeChecker
packs = selection_prompt(results) # type: List[XDCCPack]
prepare_packs(packs, args.out)
for pack in packs:
Logger().info("Downloading pack {}".format(pack))
logger.info("Downloading pack {}".format(pack))
download_packs(
packs,
timeout=args.timeout,
fallback_channel=args.fallback_channel
fallback_channel=args.fallback_channel,
throttle=args.throttle
)
except ConnectionError:
print("Connection Error, could not conduct search")
except DownloadIncomplete:
Logger().warning("Download incomplete.")
logger.warning("Download incomplete.")
raise KeyboardInterrupt()
except ValueError:
print("Invalid throttle value {}".format(args.throttle))
if __name__ == "__main__":
......@@ -80,24 +75,7 @@ if __name__ == "__main__":
default=SearchEngineType.HORRIBLESUBS.name.lower(),
choices=SearchEngineType.choices(True),
help="The Search Engine to use")
parser.add_argument("-s", "--server",
default="irc.rizon.net",
help="Specifies the IRC Server. "
"Defaults to irc.rizon.net")
parser.add_argument("-o", "--out",
help="Specifies the target file. "
"Defaults to the pack's file name. "
"When downloading multiple packs, index "
"numbers will be appended to the filename")
parser.add_argument("-t", "--throttle",
help="Limits the download speed of xdcc-dl. "
"Append K,M or G for more convenient units")
parser.add_argument("--timeout", default=120, type=int,
help="Sets a timeout for starting the download")
parser.add_argument("--silent", action="store_true",
help="Disables all print output")
parser.add_argument("--fallback-channel",
help="Fallback channel in case ")
add_xdcc_argparse_arguments(parser)
argparse_add_verbosity(parser)
cli_start(
main, parser,
......
......@@ -19,26 +19,24 @@ along with xdcc-dl. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
import os
import logging
import argparse
from puffotter.init import cli_start, argparse_add_verbosity
from xdcc_dl import sentry_dsn
from xdcc_dl.xdcc import download_packs
from xdcc_dl.helper import set_throttle_value, set_logging_level, prepare_packs
from xdcc_dl.helper import prepare_packs, add_xdcc_argparse_arguments
from xdcc_dl.entities import XDCCPack
from xdcc_dl.logging import Logger
from xdcc_dl.xdcc.exceptions import DownloadIncomplete
def main(args: argparse.Namespace):
def main(args: argparse.Namespace, logger: logging.Logger):
"""
Starts the main method of the program
:param args: The command line arguments
:param logger: The logger to use
:return: None
"""
try:
set_throttle_value(args.throttle)
set_logging_level(args.quiet, args.verbose, args.debug, args.silent)
packs = XDCCPack.from_xdcc_message(
args.message, os.getcwd(), args.server
)
......@@ -47,12 +45,15 @@ def main(args: argparse.Namespace):
download_packs(
packs,
timeout=args.timeout,
fallback_channel=args.fallback_channel
fallback_channel=args.fallback_channel,
throttle=args.throttle
)
except DownloadIncomplete:
Logger().warning("Download incomplete.")
logger.warning("Download incomplete.")
raise KeyboardInterrupt()
except ValueError:
print("Invalid throttle value {}".format(args.throttle))
if __name__ == "__main__":
......@@ -61,25 +62,8 @@ if __name__ == "__main__":
help="An XDCC Message. Supports ranges (1-100), "
"ranges with steps (1-100;2) as well as "
"comma-separated packs: (1,2,3).")
parser.add_argument("-s", "--server",
default="irc.rizon.net",
help="Specifies the IRC Server. "
"Defaults to irc.rizon.net")
parser.add_argument("-o", "--out",
help="Specifies the target file. "
"Defaults to the pack's file name. "
"When downloading multiple packs, index "
"numbers will be appended to the filename")
parser.add_argument("-t", "--throttle",
help="Limits the download speed of xdcc-dl. "
"Append K,M or G for more convenient units")
parser.add_argument("--timeout", default=120, type=int,
help="Sets a timeout for starting the download")
parser.add_argument("--fallback-channel",
help="Fallback channel in case ")
add_xdcc_argparse_arguments(parser)
argparse_add_verbosity(parser)
parser.add_argument("--silent", action="store_true",
help="Disables all print output")
cli_start(
main, parser,
sentry_dsn=sentry_dsn,
......
3.3.0
\ No newline at end of file
4.0.0
\ No newline at end of file
......@@ -17,51 +17,9 @@ You should have received a copy of the GNU General Public License
along with xdcc-dl. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
import sys
import logging
from argparse import ArgumentParser
from typing import List, Optional
from xdcc_dl.logging import Logger
from xdcc_dl.entities.XDCCPack import XDCCPack
from xdcc_dl.xdcc.XDCCClient import XDCCClient
from puffotter.units import byte_string_to_byte_count
def set_throttle_value(throttle_string: str):
"""
Sets the throttle value of the XDCC Client globally based on a string in
the form <Bytes><|k|m|g> (kilo, mega, giga)
:param throttle_string: The string to parse
:return: None
"""
try:
if throttle_string is not None:
limit = byte_string_to_byte_count(throttle_string)
XDCCClient.download_limit = limit
except ValueError:
print("Invalid throttle value")
sys.exit(1)
def set_logging_level(quiet: bool, verbose: bool, debug: bool, silent: bool):
"""
Sets the logging level based on a combination of flags
If all flags are False, the logging level will be set to WARNING
:param quiet: If set to True, will set logging to ERROR
:param verbose: If set to True, will set logging to INFO
:param debug: If set to True, will set logging to DEBUG
:param silent: If set to True, will disable ALL printing
:return: None
"""
if silent:
Logger.logging_level = -1
elif quiet:
Logger.logging_level = logging.ERROR
elif verbose:
Logger.logging_level = logging.INFO
elif debug:
Logger.logging_level = logging.DEBUG
else:
Logger.logging_level = logging.WARNING
def prepare_packs(packs: List[XDCCPack], location: Optional[str]):
......@@ -71,7 +29,6 @@ def prepare_packs(packs: List[XDCCPack], location: Optional[str]):
:param packs: The packs to prepare
:return: None
"""
if location is not None:
if len(packs) == 1:
packs[0].set_filename(location, True)
......@@ -79,3 +36,28 @@ def prepare_packs(packs: List[XDCCPack], location: Optional[str]):
# Generate unique names for each pack file
for i, pack in enumerate(packs):
pack.set_filename(location + "-" + str(i).zfill(3), True)
def add_xdcc_argparse_arguments(parser: ArgumentParser):
"""
Adds relevant command line arguments for an argument parser for xdcc-dl
:param parser: The parser to modify
:return: None
"""
parser.add_argument("-s", "--server",
default="irc.rizon.net",
help="Specifies the IRC Server. "
"Defaults to irc.rizon.net")
parser.add_argument("-o", "--out",
help="Specifies the target file. "
"Defaults to the pack's file name. "
"When downloading multiple packs, index "
"numbers will be appended to the filename")
parser.add_argument("-t", "--throttle", default=-1,
help="Limits the download speed of xdcc-dl. "
"Append K,M or G for more convenient units")
parser.add_argument("--timeout", default=120, type=int,
help="Sets a timeout for starting the download")
parser.add_argument("--fallback-channel",
help="Fallback channel in case a channel could not"
"be joined automatically using WHOIS commands")
"""LICENSE
Copyright 2016 Hermann Krumrey <hermann@krumreyh.com>
This file is part of xdcc-dl.
xdcc-dl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
xdcc-dl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with xdcc-dl. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
import logging
from typing import Optional
from datetime import datetime
from subprocess import check_output, CalledProcessError
from colorama import Fore, Back, Style
# noinspection PyMethodMayBeStatic
class Logger(object):
"""
Class that handles log and print calls in the bot
"""
logging_level = logging.WARNING
"""
The logging level to display
"""
last_end = "\n"
"""
Keeps track of the last character to be printed
"""
def log(self, message: str, level: Optional[int], back: Back = Back.BLACK,
fore: Fore = Fore.GREEN, end: str = "\n"):
"""
Logs a message at the specified logging level
:param message: The message to log
:param level: The level at which to log the message.
If set as None, will always be printed.
:param back: The background color to print
:param fore: The foreground color to print
:param end: Characters to append to the string (Default newline)
:return: None
"""
if self.logging_level == -1:
return
if level is None or self.logging_level <= level:
if self.last_end == "\r" and end != "\r":
print()
log_message = datetime.now().strftime("[%Y-%d-%m:%H-%M-%S]")
log_message += " " + fore + back + message
try:
rows, _columns = check_output(['stty', 'size']).split()
columns = int(_columns)
except (ValueError, CalledProcessError):
columns = 80
log_message = log_message[0:columns]
print(log_message + Style.RESET_ALL, end=end)
self.last_end = end
def info(self, message: str, back: Back = Back.BLACK,
fore: Fore = Fore.GREEN, end: str = "\n"):
"""
Logs a message at the INFO level
:param message: The message to log
:param back: The background color to print
:param fore: The foreground color to print
:param end: Characters to append to the string (Default newline)
:return: None
"""
self.log(message, logging.INFO, back, fore, end)
def debug(self, message: str, back: Back = Back.WHITE,
fore: Fore = Fore.BLACK, end: str = "\n"):
"""
Logs a message at the DEBUG level
:param message: The message to log
:param back: The background color to print
:param fore: The foreground color to print
:param end: Characters to append to the string (Default newline)
:return: None
"""
self.log(message, logging.DEBUG, back, fore, end)
def error(self, message: str, back: Back = Back.RED,
fore: Fore = Fore.BLUE, end: str = "\n"):
"""
Logs a message at the ERROR level
:param message: The message to log
:param back: The background color to print
:param fore: The foreground color to print
:param end: Characters to append to the string (Default newline)
:return: None
"""
self.log(message, logging.ERROR, back, fore, end)
def warning(self, message: str, back: Back = Back.YELLOW,
fore: Fore = Fore.BLUE, end: str = "\n"):
"""
Logs a message at the WARNING level
:param message: The message to log
:param back: The background color to print
:param fore: The foreground color to print
:param end: Characters to append to the string (Default newline)
:return: None
"""
self.log(message, logging.WARNING, back, fore, end)
def print(self, message: str, back: Back = Back.BLACK,
fore: Fore = Fore.GREEN, end: str = "\n"):
"""
Prints a message
:param message: The message to print
:param back: The background color to print
:param fore: The foreground color to print
:param end: Characters to append to the string (Default newline)
:return: None
"""
self.log(message, None, back, fore, end)
"""LICENSE
Copyright 2016 Hermann Krumrey <hermann@krumreyh.com>
This file is part of xdcc-dl.
xdcc-dl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
xdcc-dl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with xdcc-dl. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
from xdcc_dl.logging.Logger import Logger
This diff is collapsed.
......@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with xdcc-dl. If not, see <http://www.gnu.org/licenses/>.
LICENSE"""
from typing import List, Optional
from typing import List, Optional, Union
from xdcc_dl.entities.XDCCPack import XDCCPack
from xdcc_dl.xdcc.XDCCClient import XDCCClient
......@@ -25,19 +25,24 @@ from xdcc_dl.xdcc.XDCCClient import XDCCClient
def download_packs(
packs: List[XDCCPack],
timeout: int = 120,
fallback_channel: Optional[str] = None
fallback_channel: Optional[str] = None,
throttle: Union[int, str] = -1
):
"""
Downloads a list of XDCC Packs
:param packs: The packs to download
:param timeout: Specifies timeout time
:param fallback_channel: A fallback channel for when no channels were found
:param throttle: Throttles the download to n bytes per second.
If this value is <= 0, the download speed will be
unlimited
:return: None
"""
for pack in packs:
client = XDCCClient(
pack,
timeout=timeout,
fallback_channel=fallback_channel
fallback_channel=fallback_channel,
throttle=throttle
)
client.download()