Source

gett-cli / gett_uploader.py

Diff from to

gett_uploader.py

 import argparse
 import signal
 import re
+import unicodedata
+import difflib
+import pprint
 
+from collections import defaultdict
 from itertools import chain
 from time import sleep
 
 from gett import *
 
 url_re = re.compile(r'^(?:http://ge\.tt/|/)?(\w+)(?:/(?:v/(\d+)/?)?)?$')
+DEFAULT_SIMILARITY_RATIO = .95
+
+def ascii_only(input_str):
+    nkfd_form = unicodedata.normalize('NFKD', input_str)
+    return ''.join([c for c in nkfd_form if not unicodedata.combining(c)])
+
+def similar(a, b, ratio_floor):
+        return difflib.SequenceMatcher(a=a, b=b).ratio() > ratio_floor
 
 def humansize(nbytes, pad=False):
     if nbytes is None:
         return ''
 
-    for (exp, unit) in ((9, 'GB'), (6, 'MB'), (3, 'KB'), (0, 'B')):
+    for (exp, unit) in ((9, 'GB'), (6, 'MB'), (3, 'KB'), (0, ' B')):
        if nbytes >= 10**exp:
            break
 
     print('--------------------------------------------------------------------------------')
 
     if share.files:
-        max_url = max([len(_.url) for _ in share.files.values()])
+        max_url = max(len(_.url) for _ in share.files.values())
 
         for file in share.files.values():
-            print('- %s  %s  %s  %s' % (shorten(file.name, 29), humansize(file.size, True), file.url.ljust(max_url), file.readystate))
+            print(' - %s  %s  %s  %s' % (shorten(file.name, 28), humansize(file.size, True), file.url.ljust(max_url), file.readystate))
     else:
-        print('- No files')
+        print(' - No files')
 
     print()
 
     parser = argparse.ArgumentParser(
             description="A command-line Ge.tt uploader and manager",
             epilog="Note that whenever http://ge.tt/<share_name>[/v/<fileid>] is expected, you can omit the http://ge.tt/ part.")
-    parser.add_argument('-D', dest='debug', action='store_true', help='Debug API calls')
+    parser.add_argument('-D', dest='debug', action='store_true', help='Debug API calls (warning: very verbose)')
+    # parser.add_argument('-R', '--similarity-ratio', default=DEFAULT_SIMILARITY_RATIO, type=float, dest='similarity_ratio', action='store_const', help='Similarity ratio (between 0 and 1) used for searching')
 
     upload_group = parser.add_argument_group('Upload options')
     upload_group.add_argument('file', nargs='*', type=pattern, help="Name of a file or a directory to upload. Patterns are allowed. This is not recursive.")
 
     other_group = parser.add_argument_group('Other actions')
     other_group.add_argument('--delete', nargs='+', dest='delete', metavar='URL', help='Delete a share or a file')
-    other_group.add_argument('--list', nargs='*', dest='list', metavar='SHARE_URL', help='List the files in the specified share. If no share is specified, list all your shares.')
+    other_group.add_argument('-l', '--list', nargs='*', dest='list', metavar='SHARE_URL', help='List the files in the specified share. If no share is specified, list all your shares.')
+    other_group.add_argument('-S', '--search', nargs='+', dest='search', metavar='SEARCH_TERMS', help='Search in share titles and file names.')
 
     auth_group = parser.add_argument_group('Authentification')
     auth_group.add_argument('-L', dest='ignore_token', action='store_true', help='Log-in with a different account than the stored one (if any)')
     auth_group.add_argument('-e', dest='email', help='Email to login with')
     auth_group.add_argument('-p', dest='password', help='Password to login with')
-    auth_group.add_argument('-k', dest='tokenfile', help='Ge.tt token file path (~/.gett-token)', default=os.path.join(home, '.gett-token'))
+    auth_group.add_argument('-k', dest='tokenfile', help='Ge.tt token file path (default: ~/.gett-token)', default=os.path.join(home, '.gett-token'))
 
     args = parser.parse_args()
 
     if args.debug:
-        import gett
-        gett.DEBUG = True
+        import logging
+        logging.basicConfig(level=logging.DEBUG)
 
     user = User()
     logged = False
 
         if reply.lower() == 'y':
             # Save the refreshtoken to the user's home directory (by default)
-
             with open(args.tokenfile, 'w') as file:
                 file.write(user.rtoken)
 
                 print('Deleted share: %s [%s]' % (share.title or 'Untitled', share.url))
         print()
 
+    # --search command
+
+    if args.search:
+        simplify = lambda s: ascii_only(s.lower())
+        phrase = ' '.join(args.search)
+        phrase_simple = simplify(phrase)
+        print('Searching for `%s`...\n' % phrase)
+
+        # ratio = args.similarity_ratio
+        # if not 0 <= ratio <= 1:
+        #     ratio = DEFAULT_SIMILARITY_RATIO
+        #     print('Bad similarity ratio value. Using default: %2.f' % DEFAULT_SIMILARITY_RATIO)
+        ratio = DEFAULT_SIMILARITY_RATIO
+        is_similar = lambda a, b: similar(a, b, ratio)
+
+        found_in_shares = []
+        found_in_files = defaultdict(lambda: [])
+        for share in user.list_shares():
+            title = simplify(share.title or '')
+            if phrase_simple in title or is_similar(phrase_simple, title):
+                found_in_shares.append(share)
+
+            for file in share.files.values():
+                fname = simplify(file.name or '')
+                if phrase_simple in fname or is_similar(phrase_simple, fname):
+                    found_in_files[share].append(file)
+
+        try:
+            max_url = max(len(_.url) for _ in found_in_shares)
+        except ValueError:
+            max_url = 0
+        try:
+            max_url_shares = max(len(_.url) for _ in found_in_files.keys())
+            max_url_files = max(max(len(_.url) for _ in f) for f in found_in_files.values())
+        except ValueError:
+            max_url_shares = max_url_files = 0
+
+        maximax = max(max_url, max_url_shares + 6, max_url_files + 3)
+
+        if found_in_shares:
+            print('Found %d share(s):' % len(found_in_shares))
+
+            for share in found_in_shares:
+                print(' - %s  %s%s' % (share.url.ljust(max_url), ' '*(maximax-max_url), shorten(share.title, 75 - max_url)))
+        else:
+            print('Nothing found in shares.')
+
+        print()
+
+        if found_in_files:
+
+            print('Found %d file(s):' % sum(map(len, found_in_files.values())))
+
+            for share, files in found_in_files.items():
+                print(' - Share %s  %s%s' % (share.url.ljust(max_url_shares), ' '*(maximax-max_url_shares-6), shorten(share.title, 69 - max_url_shares)))
+
+                for file in files:
+                    print('    - %s  %s%s' % (file.url.ljust(max_url_files), ' '*(maximax-max_url_files-6), shorten(file.name, 72 - max_url_files)))
+        else:
+            print('Nothing found in files.')
+
+        print()
+
     # File uploads
 
     if args.file: