diff --git a/twitchdl/commands/__init__.py b/twitchdl/commands/__init__.py
new file mode 100644
index 0000000..170520e
--- /dev/null
+++ b/twitchdl/commands/__init__.py
@@ -0,0 +1,9 @@
+from .clips import clips
+from .download import download
+from .videos import videos
+
+__all__ = [
+ clips,
+ download,
+ videos,
+]
diff --git a/twitchdl/commands/clips.py b/twitchdl/commands/clips.py
new file mode 100644
index 0000000..0a8fde0
--- /dev/null
+++ b/twitchdl/commands/clips.py
@@ -0,0 +1,113 @@
+import re
+
+from os import path
+
+from twitchdl import twitch, utils
+from twitchdl.download import download_file
+from twitchdl.exceptions import ConsoleError
+from twitchdl.output import print_out, print_clip, print_json
+
+
+def _continue():
+ print_out(
+ "\nThere are more clips. "
+ "Press Enter to continue, "
+ "Ctrl+C to break."
+ )
+
+ try:
+ input()
+ except KeyboardInterrupt:
+ return False
+
+ return True
+
+
+def _get_game_ids(names):
+ if not names:
+ return []
+
+ game_ids = []
+ for name in names:
+ print_out("Looking up game '{}'...".format(name))
+ game_id = twitch.get_game_id(name)
+ if not game_id:
+ raise ConsoleError("Game '{}' not found".format(name))
+ game_ids.append(int(game_id))
+
+ return game_ids
+
+
+def _clips_json(args):
+ clips = twitch.get_channel_clips(args.channel_name, args.period, args.limit)
+ nodes = list(edge["node"] for edge in clips["edges"])
+ print_json(nodes)
+
+
+def _clip_target_filename(clip):
+ url = clip["videoQualities"][0]["sourceURL"]
+ _, ext = path.splitext(url)
+ ext = ext.lstrip(".")
+
+ match = re.search(r"^(\d{4})-(\d{2})-(\d{2})T", clip["createdAt"])
+ date = "".join(match.groups())
+
+ name = "_".join([
+ date,
+ clip["id"],
+ clip["broadcaster"]["channel"]["name"],
+ utils.slugify(clip["title"]),
+ ])
+
+ return "{}.{}".format(name, ext)
+
+
+def _clips_download(args):
+ generator = twitch.channel_clips_generator(args.channel_name, args.period, 100)
+ for clips, _ in generator:
+ for clip in clips["edges"]:
+ clip = clip["node"]
+ url = clip["videoQualities"][0]["sourceURL"]
+ target = _clip_target_filename(clip)
+ if path.exists(target):
+ print_out("Already downloaded: {}".format(target))
+ else:
+ print_out("Downloading: {}".format(target))
+ download_file(url, target)
+
+
+def clips(args):
+ if args.json:
+ return _clips_json(args)
+
+ if args.download:
+ return _clips_download(args)
+
+ print_out("Loading clips...")
+ generator = twitch.channel_clips_generator(args.channel_name, args.period, args.limit)
+
+ first = 1
+
+ for clips, has_more in generator:
+ count = len(clips["edges"]) if "edges" in clips else 0
+ last = first + count - 1
+
+ print_out("-" * 80)
+ print_out("Showing clips {}-{} of ??".format(first, last))
+
+ for clip in clips["edges"]:
+ print_clip(clip["node"])
+
+ if not args.pager:
+ print_out(
+ "\nThere are more clips. "
+ "Increase the --limit or use --pager to see the rest."
+ )
+ break
+
+ if not has_more or not _continue():
+ break
+
+ first += count
+ else:
+ print_out("No clips found")
diff --git a/twitchdl/commands.py b/twitchdl/commands/download.py
similarity index 71%
rename from twitchdl/commands.py
rename to twitchdl/commands/download.py
index 7d94356..4fd0e4b 100644
--- a/twitchdl/commands.py
+++ b/twitchdl/commands/download.py
@@ -12,129 +12,7 @@ from urllib.parse import urlparse
from twitchdl import twitch, utils
from twitchdl.download import download_file, download_files
from twitchdl.exceptions import ConsoleError
-from twitchdl.output import print_out, print_clip, print_video, print_json
-
-
-def _continue():
- print_out(
- "\nThere are more videos. "
- "Press Enter to continue, "
- "Ctrl+C to break."
- )
-
- try:
- input()
- except KeyboardInterrupt:
- return False
-
- return True
-
-
-def _get_game_ids(names):
- if not names:
- return []
-
- game_ids = []
- for name in names:
- print_out("Looking up game '{}'...".format(name))
- game_id = twitch.get_game_id(name)
- if not game_id:
- raise ConsoleError("Game '{}' not found".format(name))
- game_ids.append(int(game_id))
-
- return game_ids
-
-
-def _clips_json(args):
- clips = twitch.get_channel_clips(args.channel_name, args.period, args.limit)
- nodes = list(edge["node"] for edge in clips["edges"])
- print_json(nodes)
-
-
-def _clips_download(args):
- generator = twitch.channel_clips_generator(args.channel_name, args.period, 100)
- for clips, _ in generator:
- for clip in clips["edges"]:
- clip = clip["node"]
- url = clip["videoQualities"][0]["sourceURL"]
- target = _clip_target_filename(clip)
- if path.exists(target):
- print_out("Already downloaded: {}".format(target))
- else:
- print_out("Downloading: {}".format(target))
- download_file(url, target)
-
-
-def clips(args):
- if args.json:
- return _clips_json(args)
-
- if args.download:
- return _clips_download(args)
-
- print_out("Loading clips...")
- generator = twitch.channel_clips_generator(args.channel_name, args.period, args.limit)
-
- first = 1
-
- for clips, has_more in generator:
- count = len(clips["edges"]) if "edges" in clips else 0
- last = first + count - 1
-
- print_out("-" * 80)
- print_out("Showing clips {}-{} of ??".format(first, last))
-
- for clip in clips["edges"]:
- print_clip(clip["node"])
-
- if not args.pager:
- print_out(
- "\nThere are more clips. "
- "Increase the --limit or use --pager to see the rest."
- )
- break
-
- if not has_more or not _continue():
- break
-
- first += count
- else:
- print_out("No clips found")
-
-
-def videos(args):
- game_ids = _get_game_ids(args.game)
-
- print_out("Loading videos...")
- generator = twitch.channel_videos_generator(
- args.channel_name, args.limit, args.sort, args.type, game_ids=game_ids)
-
- first = 1
-
- for videos, has_more in generator:
- count = len(videos["edges"]) if "edges" in videos else 0
- total = videos["totalCount"]
- last = first + count - 1
-
- print_out("-" * 80)
- print_out("Showing videos {}-{} of {}".format(first, last, total))
-
- for video in videos["edges"]:
- print_video(video["node"])
-
- if not args.pager and has_more:
- print_out(
- "\nThere are more videos. "
- "Increase the --limit or use --pager to see the rest."
- )
- break
-
- if not has_more or not _continue():
- break
-
- first += count
- else:
- print_out("No videos found")
+from twitchdl.output import print_out
def _parse_playlists(playlists_m3u8):
diff --git a/twitchdl/commands/videos.py b/twitchdl/commands/videos.py
new file mode 100644
index 0000000..b9553da
--- /dev/null
+++ b/twitchdl/commands/videos.py
@@ -0,0 +1,68 @@
+from twitchdl import twitch
+from twitchdl.exceptions import ConsoleError
+from twitchdl.output import print_out, print_video
+
+
+def _continue():
+ print_out(
+ "\nThere are more videos. "
+ "Press Enter to continue, "
+ "Ctrl+C to break."
+ )
+
+ try:
+ input()
+ except KeyboardInterrupt:
+ return False
+
+ return True
+
+
+def _get_game_ids(names):
+ if not names:
+ return []
+
+ game_ids = []
+ for name in names:
+ print_out("Looking up game '{}'...".format(name))
+ game_id = twitch.get_game_id(name)
+ if not game_id:
+ raise ConsoleError("Game '{}' not found".format(name))
+ game_ids.append(int(game_id))
+
+ return game_ids
+
+
+def videos(args):
+ game_ids = _get_game_ids(args.game)
+
+ print_out("Loading videos...")
+ generator = twitch.channel_videos_generator(
+ args.channel_name, args.limit, args.sort, args.type, game_ids=game_ids)
+
+ first = 1
+
+ for videos, has_more in generator:
+ count = len(videos["edges"]) if "edges" in videos else 0
+ total = videos["totalCount"]
+ last = first + count - 1
+
+ print_out("-" * 80)
+ print_out("Showing videos {}-{} of {}".format(first, last, total))
+
+ for video in videos["edges"]:
+ print_video(video["node"])
+
+ if not args.pager:
+ print_out(
+ "\nThere are more videos. "
+ "Increase the --limit or use --pager to see the rest."
+ )
+ break
+
+ if not has_more or not _continue():
+ break
+
+ first += count
+ else:
+ print_out("No videos found")