Prevents modifying the config if its already being modified.
Co-authored-by: Arjix <53124886+ArjixGamer@users.noreply.github.com>master
parent
a4f3eeee51
commit
913e6bc842
|
@ -1,7 +1,11 @@
|
|||
import click
|
||||
from anime_downloader.util import is_running
|
||||
if is_running(regex=r'python|anime|config', expected_matches=3):
|
||||
raise Exception('Another instance of "anime config" is already running!')
|
||||
|
||||
import os
|
||||
import click
|
||||
from tabulate import tabulate
|
||||
from anime_downloader.config import APP_DIR, Config
|
||||
from anime_downloader.config import APP_DIR, Config # noqa
|
||||
|
||||
data = Config._CONFIG
|
||||
|
||||
|
@ -20,7 +24,7 @@ def traverse_json(data, previous=''):
|
|||
click.echo(create_table(keys, previous))
|
||||
val = click.prompt("Select Option", type=int, default=1) - 1
|
||||
|
||||
if type(data[keys[val]]) == dict:
|
||||
if isinstance(data[keys[val]], dict):
|
||||
traverse_json(data[keys[val]], keys[val])
|
||||
else:
|
||||
click.echo(f"Current value: {data[keys[val]]}")
|
||||
|
@ -32,8 +36,9 @@ def traverse_json(data, previous=''):
|
|||
except (SyntaxError, NameError) as e:
|
||||
pass
|
||||
|
||||
if type(newVal) != type(data[keys[val]]):
|
||||
choice = click.confirm(f"{newVal} appears to be of an incorrect type. Continue")
|
||||
if not isinstance(newVal, type(data[keys[val]])):
|
||||
choice = click.confirm(
|
||||
f"{newVal} appears to be of an incorrect type. Continue")
|
||||
|
||||
if not choice:
|
||||
exit()
|
||||
|
@ -41,7 +46,8 @@ def traverse_json(data, previous=''):
|
|||
try:
|
||||
newVal = type(data[keys[val]])(newVal)
|
||||
except TypeError:
|
||||
click.echo(f"'{newVal}' could not be converted to the correct type")
|
||||
click.echo(
|
||||
f"'{newVal}' could not be converted to the correct type")
|
||||
exit()
|
||||
|
||||
data[keys[val]] = newVal
|
||||
|
|
|
@ -73,7 +73,8 @@ sitenames = [v[1] for v in ALL_ANIME_SITES]
|
|||
'--choice', '-c', type=int,
|
||||
help='Choice to start downloading given anime number '
|
||||
)
|
||||
@click.option("--skip-fillers", is_flag=True, help="Skip downloading of fillers.")
|
||||
@click.option("--skip-fillers", is_flag=True,
|
||||
help="Skip downloading of fillers.")
|
||||
@click.option(
|
||||
"--speed-limit",
|
||||
type=str,
|
||||
|
@ -149,16 +150,18 @@ def command(ctx, anime_url, episode_range, url, player, skip_download, quality,
|
|||
if skip_fillers and fillers:
|
||||
if episode.ep_no in fillers:
|
||||
logger.info(
|
||||
"Skipping episode {} because it is a filler.".format(episode.ep_no))
|
||||
"Skipping episode {} because it is a filler.".format(
|
||||
episode.ep_no))
|
||||
continue
|
||||
|
||||
if url:
|
||||
util.print_episodeurl(episode)
|
||||
|
||||
if player:
|
||||
episode_range = f"0:{len(animes)}" if not episode_range else episode_range
|
||||
util.play_episode(
|
||||
episode, player=player, title=f'{anime.title} - Episode {episode.ep_no}', episodes=episode_range)
|
||||
episode,
|
||||
player=player,
|
||||
title=f'{anime.title} - Episode {episode.ep_no}')
|
||||
|
||||
if not skip_download:
|
||||
if external_downloader:
|
||||
|
|
|
@ -50,7 +50,8 @@ sitenames = [v[1] for v in ALL_ANIME_SITES]
|
|||
@click.option(
|
||||
'--download-metadata', '-dm', is_flag=True,
|
||||
help='Download additional metadata')
|
||||
@click.option("--skip-fillers", is_flag=True, help="Skip downloading of fillers.")
|
||||
@click.option("--skip-fillers", is_flag=True,
|
||||
help="Skip downloading of fillers.")
|
||||
@click.pass_context
|
||||
def command(ctx, anime_url, episode_range, player,
|
||||
force_download, provider,
|
||||
|
@ -94,11 +95,13 @@ def command(ctx, anime_url, episode_range, player,
|
|||
raise exceptions.NotFoundError('No episodes found within index.')
|
||||
|
||||
# Stores the choices for each provider, to prevent re-prompting search.
|
||||
# As the current setup runs episode wise without this a 12 episode series would give 12+ prompts.
|
||||
# As the current setup runs episode wise without this a 12 episode series
|
||||
# would give 12+ prompts.
|
||||
choice_dict = {}
|
||||
|
||||
# Doesn't work on nyaa since it only returns one episode.
|
||||
for episode_range in range(int(episode_range_split[0]), int(episode_range_split[-1]) + 1):
|
||||
for episode_range in range(int(episode_range_split[0]), int(
|
||||
episode_range_split[-1]) + 1):
|
||||
# Exits if all providers are skipped.
|
||||
if [choice_dict[i] for i in choice_dict] == [0] * len(providers):
|
||||
logger.info('All providers skipped, exiting')
|
||||
|
@ -115,7 +118,8 @@ def command(ctx, anime_url, episode_range, player,
|
|||
|
||||
# To make the downloads use the correct name if URL:s are used.
|
||||
real_provider = cls.sitename if cls else provider
|
||||
# This will allow for animeinfo metadata in filename and one filename for multiple providers.
|
||||
# This will allow for animeinfo metadata in filename and one
|
||||
# filename for multiple providers.
|
||||
rep_dict = {
|
||||
'animeinfo_anime_title': util.slugify(info.title),
|
||||
'provider': util.slugify(real_provider),
|
||||
|
@ -128,11 +132,13 @@ def command(ctx, anime_url, episode_range, player,
|
|||
disable_ssl = False
|
||||
session.get_session().verify = not disable_ssl
|
||||
|
||||
# This is just to make choices in providers presistent between searches.
|
||||
# This is just to make choices in providers presistent between
|
||||
# searches.
|
||||
choice_provider = choice_dict.get(provider)
|
||||
|
||||
if not cls:
|
||||
_anime_url, choice_provider = util.search(anime_url, provider, val=choice_provider, season_info=info, ratio=ratio)
|
||||
_anime_url, choice_provider = util.search(
|
||||
anime_url, provider, val=choice_provider, season_info=info, ratio=ratio)
|
||||
choice_dict[provider] = choice_provider
|
||||
if choice_provider == 0 or not _anime_url:
|
||||
logger.info('Skipped')
|
||||
|
@ -145,7 +151,7 @@ def command(ctx, anime_url, episode_range, player,
|
|||
fallback_qualities=fallback_qualities)
|
||||
# I have yet to investigate all errors this can output
|
||||
# No sources found gives error which exits the script
|
||||
except:
|
||||
except BaseException:
|
||||
continue
|
||||
|
||||
logger.debug('Found anime: {}'.format(anime.title))
|
||||
|
@ -153,7 +159,8 @@ def command(ctx, anime_url, episode_range, player,
|
|||
try:
|
||||
animes = util.parse_ep_str(anime, str(episode_range))
|
||||
except RuntimeError:
|
||||
logger.error('No episode found with index {}'.format(episode_range))
|
||||
logger.error(
|
||||
'No episode found with index {}'.format(episode_range))
|
||||
continue
|
||||
except:
|
||||
logger.error('Unknown provider error')
|
||||
|
@ -167,23 +174,31 @@ def command(ctx, anime_url, episode_range, player,
|
|||
skip_download = True
|
||||
|
||||
if download_dir and not skip_download:
|
||||
logger.info('Downloading to {}'.format(os.path.abspath(download_dir)))
|
||||
logger.info(
|
||||
'Downloading to {}'.format(
|
||||
os.path.abspath(download_dir)))
|
||||
if skip_fillers:
|
||||
fillers = util.get_filler_episodes(query)
|
||||
for episode in animes:
|
||||
if skip_fillers and fillers:
|
||||
if episode.ep_no in fillers:
|
||||
logger.info("Skipping episode {} because it is a filler.".format(episode.ep_no))
|
||||
logger.info(
|
||||
"Skipping episode {} because it is a filler.".format(
|
||||
episode.ep_no))
|
||||
continue
|
||||
|
||||
if download_metadata:
|
||||
util.download_metadata(fixed_file_format, info.metadata, episode)
|
||||
util.download_metadata(
|
||||
fixed_file_format, info.metadata, episode)
|
||||
|
||||
if url:
|
||||
util.print_episodeurl(episode)
|
||||
|
||||
if player:
|
||||
util.play_episode(episode, player=player, title=f'{anime.title} - Episode {episode.ep_no}')
|
||||
util.play_episode(
|
||||
episode,
|
||||
player=player,
|
||||
title=f'{anime.title} - Episode {episode.ep_no}')
|
||||
|
||||
if not skip_download:
|
||||
if external_downloader:
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
from anime_downloader.util import is_running
|
||||
if is_running(regex=r'python|anime|watch', expected_matches=3):
|
||||
raise Exception('Another instance of "anime watch" is already running!')
|
||||
|
||||
|
||||
import click
|
||||
import logging
|
||||
import sys
|
||||
|
@ -90,17 +95,21 @@ def command(anime_name, new, update_all, _list, quality, remove,
|
|||
watcher.update_anime(anime)
|
||||
|
||||
if mal_import:
|
||||
PATH = anime_name # Hack, but needed to prompt the user. Uses the anime name as parameter.
|
||||
# Hack, but needed to prompt the user. Uses the anime name as
|
||||
# parameter.
|
||||
PATH = anime_name
|
||||
if PATH:
|
||||
query = PATH
|
||||
else:
|
||||
query = click.prompt('Enter the file path for the MAL .xml file', type=str)
|
||||
query = click.prompt(
|
||||
'Enter the file path for the MAL .xml file', type=str)
|
||||
|
||||
if query.endswith('.xml'):
|
||||
watcher._import_from_MAL(query)
|
||||
sys.exit(0)
|
||||
else:
|
||||
logging.error("Either the file selected was not an .xml or no file was selected.")
|
||||
logging.error(
|
||||
"Either the file selected was not an .xml or no file was selected.")
|
||||
sys.exit(1)
|
||||
|
||||
# Defaults the command to anime watch -l all.
|
||||
|
@ -128,13 +137,15 @@ def command(anime_name, new, update_all, _list, quality, remove,
|
|||
|
||||
def command_parser(command):
|
||||
# Returns<kUp> a list of the commands
|
||||
# new "no neverland" --provider vidstream > ['new', '--provider', 'no neverland', 'vidstream']
|
||||
# new "no neverland" --provider vidstream > ['new', '--provider', 'no
|
||||
# neverland', 'vidstream']
|
||||
|
||||
# Better than split(' ') because it accounts for quoutes.
|
||||
# Group 3 for quoted command
|
||||
command_regex = r'(("|\')(.*?)("|\')|.*?\s)'
|
||||
matches = re.findall(command_regex, command + " ")
|
||||
commands = [i[0].strip('"').strip("'").strip() for i in matches if i[0].strip()]
|
||||
commands = [i[0].strip('"').strip("'").strip()
|
||||
for i in matches if i[0].strip()]
|
||||
return commands
|
||||
|
||||
|
||||
|
@ -159,8 +170,10 @@ def list_animes(watcher, quality, download_dir, imp=None, _filter=None):
|
|||
watcher.new(url)
|
||||
|
||||
if key == 'swap':
|
||||
if vals[0] in ['all', 'watching', 'completed', 'planned', 'dropped', 'hold']:
|
||||
return list_animes(watcher, quality, download_dir, imp=imp, _filter=vals[0])
|
||||
if vals[0] in ['all', 'watching', 'completed',
|
||||
'planned', 'dropped', 'hold']:
|
||||
return list_animes(
|
||||
watcher, quality, download_dir, imp=imp, _filter=vals[0])
|
||||
|
||||
return list_animes(watcher, quality, download_dir, imp=imp)
|
||||
else:
|
||||
|
@ -272,7 +285,8 @@ def list_animes(watcher, quality, download_dir, imp=None, _filter=None):
|
|||
watcher.update(anime)
|
||||
|
||||
elif key == 'watch_status':
|
||||
if val in ['watching', 'completed', 'dropped', 'planned', 'all']:
|
||||
if val in ['watching', 'completed',
|
||||
'dropped', 'planned', 'all']:
|
||||
colours = {
|
||||
'watching': 'cyan',
|
||||
'completed': 'green',
|
||||
|
|
|
@ -493,3 +493,84 @@ class ClickListOption(click.Option):
|
|||
return ast.literal_eval(value)
|
||||
except:
|
||||
raise click.BadParameter(value)
|
||||
|
||||
|
||||
class Process:
|
||||
def __init__(self, name, cmdline, pid):
|
||||
self.name = name
|
||||
self.pid = pid
|
||||
self.cmdline = cmdline
|
||||
|
||||
def __str__(self):
|
||||
return str({
|
||||
'name': self.name,
|
||||
'pid': self.pid,
|
||||
'cmdline': self.cmdline
|
||||
})
|
||||
|
||||
|
||||
def getAllProcesses_Win32():
|
||||
placeholder = list()
|
||||
out = os.popen('WMIC path win32_process get Caption,Processid,Commandline').read(
|
||||
).split('\n')[::2][1:]
|
||||
for line in out:
|
||||
f = line.split()
|
||||
if f:
|
||||
if len(f) > 2:
|
||||
placeholder.append(
|
||||
Process(name=f[0], cmdline=f[1:-1], pid=int(f[-1])))
|
||||
else:
|
||||
placeholder.append(
|
||||
Process(name=f[0], cmdline=None, pid=int(f[-1])))
|
||||
return placeholder
|
||||
|
||||
|
||||
def getAllProcesses_unix():
|
||||
if sys.platform.startswith('darwin'):
|
||||
cmd = 'ps -Ao user,pid,%cpu,%mem,vsz,rss,tt,stat,start,time,command'
|
||||
return []
|
||||
elif sys.startswith('linux'):
|
||||
cmd = 'ps aux'
|
||||
out = os.popen(cmd).read()
|
||||
out = out.split('\n')[1:]
|
||||
placeholder = list()
|
||||
for line in out:
|
||||
try:
|
||||
line_list = line.lower().split()
|
||||
PID = line_list[1]
|
||||
NAME = line_list[10:][0]
|
||||
CMD = line_list[10:]
|
||||
placeholder.append(Process(name=NAME, cmdline=CMD, pid=PID))
|
||||
except IndexError:
|
||||
continue
|
||||
return placeholder
|
||||
|
||||
|
||||
def get_all_processes():
|
||||
if sys.platform.startswith('win'):
|
||||
return getAllProcesses_Win32()
|
||||
else:
|
||||
return getAllProcesses_unix()
|
||||
|
||||
|
||||
def is_running(regex, expected_matches):
|
||||
"""
|
||||
Iterates through all the processes that are running
|
||||
and returns a boolean if a process matches the regex passed
|
||||
and the groups matched are equal to or more than the expected_matches.
|
||||
"""
|
||||
|
||||
already_running = False
|
||||
dict_pids = {
|
||||
p.pid: [p.name, p.cmdline]
|
||||
for p in get_all_processes()
|
||||
}
|
||||
|
||||
if os.getpid() in dict_pids:
|
||||
del dict_pids[os.getpid()]
|
||||
for key, value in dict_pids.items():
|
||||
if value[1]:
|
||||
list_of_matches = re.findall(regex, ' '.join(value[1]))
|
||||
if list_of_matches and len(list_of_matches) >= expected_matches:
|
||||
already_running = True
|
||||
return already_running
|
||||
|
|
Loading…
Reference in New Issue