From 0632826827535ed7ff885ca44c7054c261449733 Mon Sep 17 00:00:00 2001
From: Ricter Z <ricterzheng@gmail.com>
Date: Sun, 12 Aug 2018 22:43:36 +0800
Subject: [PATCH] download by tagname #15

---
 .travis.yml         |  1 +
 nhentai/cmdline.py  | 11 ++++-----
 nhentai/command.py  | 12 +++++++---
 nhentai/constant.py |  2 ++
 nhentai/parser.py   | 54 +++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 68 insertions(+), 12 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 698dfa8..21c1028 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,3 +14,4 @@ script:
     - NHENTAI=https://nhentai.net nhentai --search umaru
     - NHENTAI=https://nhentai.net nhentai --id=152503,146134 -t 10 --output=/tmp/
     - NHENTAI=https://nhentai.net nhentai -l nhentai_test:nhentai --output=/tmp/
+    - NHENTAI=https://nhentai.net nhentai --tag lolicon
\ No newline at end of file
diff --git a/nhentai/cmdline.py b/nhentai/cmdline.py
index d3453d2..51b541f 100644
--- a/nhentai/cmdline.py
+++ b/nhentai/cmdline.py
@@ -42,7 +42,7 @@ def cmd_parser():
     parser.add_option('--search', type='string', dest='keyword', action='store', help='search doujinshi by keyword')
     parser.add_option('--page', type='int', dest='page', action='store', default=1,
                       help='page number of search result')
-    parser.add_option('--tags', type='string', dest='tags', action='store', help='download doujinshi by tags')
+    parser.add_option('--tag', type='string', dest='tag', action='store', help='download doujinshi by tag')
     parser.add_option('--output', type='string', dest='output_dir', action='store', default='',
                       help='output dir')
     parser.add_option('--threads', '-t', type='int', dest='threads', action='store', default=5,
@@ -86,20 +86,17 @@ def cmd_parser():
         if not args.is_download:
             logger.warning('YOU DO NOT SPECIFY `--download` OPTION !!!')
 
-    if args.tags:
-        logger.warning('`--tags` is under construction')
-        exit(1)
-
     if args.id:
         _ = map(lambda id: id.strip(), args.id.split(','))
         args.id = set(map(int, filter(lambda id_: id_.isdigit(), _)))
 
-    if (args.is_download or args.is_show) and not args.id and not args.keyword and not args.login:
+    if (args.is_download or args.is_show) and not args.id and not args.keyword and \
+            not args.login and not args.tag:
         logger.critical('Doujinshi id(s) are required for downloading')
         parser.print_help()
         exit(1)
 
-    if not args.keyword and not args.id and not args.login:
+    if not args.keyword and not args.id and not args.login and not args.tag:
         parser.print_help()
         exit(1)
 
diff --git a/nhentai/command.py b/nhentai/command.py
index 5f08cef..b1492a6 100644
--- a/nhentai/command.py
+++ b/nhentai/command.py
@@ -5,7 +5,7 @@ import signal
 import platform
 
 from nhentai.cmdline import cmd_parser, banner
-from nhentai.parser import doujinshi_parser, search_parser, print_doujinshi, login_parser
+from nhentai.parser import doujinshi_parser, search_parser, print_doujinshi, login_parser, tag_guessing, tag_parser
 from nhentai.doujinshi import Doujinshi
 from nhentai.downloader import Downloader
 from nhentai.logger import logger
@@ -27,13 +27,19 @@ def main():
         for doujinshi_info in login_parser(username=username, password=password):
             doujinshi_list.append(Doujinshi(**doujinshi_info))
 
+    if options.tag:
+        tag_id = tag_guessing(options.tag)
+        if tag_id:
+            doujinshis = tag_parser(tag_id)
+            print_doujinshi(doujinshis)
+            if options.is_download:
+                doujinshi_ids = map(lambda d: d['id'], doujinshis)
+
     if options.keyword:
         doujinshis = search_parser(options.keyword, options.page)
         print_doujinshi(doujinshis)
         if options.is_download:
             doujinshi_ids = map(lambda d: d['id'], doujinshis)
-    else:
-        doujinshi_ids = options.id
 
     if doujinshi_ids:
         for id_ in doujinshi_ids:
diff --git a/nhentai/constant.py b/nhentai/constant.py
index 55e2fa4..efd5022 100644
--- a/nhentai/constant.py
+++ b/nhentai/constant.py
@@ -7,6 +7,8 @@ BASE_URL = os.getenv('NHENTAI', 'https://nhentai.net')
 
 DETAIL_URL = '%s/api/gallery' % BASE_URL
 SEARCH_URL = '%s/api/galleries/search' % BASE_URL
+TAG_URL = '%s/tag' % BASE_URL
+TAG_API_URL = '%s/api/galleries/tagged' % BASE_URL
 LOGIN_URL = '%s/login/' % BASE_URL
 FAV_URL = '%s/favorites/' % BASE_URL
 
diff --git a/nhentai/parser.py b/nhentai/parser.py
index bef5730..1517e72 100644
--- a/nhentai/parser.py
+++ b/nhentai/parser.py
@@ -110,11 +110,18 @@ def doujinshi_parser(id_):
     doujinshi['pages'] = len(response['images']['pages'])
 
     # gain information of the doujinshi
-    needed_fields = ['character', 'artist', 'language']
+    needed_fields = ['character', 'artist', 'language', 'tag']
     for tag in response['tags']:
         tag_type = tag['type']
         if tag_type in needed_fields:
-            if tag_type not in doujinshi:
+            if tag_type == 'tag':
+                if tag_type not in doujinshi:
+                    doujinshi[tag_type] = {}
+
+                tag['name'] = tag['name'].replace(' ', '-')
+                tag['name'] = tag['name'].lower()
+                doujinshi[tag_type][tag['name']] = tag['id']
+            elif tag_type not in doujinshi:
                 doujinshi[tag_type] = tag['name']
             else:
                 doujinshi[tag_type] += tag['name']
@@ -154,5 +161,48 @@ def print_doujinshi(doujinshi_list):
                 tabulate(tabular_data=doujinshi_list, headers=headers, tablefmt='rst'))
 
 
+def tag_parser(tag_id):
+    logger.info('Get doujinshi of tag id: {0}'.format(tag_id))
+    result = []
+    response = request('get', url=constant.TAG_API_URL, params={'sort': 'popular', 'tag_id': tag_id}).json()
+
+    for row in response['result']:
+        title = row['title']['english']
+        title = title[:85] + '..' if len(title) > 85 else title
+        result.append({'id': row['id'], 'title': title})
+
+    if not result:
+        logger.warn('Not found anything of tag id {}'.format(tag_id))
+
+    return result
+
+
+def tag_guessing(tag_name):
+    tag_name = tag_name.lower()
+    tag_name = tag_name.replace(' ', '-')
+    logger.info('Trying to get tag_id of tag \'{0}\''.format(tag_name))
+    response = request('get', url='%s/%s' % (constant.TAG_URL, tag_name)).content
+    html = BeautifulSoup(response, 'html.parser')
+    first_item = html.find('div', attrs={'class': 'gallery'})
+    if not first_item:
+        logger.error('Cannot find doujinshi id of tag \'{0}\''.format(tag_name))
+        return
+
+    doujinshi_id = re.findall('(\d+)', first_item.a.attrs['href'])
+    if not doujinshi_id:
+        logger.error('Cannot find doujinshi id of tag \'{0}\''.format(tag_name))
+        return
+
+    ret = doujinshi_parser(doujinshi_id[0])
+    if 'tag' in ret and tag_name in ret['tag']:
+        tag_id = ret['tag'][tag_name]
+        logger.info('Tag id of tag \'{0}\' is {1}'.format(tag_name, tag_id))
+    else:
+        logger.error('Cannot find doujinshi id of tag \'{0}\''.format(tag_name))
+        return
+
+    return tag_id
+
+
 if __name__ == '__main__':
     print(doujinshi_parser("32271"))