-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunction.py
More file actions
310 lines (257 loc) · 8.98 KB
/
Copy pathfunction.py
File metadata and controls
310 lines (257 loc) · 8.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
import os
import re
import sys
import json
import time
import socket
import psutil
from PIL import Image
import requests
import urllib.parse
import latest_user_agents
Image.MAX_IMAGE_PIXELS = None
def cls():
"""Clear the terminal screen across all operating systems."""
try:
if os.name == "nt":
os.system("cls")
else:
os.system("clear")
except Exception:
sys.stdout.write("\033c") # ANSI escape code for clearing the screen
sys.stdout.flush()
def mkDir(path):
if not os.path.exists(path):
print(f"{gettime()}: ❌ Folder {path} not created.")
print(f"{gettime()}: 📁 Try to create folder {path}...")
os.makedirs(path)
print(f"{gettime()}: 📁 Folder {path} created.")
else:
print(f"{gettime()}: ✅ Folder {path} already exists.")
pass
def delDir(path):
if os.path.exists(path):
os.rmdir(path)
print(f"Removed folder {path}.")
else:
print(f"Folder {path} does not exist.")
pass
def writeFile(path, content):
with open(path, "a+", encoding='utf-8') as file:
file.write(content)
def readFile(path):
with open(path, "r", encoding='utf8') as file:
return [line.rstrip('\n') for line in file]
def countFiles(path):
files = os.listdir(path)
count = len(files)
return count
def savejson(path, mgTitle=None, mgtype=None, mggenres=None, mgstatus=None, chaptercount=None, chaptertitle=None, chapterurl=None):
title_prefix = "Title"
type_prefix = "Type"
genre_prefix = "Genres"
status_prefix = "Status"
count_prefix = "Count"
savechapters = "ChapterURLs"
if os.path.exists(path):
with open(path, "r", encoding="utf-8") as file:
data = json.load(file)
else:
data = {
title_prefix: mgTitle,
type_prefix: mgtype,
genre_prefix: mggenres,
status_prefix: mgstatus,
count_prefix: chaptercount,
savechapters: {}
}
if mgTitle is not None:
data[title_prefix] = mgTitle
if mgtype is not None:
data[type_prefix] = mgtype
if mggenres is not None:
data[genre_prefix] = mggenres
if mgstatus is not None:
data[status_prefix] = mgstatus
if chaptercount is not None:
data[count_prefix] = chaptercount
if chaptertitle and chapterurl:
if chapterurl not in data[savechapters]:
data[savechapters][chapterurl] = chaptertitle
else:
print(f"Chapter URL '{chapterurl}' already exists. Skipping addition.")
with open(path, "w", encoding="utf-8") as file:
json.dump(data, file, ensure_ascii=False, indent=4)
def readjson(path):
with open(path, "r", encoding="utf-8") as file:
data = json.load(file)
mgtitle = data["Title"]
mgtype = data["Type"]
mggenres = data["Genres"]
mgStatus = data["Status"]
chaptercount = data["Count"]
chapterurls = data["ChapterURLs"]
return mgtitle, mgtype, mggenres, mgStatus, chaptercount, chapterurls
def get_user_agent():
all_user_agents = latest_user_agents.get_latest_user_agents()
chrome_user_agent = next(user_agent for user_agent in all_user_agents if 'Chrome/' and 'NT' and 'Win64' in user_agent)
return chrome_user_agent
def getHeaders():
user_agent = get_user_agent()
headers = {
'User-Agent': user_agent,
'Accept-Language': 'th-TH,th;q=0.9,en-US;q=0.8,en;q=0.7',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1'
}
return headers
def isOnline(host, port=443, timeout=10):
try:
socket.setdefaulttimeout(timeout)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
return True
except socket.error as ex:
print(f"Host {host} is offline: {ex}")
return False
def checkNet():
try:
response = requests.get("https://funtoons.online", timeout=15)
return response.status_code == 200
except (requests.ConnectionError,requests.Timeout):
return False
def waitNet():
print(f'{gettime()}: ⏳ Watiting for internet connection...')
while not checkNet():
print(f'{gettime()}: ⚠️ No internet connection. Retrying in 15 seconds...')
time.sleep(15)
print(f"{gettime()}: 🌐 Internet connection detected. Continuing...")
def getchapter(title):
numbers = re.findall(r'\d+', title)
if len(numbers) == 6:
return '-'.join(numbers)
elif len(numbers) == 5:
return '-'.join(numbers)
elif len(numbers) == 4:
return '-'.join(numbers)
elif len(numbers) == 3:
return '-'.join(numbers)
elif len(numbers) == 2:
return '-'.join(numbers)
elif len(numbers) == 1:
return numbers[0]
else:
return ''
def findchapternum(title):
if 'ตอน' in title:
result = re.split(r'(?=ตอน)', title)[-1]
elif 'Chapter' in title:
result = re.split(r'(?=Chapter)', title)[-1]
else:
result = re.split(r'\d+', title)[-1]
numbers = re.findall(r'\d+', result)
if len(numbers) == 6:
return '-'.join(numbers)
elif len(numbers) == 5:
return '-'.join(numbers)
elif len(numbers) == 4:
return '-'.join(numbers)
elif len(numbers) == 3:
return '-'.join(numbers)
elif len(numbers) == 2:
return '-'.join(numbers)
elif len(numbers) == 1:
return numbers[0]
else:
return ''
def mangaid(manga_url):
pattern = re.compile(r"([^/]+)/?$")
urlpath = manga_url.path
match = pattern.search(urlpath)
if match:
return match.group(1)
else:
return ''
def gettime():
return time.strftime("%d-%m-%Y %H:%M:%S", time.localtime())
def sortKey(name):
"""Custom sorting key to handle both numbers and text in chapter names."""
return [int(text) if text.isdigit() else text.lower() for text in re.split(r'(\d+)', name)]
def sanitizedName(name):
"""Sanitizes a string by removing invalid characters for file names."""
return re.sub(r'[<>:"/\\|?*\x00-\x1F]', '', name).strip()
def getFilesize(filepath):
"""Returns file size in bytes if the file exists, otherwise returns None."""
return os.path.getsize(filepath) if os.path.isfile(filepath) else None
def formatSize(size):
"""Format file size to human-readable format."""
suffixes = ["B", "KB", "MB", "GB", "TB"]
i = 0
while size >= 1024 and i < len(suffixes) - 1:
size /= 1024
i += 1
return f"{size:.2f} {suffixes[i]}"
def checkImg(imgPath):
"""Verify if an image is fully loaded and valid."""
try:
with Image.open(imgPath) as img:
img.load()
return True
except Exception:
return False
def compareSize(contentsize, localsize):
if contentsize == localsize:
return True
else:
return False
def mangaID(url):
pattern = re.compile(r"([^/]+)/?$")
decode_url = urllib.parse.urlparse(url)
urlpath = decode_url.path
match = pattern.search(urlpath)
if match:
return match.group(1)
else:
return ''
def numChapter(mgID, chapterID):
# Use re.sub to remove the title from the chapter_title
text = re.sub(f"^{mgID}", "", chapterID).strip()
# Use regular expression to find all groups of digits in the input string
numbers = re.findall(r'\d+', text)
# If there are two numbers, format them as "u-v-w-x-y-z"
if len(numbers) == 6:
return '-'.join(numbers)
elif len(numbers) == 5:
return '-'.join(numbers)
elif len(numbers) == 4:
return '-'.join(numbers)
elif len(numbers) == 3:
return '-'.join(numbers)
elif len(numbers) == 2:
return '-'.join(numbers)
elif len(numbers) == 1:
return numbers[0]
else:
return ''
def checkSpace(required_mb=4096, path=None):
"""
Checks if there is at least `required_mb` of free space on the current drive or specified path.
:param required_mb: Minimum free space required in MB (default: 4096MB)
:param path: Path to check (default: current working directory)
:return: True if enough space is available, False otherwise
"""
if path is None:
path = os.getcwd() # Use current working directory if no path is specified
drive = os.path.splitdrive(path)[0] # Extract the drive letter
free_space_mb = psutil.disk_usage(drive).free / (1024**2) # Convert bytes to MB
return free_space_mb >= required_mb
def safeDecode(url: str) -> str:
"""Detect and safely decode a URL without over-decoding."""
if "%" not in url:
return url # Already decoded, return as is
once_decoded = urllib.parse.unquote(url)
if "%" not in once_decoded:
return once_decoded # Properly decoded after one unquote
twice_decoded = urllib.parse.unquote(once_decoded)
if "%" not in twice_decoded:
return twice_decoded # Was double-encoded, return fully decoded
return once_decoded