|
| 1 | +import os |
| 2 | +import re |
| 3 | +import traceback |
1 | 4 | from warnings import filterwarnings
|
| 5 | + |
2 | 6 | from PIL import Image, ImageOps
|
3 | 7 | from jikanpy import Jikan
|
| 8 | +# noinspection PyPackageRequirements |
| 9 | +from mal import AnimeSearch |
4 | 10 | from requests import get
|
5 |
| -from time import sleep |
6 |
| -import re |
7 |
| -import os |
8 | 11 |
|
9 |
| -print('''Run this in your anime folder |
10 |
| -For help, info and memes, check out |
11 |
| -https://github.com/notdedsec/anicon |
12 |
| -''') |
13 |
| - |
14 |
| -sleep(1) |
15 |
| -jikan = Jikan() |
16 | 12 | filterwarnings("ignore")
|
17 |
| -folderlist = next(os.walk('.'))[1] |
18 |
| -if folderlist is None or len(folderlist) == 0: |
19 |
| - # In case the file is placed inside an inner most directory which contains only files and no other folders, this list will be empty. |
20 |
| - # Thus adding the current directory path as an element of the list. |
21 |
| - folderlist = [str(os.getcwd())] |
22 |
| -automode = True if input('Use AutoMode? Y/N : ').upper() == 'Y' else False |
23 |
| - |
24 |
| -def getname(name: str) -> str: |
25 |
| - |
26 |
| - lastwords = ['bd', 's0', '480p', '720p', '1080p'] |
27 |
| - wordstoremove = ['bluray', 'x265', 'x264', 'hevc', 'hi10p', 'avc', '10bit', 'dual', 'audio', 'eng', 'english', 'subbed', 'sub', 'dubbed', 'dub'] |
28 |
| - |
29 |
| - name = name.lower().replace('_', ' ').replace('.', ' ') |
30 |
| - |
31 |
| - for word in wordstoremove: |
32 |
| - name = name.replace(word, '') |
33 |
| - |
34 |
| - name = re.sub(r"(?<=\[)(.*?)(?=\])", '', name) |
35 |
| - name = re.sub(r"(?<=\()(.*?)(?=\))", '', name) |
36 |
| - name = name.replace('()', '').replace('[]', '') |
37 |
| - |
38 |
| - for word in lastwords: |
39 |
| - rexstr = "(?<=" + word + ")(?s)(.*$)" |
40 |
| - name = re.sub(rexstr, '', name).replace(word, '') |
41 |
| - |
42 |
| - return(name.strip()) |
43 |
| - |
44 |
| -def getartwork(name: str) -> tuple: |
45 |
| - |
46 |
| - results = jikan.search('anime', name, parameters={'type': 'tv'}) |
47 |
| - |
48 |
| - print('\n' + name.title(), end = '') |
49 |
| - counter = 1 |
50 |
| - for result in results['results']: |
51 |
| - if automode: |
52 |
| - print(' - ' + result['title']) |
53 |
| - ch = 1 |
54 |
| - break |
55 |
| - else: |
56 |
| - print('\n' + str(counter) + ' - ' + result['title'], end = '') |
57 |
| - |
58 |
| - if counter == 5: |
59 |
| - break |
60 |
| - counter += 1 |
61 |
| - |
62 |
| - if not automode: |
63 |
| - ch = input('\n>') |
64 |
| - if ch == '': |
65 |
| - ch = 1 |
66 |
| - |
67 |
| - return (results['results'][int(ch)-1]['image_url'], results['results'][int(ch)-1]['type']) |
68 |
| - |
69 |
| -def createicon(folder: str, link: str): |
| 13 | +jikan = Jikan() |
70 | 14 |
|
71 |
| - art = get(link) |
72 |
| - open(jpgfile, 'wb').write(art.content) |
73 | 15 |
|
74 |
| - img = Image.open(jpgfile) |
| 16 | +def get_name(folder_name: str) -> str: |
| 17 | + last_words = ['bd', 's0', '480p', '720p', '1080p'] |
| 18 | + words_to_remove = ['bluray', 'x265', 'x264', 'hevc', 'hi10p', 'avc', '10bit', 'dual', 'audio', 'eng', 'english', |
| 19 | + 'subbed', 'sub', 'dubbed', 'dub'] |
| 20 | + |
| 21 | + folder_name = folder_name.lower().replace('_', ' ').replace('.', ' ') |
| 22 | + |
| 23 | + for word in words_to_remove: |
| 24 | + folder_name = folder_name.replace(word, '') |
| 25 | + |
| 26 | + folder_name = re.sub(r"(?<=\[)(.*?)(?=])", '', folder_name) |
| 27 | + folder_name = re.sub(r"(?<=\()(.*?)(?=\))", '', folder_name) |
| 28 | + folder_name = folder_name.replace('()', '').replace('[]', '') |
| 29 | + |
| 30 | + for word in last_words: |
| 31 | + regex_str = "(?<=" + word + ")(?s)(.*$)" |
| 32 | + folder_name = re.sub(regex_str, '', folder_name).replace(word, '') |
| 33 | + |
| 34 | + return folder_name.strip() |
| 35 | + |
| 36 | + |
| 37 | +def get_artwork(anime_name: str, max_results: int = 5, mode: str = "mal-api") -> tuple: |
| 38 | + print('\n' + anime_name.title()) |
| 39 | + |
| 40 | + counter, choice = 1, 0 |
| 41 | + if mode == "mal-api": |
| 42 | + results = AnimeSearch(anime_name).results |
| 43 | + for result in results: |
| 44 | + if auto_mode: |
| 45 | + print(' - ' + result.title) |
| 46 | + choice = 1 |
| 47 | + break |
| 48 | + else: |
| 49 | + print(str(counter) + ' - ' + result.title) |
| 50 | + |
| 51 | + if counter == max_results: |
| 52 | + break |
| 53 | + counter += 1 |
| 54 | + elif mode == "jikanpy": |
| 55 | + results = jikan.search('anime', anime_name, parameters={'type': 'tv'}) |
| 56 | + for result in results['results']: |
| 57 | + if auto_mode: |
| 58 | + print(' - ' + result['title']) |
| 59 | + choice = 1 |
| 60 | + break |
| 61 | + else: |
| 62 | + print(str(counter) + ' - ' + result['title']) |
| 63 | + |
| 64 | + if counter == max_results: |
| 65 | + break |
| 66 | + counter += 1 |
| 67 | + else: |
| 68 | + raise Exception("Invalid mode specified") |
| 69 | + print("X - Skip this folder") |
| 70 | + |
| 71 | + if not auto_mode: |
| 72 | + choice = input('> ') |
| 73 | + if choice == '': |
| 74 | + choice = 1 |
| 75 | + elif choice.upper() == "X": |
| 76 | + return None, None |
| 77 | + choice = int(choice) - 1 |
| 78 | + |
| 79 | + image_url = results['results'][choice]['image_url'] if mode == "jikanpy" else results[choice].image_url |
| 80 | + image_type = results['results'][choice]['type'] if mode == "jikanpy" else results[choice].type |
| 81 | + |
| 82 | + return image_url, image_type |
| 83 | + |
| 84 | + |
| 85 | +def create_icon(img_link: str): |
| 86 | + art = get(img_link) |
| 87 | + open(jpg_file, 'wb').write(art.content) |
| 88 | + |
| 89 | + img = Image.open(jpg_file) |
75 | 90 | img = ImageOps.expand(img, (69, 0, 69, 0), fill=0)
|
76 |
| - img = ImageOps.fit(img, (300,300)).convert("RGBA") |
77 |
| - |
| 91 | + img = ImageOps.fit(img, (300, 300)).convert("RGBA") |
| 92 | + |
78 | 93 | datas = img.getdata()
|
79 |
| - newData = [] |
| 94 | + new_data = [] |
80 | 95 | for item in datas:
|
81 | 96 | if item[0] == 0 and item[1] == 0 and item[2] == 0:
|
82 |
| - newData.append((0, 0, 0, 0)) |
| 97 | + new_data.append((0, 0, 0, 0)) |
83 | 98 | else:
|
84 |
| - newData.append(item) |
| 99 | + new_data.append(item) |
85 | 100 |
|
86 |
| - img.putdata(newData) |
87 |
| - os.remove(jpgfile) |
88 |
| - img.save(icofile) |
| 101 | + img.putdata(new_data) |
| 102 | + os.remove(jpg_file) |
| 103 | + img.save(ico_file) |
89 | 104 | img.close()
|
90 |
| - return(icofile) |
| 105 | + return ico_file |
91 | 106 |
|
92 |
| -for folder in folderlist: |
93 |
| - name = getname(folder) |
94 | 107 |
|
95 |
| - # Extracting the name of the folder without the path and then performing search for the same. This will be the name of the anime |
96 |
| - # episode, thus instead of performing a search for the directory path, now performing a search for the directory name. |
97 |
| - name = name.rpartition('\\')[2].strip() |
98 |
| - |
99 |
| - iconname = name.replace(' ', '_') |
100 |
| - jpgfile = folder + '\\' + iconname + '.jpg' |
101 |
| - icofile = folder + '\\' + iconname + '.ico' |
102 |
| - |
103 |
| - if os.path.isfile(icofile): |
104 |
| - print('An icon is already present. Delete the older icon and `desktop.ini` file before applying a new icon') |
105 |
| - continue |
106 |
| - |
107 |
| - link, Type = getartwork(name) |
108 |
| - |
| 108 | +if __name__ == "__main__": |
| 109 | + print("""\ |
| 110 | +Run this in your anime folder |
| 111 | +For help, info and memes, check out |
| 112 | +https://github.com/notdedsec/anicon |
| 113 | +""") |
| 114 | + auto_mode = True if input('Use AutoMode? Y/N : ').upper() == 'Y' else False |
| 115 | + max_res = input("Max Results (default 5): ") |
109 | 116 | try:
|
110 |
| - icon = createicon(folder, link) |
111 |
| - except: |
112 |
| - print('Ran into an error. Blame the dev :(') |
113 |
| - continue |
114 |
| - |
115 |
| - f = open(folder + "\\desktop.ini","w+") |
116 |
| - |
117 |
| - f.write("[.ShellClassInfo]\nConfirmFileOp=0\n") |
118 |
| - f.write("IconResource={},0".format(icofile.replace(folder, "").strip("\\"))) |
119 |
| - f.write("\nIconFile={}\nIconIndex=0".format(icofile.replace(folder, "").strip("\\"))) |
120 |
| - |
121 |
| - if Type is not None and len(Type) > 0: |
122 |
| - # If the result has a type, then using this as the infotip for the desktop icon. |
123 |
| - f.write("\nInfoTip={}".format(Type)) |
124 |
| - |
125 |
| - # Closing the output stream. All the text will be written into `desktop.ini` file only when the output is being closed. |
126 |
| - f.close() |
127 |
| - |
128 |
| - # Not marking the `desktop.ini` file as a system file. This will make sure that the file can be seen if display hidden items is enabled. |
129 |
| - os.system('attrib +r \"{}\\{}\"'.format(os.getcwd(), folder)) |
130 |
| - os.system('attrib +h \"{}\\desktop.ini\"'.format(folder)) |
131 |
| - os.system('attrib +h \"{}\"'.format(icon)) |
| 117 | + max_res = int(max_res) |
| 118 | + except ValueError: |
| 119 | + max_res = 5 |
| 120 | + |
| 121 | + lib_mode = input("""\ |
| 122 | +
|
| 123 | +Image Source Library: |
| 124 | +1. mal-api (default) |
| 125 | +2. Jikanpy |
| 126 | +> """) |
| 127 | + if lib_mode == "2": |
| 128 | + lib_mode = "jikanpy" |
| 129 | + else: |
| 130 | + lib_mode = "mal-api" |
| 131 | + |
| 132 | + folder_list = next(os.walk('.'))[1] |
| 133 | + if folder_list is None or len(folder_list) == 0: |
| 134 | + # In case the file is placed inside an innermost directory which contains only files and no other folders, |
| 135 | + # this list will be empty. Thus adding the current directory path as an element of the list. |
| 136 | + folder_list = [str(os.getcwd())] |
| 137 | + |
| 138 | + for folder in folder_list: |
| 139 | + name = get_name(folder) |
| 140 | + |
| 141 | + # Extracting the name of the folder without the path and then performing search for the same. |
| 142 | + # This will be the name of the anime episode, thus instead of performing a search for the directory path, |
| 143 | + # now performing a search for the directory name. |
| 144 | + name = name.rpartition('\\')[2].strip() |
| 145 | + |
| 146 | + icon_name = re.sub("[^A-Za-z0-9_,. ()-]", "_", name) |
| 147 | + jpg_file = folder + '\\' + icon_name + '.jpg' |
| 148 | + ico_file = folder + '\\' + icon_name + '.ico' |
| 149 | + |
| 150 | + if os.path.isfile(folder + "\\" + "desktop.ini"): |
| 151 | + print('An icon is already present. Delete the older icon and `desktop.ini` file before applying a new icon') |
| 152 | + continue |
| 153 | + |
| 154 | + link, artwork_type = get_artwork(name, max_results=max_res, mode=lib_mode) |
| 155 | + if not link or not artwork_type: |
| 156 | + print("Skipping this folder...") |
| 157 | + continue |
| 158 | + |
| 159 | + try: |
| 160 | + icon = create_icon(link) |
| 161 | + except Exception as e: |
| 162 | + print('Ran into an error while creating the icon object. Blame the dev :(') |
| 163 | + for line in traceback.format_exception(None, e, e.__traceback__): |
| 164 | + print(line, end="") |
| 165 | + continue |
| 166 | + |
| 167 | + try: |
| 168 | + f = open(folder + "\\desktop.ini", "w+") |
| 169 | + |
| 170 | + f.write("[.ShellClassInfo]\nConfirmFileOp=0\n") |
| 171 | + f.write("IconResource={},0".format(ico_file.replace(folder, "").strip("\\"))) |
| 172 | + f.write("\nIconFile={}\nIconIndex=0".format(ico_file.replace(folder, "").strip("\\"))) |
| 173 | + |
| 174 | + if artwork_type is not None and len(artwork_type) > 0: |
| 175 | + # If the result has a type, then using this as the info-tip for the desktop icon. |
| 176 | + f.write("\nInfoTip={}".format(artwork_type)) |
| 177 | + |
| 178 | + # Closing the output stream. |
| 179 | + # All the text will be written into `desktop.ini` file only when the output is being closed. |
| 180 | + f.close() |
| 181 | + |
| 182 | + # Not marking the `desktop.ini` file as a system file. |
| 183 | + # This will make sure that the file can be seen if display hidden items is enabled. |
| 184 | + os.system('attrib +r \"{}\\{}\"'.format(os.getcwd(), folder)) |
| 185 | + os.system('attrib +h \"{}\\desktop.ini\"'.format(folder)) |
| 186 | + os.system('attrib +h \"{}\"'.format(icon)) |
| 187 | + except Exception as e: |
| 188 | + print('Ran into an error while creating files. Blame the dev :(') |
| 189 | + for line in traceback.format_exception(None, e, e.__traceback__): |
| 190 | + print(line, end="") |
| 191 | + continue |
0 commit comments