|
1
|
|
|
import shutil # Library For Work With File In High Level Like Copy |
|
2
|
|
|
import webbrowser |
|
3
|
|
|
from params import * |
|
4
|
|
|
import socket |
|
5
|
|
|
import requests |
|
6
|
|
|
import re |
|
7
|
|
|
import time |
|
8
|
|
|
import sys |
|
9
|
|
|
import urllib.request |
|
10
|
|
|
import platform |
|
11
|
|
|
import random |
|
12
|
|
|
import datetime |
|
13
|
|
|
from functools import reduce |
|
14
|
|
|
import doctest |
|
15
|
|
|
meta_input = "" |
|
16
|
|
|
def sample_browser(sample_number=1,randomize=True): |
|
17
|
|
|
''' |
|
18
|
|
|
Choose a sample site and open it with browser |
|
19
|
|
|
:param sample_number: choose which sample site default value is 1 |
|
20
|
|
|
:type sample_number:int |
|
21
|
|
|
:return: None |
|
22
|
|
|
''' |
|
23
|
|
|
try: |
|
24
|
|
|
response=input("Please enter [S] key if you want see a sample site of qpage (or any other key to ignore this step)") |
|
25
|
|
|
if response.upper()=="S": |
|
26
|
|
|
if randomize==True: |
|
27
|
|
|
webbrowser.open(SAMPLE_SITE_LIST[random.randint(0,len(SAMPLE_SITE_LIST)-1)]) |
|
28
|
|
|
elif sample_number<len(SAMPLE_SITE_LIST): |
|
29
|
|
|
webbrowser.open(SAMPLE_SITE_LIST[sample_number]) |
|
30
|
|
|
except Exception as e: |
|
31
|
|
|
print("Error In Sample Browsing") |
|
32
|
|
|
error_log(str(e)) |
|
33
|
|
|
def list_randomize(input_list): |
|
34
|
|
|
''' |
|
35
|
|
|
:param input_list: raw_input list |
|
36
|
|
|
:type input_list:list |
|
37
|
|
|
:return: randomized list |
|
38
|
|
|
>>> random.seed(1) |
|
39
|
|
|
>>> list_randomize([1,2,3,5,6]) |
|
40
|
|
|
[2, 1, 5, 3, 6] |
|
41
|
|
|
''' |
|
42
|
|
|
response=[] |
|
43
|
|
|
input_list_copy=input_list |
|
44
|
|
|
iteration_number=len(input_list_copy) |
|
45
|
|
|
for i in range(iteration_number): |
|
46
|
|
|
response.append(input_list_copy.pop(random.randint(0,len(input_list_copy)-1))) |
|
47
|
|
|
return response |
|
48
|
|
|
def email_at(text,USE_RE=False,replace_char=" at "): |
|
49
|
|
|
''' |
|
50
|
|
|
:param text: input text of pages |
|
51
|
|
|
:param USE_RE: flag for using regular expression (default False) |
|
52
|
|
|
:param replace_char: replace char for @ |
|
53
|
|
|
:type text:str |
|
54
|
|
|
:type USE_RE:bool |
|
55
|
|
|
:type replace_char:str |
|
56
|
|
|
:return: replaced string |
|
57
|
|
|
>>> email_at("[email protected]") |
|
58
|
|
|
'example at yahoo.com' |
|
59
|
|
|
>>> |
|
60
|
|
|
''' |
|
61
|
|
|
if USE_RE==False: |
|
62
|
|
|
return text.replace("@",replace_char) |
|
63
|
|
|
def show_items(enum_list): |
|
64
|
|
|
""" |
|
65
|
|
|
show item of enum_list |
|
66
|
|
|
:param enum_list the list that should be shown |
|
67
|
|
|
:type enum_list : list |
|
68
|
|
|
""" |
|
69
|
|
|
for i, item in enumerate(enum_list): |
|
70
|
|
|
print(str(i + 1) + "-" + item) |
|
71
|
|
|
def print_logo(external=False): |
|
72
|
|
|
''' |
|
73
|
|
|
print qpage logo by sequential characters |
|
74
|
|
|
:param external: flag for choosing internal or external logo |
|
75
|
|
|
:type external:bool |
|
76
|
|
|
:return: None |
|
77
|
|
|
>>> print_logo() |
|
78
|
|
|
____ ___ |
|
79
|
|
|
/ __ \ / _ \___ ____ ____ |
|
80
|
|
|
/ /_/ / / ___/ _ `/ _ `/ -_) |
|
81
|
|
|
\___\_\/_/ \_,_/\_, /\__/ |
|
82
|
|
|
/___/ |
|
83
|
|
|
''' |
|
84
|
|
|
if external==True: |
|
85
|
|
|
if "logo.txt" in os.listdir(RESOURCE_DIR): |
|
86
|
|
|
logo_path = os.path.join(RESOURCE_DIR, 'logo.txt') |
|
87
|
|
|
with open(logo_path, "r") as logo_file: |
|
88
|
|
|
for line in logo_file: |
|
89
|
|
|
print(line.rstrip()) |
|
90
|
|
|
else: |
|
91
|
|
|
pass |
|
92
|
|
|
else: |
|
93
|
|
|
print(LOGO) |
|
94
|
|
|
def convert_bytes(num): |
|
95
|
|
|
""" |
|
96
|
|
|
convert num to idiomatic byte unit |
|
97
|
|
|
:param num: the input number. |
|
98
|
|
|
:type num:int |
|
99
|
|
|
:return: str |
|
100
|
|
|
>>> convert_bytes(200) |
|
101
|
|
|
'200.0 bytes' |
|
102
|
|
|
>>> convert_bytes(6000) |
|
103
|
|
|
'5.9 KB' |
|
104
|
|
|
>>> convert_bytes(80000) |
|
105
|
|
|
'78.1 KB' |
|
106
|
|
|
""" |
|
107
|
|
|
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']: |
|
108
|
|
|
if num < 1024.0: |
|
109
|
|
|
return "%3.1f %s" % (num, x) |
|
110
|
|
|
num /= 1024.0 |
|
111
|
|
|
def file_size(): |
|
112
|
|
|
""" |
|
113
|
|
|
Print the size of output file |
|
114
|
|
|
:return: None |
|
115
|
|
|
>>> file_size() # if there is no output directory |
|
116
|
|
|
Access Error |
|
117
|
|
|
>>> file_size() # if there is a valid output directory |
|
118
|
|
|
Used SPACE --> 78.1 KB |
|
119
|
|
|
""" |
|
120
|
|
|
try: |
|
121
|
|
|
list_of_files = os.listdir(OUT_DIR) |
|
122
|
|
|
response = 0 |
|
123
|
|
|
for file in list_of_files: |
|
124
|
|
|
file_info = os.stat(os.path.join(OUT_DIR, file)) |
|
125
|
|
|
response += file_info.st_size |
|
126
|
|
|
print_line(70, "*") |
|
127
|
|
|
print("Used SPACE --> " + convert_bytes(response)) |
|
128
|
|
|
print_line(70, "*") |
|
129
|
|
|
except: |
|
130
|
|
|
print("Access Error!") |
|
131
|
|
|
def download_badge(address): |
|
132
|
|
|
|
|
133
|
|
|
""" |
|
134
|
|
|
Download badge for website |
|
135
|
|
|
:param address: the address that should get badge |
|
136
|
|
|
:type address : str |
|
137
|
|
|
:return: None |
|
138
|
|
|
""" |
|
139
|
|
|
r = requests.get(address, stream=True) |
|
140
|
|
|
with open(os.path.join(OUT_DIR, "badge.svg"), 'wb') as f: |
|
141
|
|
|
shutil.copyfileobj(r.raw, f) |
|
142
|
|
|
def random_badge_color(): |
|
143
|
|
|
""" |
|
144
|
|
|
return a random color for badge |
|
145
|
|
|
:return: badge color as string |
|
146
|
|
|
>>> random.seed(1) |
|
147
|
|
|
>>> random_badge_color() |
|
148
|
|
|
'yellowgreen' |
|
149
|
|
|
""" |
|
150
|
|
|
random_index = random.randint(0, len(BADGE_COLOR_LIST) - 1) |
|
151
|
|
|
return BADGE_COLOR_LIST[random_index] |
|
152
|
|
|
def system_details(): |
|
153
|
|
|
""" |
|
154
|
|
|
Show detail of system that code is runnig on |
|
155
|
|
|
:return: system details as string (node , processor , platform) |
|
156
|
|
|
>>> system_details() |
|
157
|
|
|
'DESKTOP-B16C9BR , Intel64 Family 6 Model 94 Stepping 3, GenuineIntel , Windows-10-10.0.10240-SP0' |
|
158
|
|
|
""" |
|
159
|
|
|
return platform.node() + " , " + platform.processor() + " , " + platform.platform() |
|
160
|
|
|
def generation_time(time_1=None): |
|
161
|
|
|
""" |
|
162
|
|
|
Calculate the generation time |
|
163
|
|
|
:param time_1: time that passed but not counted in generation time |
|
164
|
|
|
:type time_1:float |
|
165
|
|
|
:return :the amount of time that passed as float |
|
166
|
|
|
""" |
|
167
|
|
|
if time_1 is None: |
|
168
|
|
|
return time.perf_counter() |
|
169
|
|
|
else: |
|
170
|
|
|
return time.perf_counter() - time_1 |
|
171
|
|
|
def find_global_ip(): |
|
172
|
|
|
""" |
|
173
|
|
|
Find the global IP for using in API |
|
174
|
|
|
:return: return the IP as string |
|
175
|
|
|
""" |
|
176
|
|
|
try: |
|
177
|
|
|
response = requests.get(IP_FINDER_API) |
|
178
|
|
|
return response.text[:-1] |
|
179
|
|
|
except Exception as e: |
|
180
|
|
|
error_log(e) |
|
181
|
|
|
return "0.0.0.0" |
|
182
|
|
|
def create_badge(subject="qpage", status=VERSION, color="blue", random=False): |
|
183
|
|
|
''' |
|
184
|
|
|
this function use shields.io template for creating badges |
|
185
|
|
|
:param subject: badge subject |
|
186
|
|
|
:param status: badge status ( in our case version) |
|
187
|
|
|
:param color: badge color |
|
188
|
|
|
:param random: randomization flag |
|
189
|
|
|
:type subject:str |
|
190
|
|
|
:type status:str |
|
191
|
|
|
:type color:str |
|
192
|
|
|
:type random:bool |
|
193
|
|
|
:return: shields.io badge addresses as string |
|
194
|
|
|
>>> create_badge() |
|
195
|
|
|
'https://img.shields.io/badge/qpage-1.9-blue.svg' |
|
196
|
|
|
>>> random.seed(1) |
|
197
|
|
|
>>> create_badge(random=True) |
|
198
|
|
|
'https://img.shields.io/badge/qpage-1.9-yellowgreen.svg' |
|
199
|
|
|
''' |
|
200
|
|
|
if random: |
|
201
|
|
|
color = random_badge_color() |
|
202
|
|
|
else: |
|
203
|
|
|
if color not in BADGE_COLOR_LIST: |
|
204
|
|
|
color = "orange" |
|
205
|
|
|
badge_adr = ADV_BADGE_STATIC + subject + "-" + status + "-" + color + '.svg' |
|
206
|
|
|
return badge_adr |
|
207
|
|
|
def is_sample_downloaded(): |
|
208
|
|
|
""" |
|
209
|
|
|
Check the sample site material is downloaded of not |
|
210
|
|
|
:return : index of materials that downloaded as list |
|
211
|
|
|
""" |
|
212
|
|
|
download_list = [] |
|
213
|
|
|
if "profile.png" not in os.listdir(IMAGE_DIR): |
|
214
|
|
|
download_list.append(0) |
|
215
|
|
|
if "font.TTF" not in os.listdir(FONT_DIR): |
|
216
|
|
|
download_list.append(1) |
|
217
|
|
|
if "resume.pdf" not in os.listdir(DOC_DIR) and "resume.txt" not in os.listdir(DOC_DIR): |
|
218
|
|
|
download_list.extend([2, 3]) |
|
219
|
|
|
if "icon.ico" not in os.listdir(IMAGE_DIR): |
|
220
|
|
|
download_list.append(4) |
|
221
|
|
|
return download_list |
|
222
|
|
|
def download_lorem(): |
|
223
|
|
|
""" |
|
224
|
|
|
Download the lorem file |
|
225
|
|
|
:return: None |
|
226
|
|
|
""" |
|
227
|
|
|
if internet(): |
|
228
|
|
|
lorem_path = os.path.join(RESOURCE_DIR, 'Latin-Lipsum.txt') |
|
229
|
|
|
urllib.request.urlretrieve("http://www.qpage.ir/sample/Latin-Lipsum.txt", lorem_path) |
|
230
|
|
|
else: |
|
231
|
|
|
print("Error In Download Lorem") |
|
232
|
|
|
def read_lorem(char=100,external=False,randomize=True): |
|
233
|
|
|
""" |
|
234
|
|
|
find and read lorem |
|
235
|
|
|
:param char: the amount of char that needed to print |
|
236
|
|
|
:param external: flag for using external of internal resource for lorem_ipsum |
|
237
|
|
|
:param randomize: flag for using randomization |
|
238
|
|
|
:type char:int |
|
239
|
|
|
:type external:bool |
|
240
|
|
|
:type randomize:bool |
|
241
|
|
|
:return : the lorem string |
|
242
|
|
|
>>> read_lorem(5) |
|
243
|
|
|
'Lorem ipsum dolor sit amet,' |
|
244
|
|
|
""" |
|
245
|
|
|
try: |
|
246
|
|
|
if external==True: |
|
247
|
|
|
if "Latin-Lipsum.txt" not in os.listdir(RESOURCE_DIR): |
|
248
|
|
|
download_lorem() |
|
249
|
|
|
lorem_path = os.path.join(RESOURCE_DIR, 'Latin-Lipsum.txt') |
|
250
|
|
|
lorem_file = open(lorem_path, "r") |
|
251
|
|
|
lorem_text = lorem_file.read() |
|
252
|
|
|
lorem_file.close() |
|
253
|
|
|
if randomize==True: |
|
254
|
|
|
return " ".join(list_randomize(lorem_text.split(" ")[:char])) |
|
255
|
|
|
else: |
|
256
|
|
|
return " ".join(lorem_text.split(" ")[:char]) |
|
257
|
|
|
else: |
|
258
|
|
|
if randomize==True: |
|
259
|
|
|
return " ".join(list_randomize(LOREM_IPSUM.split(" ")[:char])) |
|
260
|
|
|
else: |
|
261
|
|
|
return " ".join(LOREM_IPSUM.split(" ")[:char]) |
|
262
|
|
|
except Exception as e: |
|
263
|
|
|
error_log(str(e)) |
|
264
|
|
|
return None |
|
265
|
|
|
def sample_site_download(item_list): |
|
266
|
|
|
""" |
|
267
|
|
|
Download sample material for make a fake site |
|
268
|
|
|
:param item_list: Download items form item_list |
|
269
|
|
|
:type item_list:list |
|
270
|
|
|
""" |
|
271
|
|
|
try: |
|
272
|
|
|
if internet(): |
|
273
|
|
|
for i in item_list: |
|
274
|
|
|
print("Downloading " + SAMPLE_DICT_MESSAGE[i] + " . . . [" + str(i + 1) + "/5]") |
|
275
|
|
|
print_line(70) |
|
276
|
|
|
urllib.request.urlretrieve(list(SAMPLE_DICT_ADDR.values())[i], |
|
277
|
|
|
os.path.join(IMAGE_DIR, list(SAMPLE_DICT_ADDR.keys())[i])) |
|
278
|
|
|
print("Done! All Material Downloaded") |
|
279
|
|
|
print_line(70) |
|
280
|
|
|
else: |
|
281
|
|
|
print("Error In Internet Connection!") |
|
282
|
|
|
print_line(70) |
|
283
|
|
|
except Exception as e: |
|
284
|
|
|
error_log(e) |
|
285
|
|
|
print("Error in downloading sample files check your internet conection") |
|
286
|
|
|
print_line(70) |
|
287
|
|
|
def logger(status=False, perf_time=None): |
|
288
|
|
|
""" |
|
289
|
|
|
Create the build log of the app |
|
290
|
|
|
:param status: show status of app. |
|
291
|
|
|
:param perf_time : show the time passed for generate files |
|
292
|
|
|
:type status:bool |
|
293
|
|
|
:type perf_time:float |
|
294
|
|
|
""" |
|
295
|
|
|
if "log" not in os.listdir(): |
|
296
|
|
|
os.mkdir("log") |
|
297
|
|
|
file = open(reduce(os.path.join, [os.getcwd(), "log", "build_log.txt"]), "a") |
|
298
|
|
|
if not status: |
|
299
|
|
|
file.write("Failed " + str(datetime.datetime.now()) + "\n") |
|
300
|
|
|
else: |
|
301
|
|
|
file.write("Success " + str(datetime.datetime.now()) + "\n") |
|
302
|
|
|
file.write("Generation Time: " + str(perf_time) + "\n") |
|
303
|
|
|
file.close() |
|
304
|
|
|
def error_log(msg): |
|
305
|
|
|
""" |
|
306
|
|
|
Create the errorlog of the app |
|
307
|
|
|
:param msg: error message |
|
308
|
|
|
:type msg:str |
|
309
|
|
|
""" |
|
310
|
|
|
if "log" not in os.listdir(): |
|
311
|
|
|
os.mkdir("log") |
|
312
|
|
|
file = open(reduce(os.path.join, [os.getcwd(), "log", "error_log.txt"]), "a") |
|
313
|
|
|
file.write(str(datetime.datetime.now()) + " --> " + str(msg) + "\n") |
|
314
|
|
|
file.close() |
|
315
|
|
|
def print_line(number, char="-"): |
|
316
|
|
|
""" |
|
317
|
|
|
Print a Line |
|
318
|
|
|
:param number: the amount char that in lien |
|
319
|
|
|
:param char : the char that used to draw line |
|
320
|
|
|
:type number :int |
|
321
|
|
|
:type char : str |
|
322
|
|
|
>>> print_line(4) |
|
323
|
|
|
---- |
|
324
|
|
|
>>> print_line(5,"%") |
|
325
|
|
|
%%%%% |
|
326
|
|
|
""" |
|
327
|
|
|
line = "" |
|
328
|
|
|
i = 0 |
|
329
|
|
|
while (i < number): |
|
330
|
|
|
line += char |
|
331
|
|
|
i += 1 |
|
332
|
|
|
print(line) |
|
333
|
|
|
def name_standard(name): |
|
334
|
|
|
""" |
|
335
|
|
|
return the Standard VERSION of the input word |
|
336
|
|
|
:param name: the name that should be standard |
|
337
|
|
|
:type name:str |
|
338
|
|
|
:return name: the standard form of word as string |
|
339
|
|
|
>>> name_standard('test') |
|
340
|
|
|
'Test' |
|
341
|
|
|
>>> name_standard('TesT') |
|
342
|
|
|
'Test' |
|
343
|
|
|
""" |
|
344
|
|
|
reponse_name = name[0].upper() + name[1:].lower() |
|
345
|
|
|
return reponse_name |
|
346
|
|
|
def address_print(): |
|
347
|
|
|
""" |
|
348
|
|
|
Print the working directory |
|
349
|
|
|
:return:None |
|
350
|
|
|
""" |
|
351
|
|
|
print_line(70, "*") |
|
352
|
|
|
print("Where --> " + SOURCE_DIR) |
|
353
|
|
|
print_line(70, "*") |
|
354
|
|
|
def create_folder(): |
|
355
|
|
|
""" |
|
356
|
|
|
This Function Create Empty Folder At Begin |
|
357
|
|
|
:return:folder status as boolean |
|
358
|
|
|
""" |
|
359
|
|
|
folder_flag = 0 |
|
360
|
|
|
list_of_folders = os.listdir(SOURCE_DIR) |
|
361
|
|
|
for i in ["doc", "image", "output", "font"]: |
|
362
|
|
|
if i not in list_of_folders: |
|
363
|
|
|
os.mkdir(i) |
|
364
|
|
|
folder_flag += 1 |
|
365
|
|
|
if i == "doc": |
|
366
|
|
|
file = open(os.path.join(DOC_DIR, "index.txt"), "w") |
|
367
|
|
|
if read_lorem() is None: |
|
368
|
|
|
file.write("This is For First Page . . .") |
|
369
|
|
|
else: |
|
370
|
|
|
file.write(read_lorem()) |
|
371
|
|
|
file.close() |
|
372
|
|
|
return bool(folder_flag) |
|
373
|
|
|
def page_name_update(): |
|
374
|
|
|
""" |
|
375
|
|
|
This Function Update Page Names |
|
376
|
|
|
:return: None |
|
377
|
|
|
""" |
|
378
|
|
|
for i in os.listdir(DOC_DIR): |
|
379
|
|
|
if i.find(".txt") != -1 and i[:-4].upper() != "INDEX": |
|
380
|
|
|
ACTUAL_NAME.append(i[:-4]) |
|
381
|
|
|
PAGE_NAME.append(i[:-4]) |
|
382
|
|
|
def menu_maker(): |
|
383
|
|
|
""" |
|
384
|
|
|
Top Menu Maker In each html page |
|
385
|
|
|
:return:site menu as string |
|
386
|
|
|
""" |
|
387
|
|
|
result = "<center>" |
|
388
|
|
|
for i, item in enumerate(PAGE_NAME): |
|
389
|
|
|
if item == "Home": |
|
390
|
|
|
targets_blank = "" |
|
391
|
|
|
else: |
|
392
|
|
|
#targets_blank = 'target="blank"' |
|
393
|
|
|
targets_blank = '' |
|
394
|
|
|
# Hyper Link To Each Page In HTML File |
|
395
|
|
|
result += '\t<a href="' \ |
|
396
|
|
|
+ ACTUAL_NAME[i] + '.html"' + targets_blank + '>' + name_standard(item) + "</a>\n" |
|
397
|
|
|
result += " \n" |
|
398
|
|
|
result += "</center>" |
|
399
|
|
|
result = result + "\t\t" + BREAK_LINE # Add Break line to End Of The Menu |
|
400
|
|
|
return result # Return All Of The Menu |
|
401
|
|
|
def menu_writer(): # |
|
402
|
|
|
""" |
|
403
|
|
|
Write menu_maker output in html and close file after |
|
404
|
|
|
:return:None |
|
405
|
|
|
""" |
|
406
|
|
|
message = menu_maker() |
|
407
|
|
|
PAGE_NAME_length = len(PAGE_NAME) |
|
408
|
|
|
for i in range(PAGE_NAME_length): |
|
409
|
|
|
file = open(os.path.join(OUT_DIR, ACTUAL_NAME[i] + ".html"), "a") |
|
410
|
|
|
file.write(message) |
|
411
|
|
|
file.close() |
|
412
|
|
|
def print_meta(): |
|
413
|
|
|
""" |
|
414
|
|
|
Add meta to html files |
|
415
|
|
|
:return static_meta: The meta that created |
|
416
|
|
|
""" |
|
417
|
|
|
global meta_input |
|
418
|
|
|
meta_input = input("Please Enter Your Name : ") |
|
419
|
|
|
static_meta = '<meta name="description" content="Welcome to HOMEPAGE of ' + meta_input + '"/>\n' |
|
420
|
|
|
static_meta += '<meta property="og:title" content="' + meta_input + '"/>\n' |
|
421
|
|
|
static_meta += '<meta property="og:site_name" content="' + meta_input + '"/>\n' |
|
422
|
|
|
static_meta += '<meta property="og:image" content="favicon.ico" />\n' |
|
423
|
|
|
if len(meta_input) < 4: |
|
424
|
|
|
warnings.append("[Warning] Your input for name is too short!!") |
|
425
|
|
|
return static_meta |
|
426
|
|
|
def html_init(name): |
|
427
|
|
|
""" |
|
428
|
|
|
Create Initial Form Of each Html Page Like Title And HTML And Body Tag. |
|
429
|
|
|
:param name: the name of html file. |
|
430
|
|
|
:type name:str |
|
431
|
|
|
""" |
|
432
|
|
|
|
|
433
|
|
|
html_name = os.path.join(OUT_DIR, name + ".html") |
|
434
|
|
|
file = open(html_name, "w") |
|
435
|
|
|
file.write("<html>\n") |
|
436
|
|
|
file.write("\t<head>\n") |
|
437
|
|
|
if name == "index": |
|
438
|
|
|
file.write("\t\t<title>Welcome To My HOMEPAGE</title>\n") |
|
439
|
|
|
else: |
|
440
|
|
|
file.write("\t\t<title>" + name_standard(name) + "</title>\n") |
|
441
|
|
|
file.write('<link rel="stylesheet" href="styles.css" type="text/css"/>\n') |
|
442
|
|
|
css_link = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css' |
|
443
|
|
|
file.write('<link rel="stylesheet" href= ' + css_link + ' type="text/style"/>\n') |
|
444
|
|
|
|
|
445
|
|
|
if name == 'index': # Add meta only for index page |
|
446
|
|
|
file.write(print_meta()) |
|
447
|
|
|
|
|
448
|
|
|
file.write("\t</head>\n") |
|
449
|
|
|
file.write('\t<body class="body_tag">\n') |
|
450
|
|
|
file.close() |
|
451
|
|
|
def html_end(name): |
|
452
|
|
|
""" |
|
453
|
|
|
Create End Of The Html and close file |
|
454
|
|
|
:param name: The name of html file. |
|
455
|
|
|
:type name:str |
|
456
|
|
|
""" |
|
457
|
|
|
html_name = os.path.join(OUT_DIR, name + ".html") |
|
458
|
|
|
file = open(html_name, "a") |
|
459
|
|
|
file.write("\n\t</body>\n") |
|
460
|
|
|
file.write("</html>") |
|
461
|
|
|
file.close() |
|
462
|
|
|
def close_files(): |
|
463
|
|
|
""" |
|
464
|
|
|
Close all the files. |
|
465
|
|
|
:return:None |
|
466
|
|
|
""" |
|
467
|
|
|
for i in files: |
|
468
|
|
|
if i.closed == False: |
|
469
|
|
|
i.close() |
|
470
|
|
|
def LSM_translate(line, center): |
|
471
|
|
|
# TODO : write a document for this function |
|
472
|
|
|
""" |
|
473
|
|
|
Convert size and style of each line in input plaintext |
|
474
|
|
|
:param line: the input line. |
|
475
|
|
|
:param center: flag of putting text in center |
|
476
|
|
|
:type center:bool |
|
477
|
|
|
:type line:str |
|
478
|
|
|
:return : return a list contain text,header_end and header_begin |
|
479
|
|
|
""" |
|
480
|
|
|
line.strip() |
|
481
|
|
|
text = line |
|
482
|
|
|
header_start = '<h4 class="color_tag">' |
|
483
|
|
|
header_end = "</h4>" |
|
484
|
|
|
if line.find("[L]") != -1: |
|
485
|
|
|
header_start = '<h2 class="color_tag">' |
|
486
|
|
|
header_end = "</h2>" |
|
487
|
|
|
text = line[3:] |
|
488
|
|
|
elif line.find("[S]") != -1: |
|
489
|
|
|
header_start = '<h5 class="color_tag">' |
|
490
|
|
|
header_end = "</h5>" |
|
491
|
|
|
text = line[3:] |
|
492
|
|
|
elif line.find("[M]") != -1: |
|
493
|
|
|
text = line[3:] |
|
494
|
|
|
if center: # Centuries Text If Condition Is True For Manual Centering |
|
495
|
|
|
header_start = "<center>" + header_start |
|
496
|
|
|
header_end += "</center>" |
|
497
|
|
|
if text.find("[center]") != -1: # Find Center Tag In Each Line |
|
498
|
|
|
header_start = "<center>" + header_start |
|
499
|
|
|
header_end += "</center>" |
|
500
|
|
|
text = text[:text.find("[center]")] |
|
501
|
|
|
return [text, header_end, header_start] |
|
502
|
|
|
def print_text(text_file, file, center=False, close=False): # Write Text Part Of Each Page |
|
503
|
|
|
""" |
|
504
|
|
|
Write the text part of each page |
|
505
|
|
|
:param text_file: Text that should be written. |
|
506
|
|
|
:param file : The file that text will be written inside. |
|
507
|
|
|
:param center: flag of putting text in center |
|
508
|
|
|
:param close : flag of closing file after editing |
|
509
|
|
|
:type close : bool |
|
510
|
|
|
:type center: bool |
|
511
|
|
|
:type file:_io.TextIOWrapper |
|
512
|
|
|
:type text_file:str |
|
513
|
|
|
:return:None |
|
514
|
|
|
""" |
|
515
|
|
|
text_code = "" |
|
516
|
|
|
for line in text_file: |
|
517
|
|
|
if len(line) == 1: |
|
518
|
|
|
text_code = SPACE |
|
519
|
|
|
else: |
|
520
|
|
|
text_header = LSM_translate(line, center) |
|
521
|
|
|
text = email_at(text=text_header[0]) |
|
522
|
|
|
header_end = text_header[1] |
|
523
|
|
|
header_start = text_header[2] |
|
524
|
|
|
text_code = header_start + text + header_end + "\n" |
|
525
|
|
|
file.write(text_code) |
|
526
|
|
|
if close: |
|
527
|
|
|
file.close() |
|
528
|
|
|
def print_image(file, image_format="jpg", close=False): |
|
529
|
|
|
""" |
|
530
|
|
|
Write Image Part OF The Page. |
|
531
|
|
|
:param file: The file that images will be added. |
|
532
|
|
|
:param close : flag of closing file after editing |
|
533
|
|
|
:param image_format: the format of image |
|
534
|
|
|
:type close : bool |
|
535
|
|
|
:type image_format:str |
|
536
|
|
|
:type file:_io.TextIOWrapper |
|
537
|
|
|
:return:None |
|
538
|
|
|
""" |
|
539
|
|
|
for i, item in enumerate(SIZE_BOX): |
|
540
|
|
|
print(i, "-", item) |
|
541
|
|
|
image_size = int(input("Please Enter Profile Image Size : ")) # Choose Profile Image Size |
|
542
|
|
|
image_size_string = SIZE_BOX[2] # Getting Html String From SIZE_BOX list default mode (Medium) |
|
543
|
|
|
if 0 <= image_size < len(SIZE_BOX): |
|
544
|
|
|
image_size_string = SIZE_BOX[image_size] |
|
545
|
|
|
image_code = '<center><img src="image.' + image_format + '"' + ', width=' + image_size_string + ' alt="profile image"></img></center>\n' |
|
546
|
|
|
file.write(image_code) |
|
547
|
|
|
if close: |
|
548
|
|
|
file.close() |
|
549
|
|
|
def print_download(file, name, link, center=False, close=False): |
|
550
|
|
|
""" |
|
551
|
|
|
Create Download Link in page |
|
552
|
|
|
:param file: The file that contain html of page. |
|
553
|
|
|
:param name: The name of the link |
|
554
|
|
|
:param link: The place that name is Linked |
|
555
|
|
|
:param center: put the text in center |
|
556
|
|
|
:param close : close file after done editing |
|
557
|
|
|
:type center: bool |
|
558
|
|
|
:type close : bool |
|
559
|
|
|
:type link:str |
|
560
|
|
|
:type name:str |
|
561
|
|
|
:type file:_io.TextIOWrapper |
|
562
|
|
|
:return:None |
|
563
|
|
|
""" |
|
564
|
|
|
link_code = "<a href=" + '"' + link + '"' + TARGET_BLANK + '>' + name + "</a>" |
|
565
|
|
|
if center: |
|
566
|
|
|
link_code = "<center>" + link_code + "</center>" |
|
567
|
|
|
file.write(link_code + "\n") |
|
568
|
|
|
file.write(BREAK_LINE) |
|
569
|
|
|
if close: |
|
570
|
|
|
file.close() |
|
571
|
|
|
def print_adv(file, close=True): |
|
572
|
|
|
""" |
|
573
|
|
|
Print the advertisement (qpage footer) |
|
574
|
|
|
:param file : The file that should adv to it. |
|
575
|
|
|
:param close : Close file after add |
|
576
|
|
|
:type file:_io.TextIOWrapper |
|
577
|
|
|
:type close:bool |
|
578
|
|
|
:return: None |
|
579
|
|
|
""" |
|
580
|
|
|
file.write(BREAK_LINE) |
|
581
|
|
|
file.write( |
|
582
|
|
|
'<center>' + "<p>" + "Generated " + today_time + " By" + "</p>" + '<a href=' + '"' + HOMEPAGE + '"' + TARGET_BLANK + '>' + '<img src="' + create_badge( |
|
583
|
|
|
random=True) + '"alt="Qpage">' + '</a> </center>') |
|
584
|
|
|
if close: |
|
585
|
|
|
file.close() |
|
586
|
|
|
def build_index(file): |
|
587
|
|
|
""" |
|
588
|
|
|
Find and build index page |
|
589
|
|
|
:param file: The index file. |
|
590
|
|
|
:type file:_io.TextIOWrapper |
|
591
|
|
|
:return:None |
|
592
|
|
|
""" |
|
593
|
|
|
image_name = "" |
|
594
|
|
|
img_format = "jpg" |
|
595
|
|
|
file_of_images = os.listdir(IMAGE_DIR) |
|
596
|
|
|
for i in file_of_images: |
|
597
|
|
|
for form in IMFORMAT_BOX: |
|
598
|
|
|
if i.find("." + form) != -1: |
|
599
|
|
|
image_name = os.path.join(IMAGE_DIR, i) |
|
600
|
|
|
img_format = form |
|
601
|
|
|
global IMAGE_COUNTER |
|
602
|
|
|
IMAGE_COUNTER = 1 |
|
603
|
|
|
break |
|
604
|
|
|
shutil.copyfile(image_name, os.path.join(OUT_DIR, "image." + img_format)) |
|
605
|
|
|
print_image(file, img_format) |
|
606
|
|
|
def build_resume(file): |
|
607
|
|
|
""" |
|
608
|
|
|
Find and build resume page. |
|
609
|
|
|
:param file: The resume file. |
|
610
|
|
|
:type file:_io.TextIOWrapper |
|
611
|
|
|
:return:None |
|
612
|
|
|
""" |
|
613
|
|
|
resume_name = "" |
|
614
|
|
|
file_of_docs = os.listdir(DOC_DIR) |
|
615
|
|
|
for i in file_of_docs: |
|
616
|
|
|
if i.find(".pdf") != -1: |
|
617
|
|
|
resume_name = os.path.join(DOC_DIR, i) |
|
618
|
|
|
global PDF_COUNTER |
|
619
|
|
|
PDF_COUNTER = 1 |
|
620
|
|
|
break |
|
621
|
|
|
shutil.copyfile(resume_name, os.path.join(OUT_DIR, "Resume.pdf")) |
|
622
|
|
|
print_download(file, "Download Full Version", "Resume.pdf", center=True) |
|
623
|
|
|
def contain(name): |
|
624
|
|
|
""" |
|
625
|
|
|
Main function that open each page HTML file and call other function to write data in it |
|
626
|
|
|
:param name: the name of the file that should be written |
|
627
|
|
|
:type name:str |
|
628
|
|
|
:return:None |
|
629
|
|
|
""" |
|
630
|
|
|
# |
|
631
|
|
|
file = open(os.path.join(OUT_DIR, name + ".html"), "a") |
|
632
|
|
|
text_file = open(os.path.join(DOC_DIR, name + ".txt"), "r") |
|
633
|
|
|
files.append(file) |
|
634
|
|
|
files.append(text_file) |
|
635
|
|
|
|
|
636
|
|
|
if name.upper() == "INDEX": |
|
637
|
|
|
build_index(file) |
|
638
|
|
|
elif name.upper() == "RESUME": |
|
639
|
|
|
build_resume(file) |
|
640
|
|
|
|
|
641
|
|
|
print_text(text_file, file) |
|
642
|
|
|
if name.upper() == "INDEX": |
|
643
|
|
|
print_adv(file) |
|
644
|
|
|
def clear_folder(path): |
|
645
|
|
|
""" |
|
646
|
|
|
This function get path of folder and delete its contains |
|
647
|
|
|
:param path: the path that gonna be deleted. |
|
648
|
|
|
:type path:str |
|
649
|
|
|
:return: None |
|
650
|
|
|
""" |
|
651
|
|
|
if os.path.exists(path): |
|
652
|
|
|
list_of_files = os.listdir(path) |
|
653
|
|
|
for file in list_of_files: |
|
654
|
|
|
os.remove(os.path.join(path, file)) |
|
655
|
|
|
else: |
|
656
|
|
|
os.mkdir(path) |
|
657
|
|
|
def print_warning(): |
|
658
|
|
|
""" |
|
659
|
|
|
Print warnings! |
|
660
|
|
|
:return:None |
|
661
|
|
|
""" |
|
662
|
|
|
print(str(len(warnings)) + " Warning , 0 Error") |
|
663
|
|
|
show_items(warnings) |
|
664
|
|
|
def get_color_code(): |
|
665
|
|
|
""" |
|
666
|
|
|
Ask for selecting color of text and background |
|
667
|
|
|
:return list: background and text color |
|
668
|
|
|
>>> get_color_code() |
|
669
|
|
|
0 - White |
|
670
|
|
|
1 - Black |
|
671
|
|
|
2 - Purple |
|
672
|
|
|
3 - Yellow |
|
673
|
|
|
4 - Orange |
|
674
|
|
|
5 - Green |
|
675
|
|
|
6 - Blue |
|
676
|
|
|
Please enter your background color : 1 |
|
677
|
|
|
Please enter your text color : 2 |
|
678
|
|
|
[1, 2] |
|
679
|
|
|
""" |
|
680
|
|
|
for i, item in enumerate(COLOR_BOX): |
|
681
|
|
|
print(i, "-", item) |
|
682
|
|
|
back_color_code = int(input("Please enter your background color : ")) |
|
683
|
|
|
if back_color_code not in range(7): |
|
684
|
|
|
back_color_code = 0 |
|
685
|
|
|
text_color_code = int(input("Please enter your text color : ")) |
|
686
|
|
|
if text_color_code not in range(7): |
|
687
|
|
|
text_color_code = 1 |
|
688
|
|
|
return [back_color_code, text_color_code] |
|
689
|
|
|
def color_code_map(): |
|
690
|
|
|
""" |
|
691
|
|
|
Check and insert colors that is chosen. |
|
692
|
|
|
:return list: background and text color |
|
693
|
|
|
""" |
|
694
|
|
|
[back_color_code, text_color_code] = get_color_code() |
|
695
|
|
|
if text_color_code == back_color_code: |
|
696
|
|
|
warnings.append(WARNING_DICT["color_warning"] + " Your text color and background color are same!!") |
|
697
|
|
|
background_color = COLOR_BOX[back_color_code] # convert code to color string in COLOR_BOX |
|
698
|
|
|
text_color = COLOR_BOX[text_color_code] # convert code to color string in COLOR_BOX |
|
699
|
|
|
return [background_color, text_color] |
|
700
|
|
|
def css_font(font_folder): |
|
701
|
|
|
""" |
|
702
|
|
|
Search and file all fonts. |
|
703
|
|
|
:param font_folder: the folder to search. |
|
704
|
|
|
:type font_folder:list |
|
705
|
|
|
:return list : font_flag and the current format |
|
706
|
|
|
""" |
|
707
|
|
|
font_flag = 0 # 0 If there is no font file in font_folder |
|
708
|
|
|
current_FONT_FORMAT = None |
|
709
|
|
|
for i in font_folder: |
|
710
|
|
|
for j in FONT_FORMAT: # search for other font format in font box |
|
711
|
|
|
if i.lower().find(j) != -1: # If there is a font in font folder |
|
712
|
|
|
shutil.copyfile(os.path.join(FONT_DIR, i), |
|
713
|
|
|
os.path.join(OUT_DIR, "qpage" + j)) # copy font file to output folder |
|
714
|
|
|
font_flag = 1 # Turn Flag On |
|
715
|
|
|
current_FONT_FORMAT = j # font format of current selected font for css editing |
|
716
|
|
|
return [font_flag, current_FONT_FORMAT] |
|
717
|
|
|
def font_creator(css_file, font_section): |
|
718
|
|
|
""" |
|
719
|
|
|
Ask and Select font. |
|
720
|
|
|
:param css_file: the file that font css will be added to. |
|
721
|
|
|
:param font_section: the font section of css file |
|
722
|
|
|
:type css_file:_io.TextIOWrapper |
|
723
|
|
|
:type font_section:str |
|
724
|
|
|
:return font_section: the font section of css after edit as string |
|
725
|
|
|
""" |
|
726
|
|
|
font_folder = os.listdir(FONT_DIR) |
|
727
|
|
|
details = css_font(font_folder) |
|
728
|
|
|
current_FONT_FORMAT = details[1] |
|
729
|
|
|
font_flag = details[0] |
|
730
|
|
|
if font_flag == 1: # check flag if it is 1 |
|
731
|
|
|
css_file.write( |
|
732
|
|
|
"@font-face{\nfont-family:qpagefont;\nsrc:url(qpage" |
|
733
|
|
|
+ current_FONT_FORMAT |
|
734
|
|
|
+ ");\n}\n") # Write font-face in html |
|
735
|
|
|
|
|
736
|
|
|
font_section = "font-family:qpagefont;\n" # Update Font Section For Body Tag |
|
737
|
|
|
for i, item in enumerate(FONTSTYLE_BOX): |
|
738
|
|
|
print(i, "-", item) |
|
739
|
|
|
font_style = int(input(" Please choose your font style ")) |
|
740
|
|
|
if font_style < len(FONTSTYLE_BOX): |
|
741
|
|
|
font_style = FONTSTYLE_BOX[font_style] |
|
742
|
|
|
else: |
|
743
|
|
|
font_style = "normal" |
|
744
|
|
|
font_section = font_section + "font-style:" + font_style + ";\n" |
|
745
|
|
|
else: |
|
746
|
|
|
warnings.append(WARNING_DICT["font_warning"] + " There is no specific font set for this website!!") |
|
747
|
|
|
return font_section |
|
748
|
|
|
def css_creator(): |
|
749
|
|
|
""" |
|
750
|
|
|
Ask For background and text color in and make css base |
|
751
|
|
|
:return:None |
|
752
|
|
|
""" |
|
753
|
|
|
font_section = 'font-family : Georgia , serif;\n' |
|
754
|
|
|
colors = color_code_map() |
|
755
|
|
|
background_color = colors[0] |
|
756
|
|
|
text_color = colors[1] |
|
757
|
|
|
|
|
758
|
|
|
css_file = open(os.path.join(OUT_DIR, "styles.css"), "w") # open css file |
|
759
|
|
|
font_section = font_creator(css_file, font_section) |
|
760
|
|
|
|
|
761
|
|
|
css_file.write( |
|
762
|
|
|
".body_tag{\n" |
|
763
|
|
|
+ "background-color:" |
|
764
|
|
|
+ background_color |
|
765
|
|
|
+ ";\n" |
|
766
|
|
|
+ font_section |
|
767
|
|
|
+ CSS_MARGIN |
|
768
|
|
|
+ CSS_ANIMATION_1 |
|
769
|
|
|
+ "}\n") # write body tag |
|
770
|
|
|
css_file.write(".color_tag{\n" + "color:" + text_color + ";\n}") # write color_tag in css |
|
771
|
|
|
css_file.write(CSS_ANIMATION_2) |
|
772
|
|
|
css_file.close() # close css file |
|
773
|
|
|
def preview(): |
|
774
|
|
|
""" |
|
775
|
|
|
Preview website in browser |
|
776
|
|
|
:return:None |
|
777
|
|
|
""" |
|
778
|
|
|
# TODO: not working on unix |
|
779
|
|
|
webbrowser.open(os.path.join(OUT_DIR, "index.html")) |
|
780
|
|
|
def error_finder(): |
|
781
|
|
|
""" |
|
782
|
|
|
Check and find error that display it |
|
783
|
|
|
:return : error and pass vector as list |
|
784
|
|
|
""" |
|
785
|
|
|
error_vector = [] |
|
786
|
|
|
pass_vector = [] |
|
787
|
|
|
PDF_COUNTER = 0 |
|
788
|
|
|
# image_list = os.listdir(IMAGE_DIR) |
|
789
|
|
|
doc_list = os.listdir(DOC_DIR) |
|
790
|
|
|
if IMAGE_COUNTER == 1: |
|
791
|
|
|
pass_vector.append("[Pass] Your profile image in OK!!") |
|
792
|
|
|
else: |
|
793
|
|
|
error_vector.append(ERROR_DICT["image_error"] + " Your profile image is not in correct format") |
|
794
|
|
|
if len(doc_list) == 0: |
|
795
|
|
|
error_vector.append(ERROR_DICT["empty_error"] + "There is no file in doc folder ( index.txt and .pdf file in " |
|
796
|
|
|
"necessary)") |
|
797
|
|
|
else: |
|
798
|
|
|
if "index.txt" in doc_list: |
|
799
|
|
|
pass_vector.append("[Pass] index.txt file OK!") |
|
800
|
|
|
else: |
|
801
|
|
|
error_vector.append(ERROR_DICT["firstpage_error"] + " index.txt is not in doc folder!") |
|
802
|
|
|
if PDF_COUNTER == 0: |
|
803
|
|
|
error_vector.append(ERROR_DICT["resume_error"] + "[Error] Where Is Your Resume File? It should be in doc " |
|
804
|
|
|
"folder") |
|
805
|
|
|
else: |
|
806
|
|
|
pass_vector.append("[Pass] Your Resume File is OK!!") |
|
807
|
|
|
return [error_vector, pass_vector] |
|
808
|
|
|
def icon_creator(): |
|
809
|
|
|
""" |
|
810
|
|
|
Find .ico file and use it as favicon of website. |
|
811
|
|
|
:return:None |
|
812
|
|
|
""" |
|
813
|
|
|
icon_flag = 0 |
|
814
|
|
|
for file in os.listdir(IMAGE_DIR): |
|
815
|
|
|
if file.endswith('ico'): |
|
816
|
|
|
shutil.copy(os.path.join(IMAGE_DIR, file), OUT_DIR) |
|
817
|
|
|
os.rename(os.path.join(OUT_DIR, file), os.path.join(OUT_DIR, 'favicon.ico')) |
|
818
|
|
|
icon_flag = 1 |
|
819
|
|
|
break |
|
820
|
|
|
if icon_flag == 0: |
|
821
|
|
|
if "favicon.ico" in os.listdir(SOURCE_DIR): |
|
822
|
|
|
shutil.copy(os.path.join(SOURCE_DIR, "favicon.ico"), OUT_DIR) |
|
823
|
|
|
warnings.append(WARNING_DICT["icon_warning"] + " There is no icon for this website") |
|
824
|
|
|
def robot_maker(): |
|
825
|
|
|
""" |
|
826
|
|
|
Create Robots.txt for pages |
|
827
|
|
|
:return:None |
|
828
|
|
|
""" |
|
829
|
|
|
robots = open(os.path.join(OUT_DIR, "robots.txt"), "w") |
|
830
|
|
|
robots.write("User-agent: *\n") |
|
831
|
|
|
robots.write("Disallow: ") |
|
832
|
|
|
robots.close() |
|
833
|
|
|
def internet(host="8.8.8.8", port=53, timeout=3): |
|
834
|
|
|
""" |
|
835
|
|
|
Check Internet Connections. |
|
836
|
|
|
:param host: the host that check connection to |
|
837
|
|
|
:param port: port that check connection with |
|
838
|
|
|
:param timeout: times that check the connnection |
|
839
|
|
|
:type host:str |
|
840
|
|
|
:type port:int |
|
841
|
|
|
:type timeout:int |
|
842
|
|
|
:return bool: True if Connection is Stable |
|
843
|
|
|
>>> internet() # if there is stable internet connection |
|
844
|
|
|
True |
|
845
|
|
|
>>> internet() # if there is no stable internet connection |
|
846
|
|
|
False |
|
847
|
|
|
""" |
|
848
|
|
|
try: |
|
849
|
|
|
socket.setdefaulttimeout(timeout) |
|
850
|
|
|
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port)) |
|
851
|
|
|
return True |
|
852
|
|
|
except Exception as ex: |
|
853
|
|
|
error_log(str(ex)) |
|
854
|
|
|
return False |
|
855
|
|
|
def server(): |
|
856
|
|
|
""" |
|
857
|
|
|
Get Server response. |
|
858
|
|
|
:return:None |
|
859
|
|
|
>>> server() |
|
860
|
|
|
Installed Saved! |
|
861
|
|
|
""" |
|
862
|
|
|
# global meta_input |
|
863
|
|
|
headers = {'content-type': 'application/json', "NAME": meta_input, "VERSION": VERSION, "SYSTEM": system_details(), |
|
864
|
|
|
"IP": find_global_ip()} |
|
865
|
|
|
try: |
|
866
|
|
|
response = requests.get(SERVER_API, headers=headers) |
|
867
|
|
|
if response.status_code == 200: |
|
868
|
|
|
print("Installed Saved!") |
|
869
|
|
|
except Exception as e: |
|
870
|
|
|
error_log(str(e)) |
|
871
|
|
|
def version_control(): |
|
872
|
|
|
""" |
|
873
|
|
|
Check and update version status |
|
874
|
|
|
:return:None |
|
875
|
|
|
""" |
|
876
|
|
|
try: |
|
877
|
|
|
# print("Check for new VERSION . . .") |
|
878
|
|
|
# print_line(70) |
|
879
|
|
|
VERSION_pattern = r"last_VERSION:(.+)" |
|
880
|
|
|
if internet(): |
|
881
|
|
|
response = requests.get("http://www.qpage.ir/releases.html") |
|
882
|
|
|
body = response.text |
|
883
|
|
|
last_VERSION = float(re.findall(VERSION_pattern, body)[0][:-3]) |
|
884
|
|
|
if last_VERSION > float(VERSION): |
|
885
|
|
|
print_line(70) |
|
886
|
|
|
print("**New VERSION Of Qpage Is Available Now (VERSION " + str(last_VERSION) + ")**") |
|
887
|
|
|
print("Download Link -->" + "https://github.com/sepandhaghighi/qpage/archive/v" + str( |
|
888
|
|
|
last_VERSION) + ".zip") |
|
889
|
|
|
print_line(70) |
|
890
|
|
|
else: |
|
891
|
|
|
# TODO : fix VERSION control else |
|
892
|
|
|
pass |
|
893
|
|
|
# print("Already Updated!!!") |
|
894
|
|
|
# print_line(70) |
|
895
|
|
|
except Exception as e: |
|
896
|
|
|
error_log(str(e)) |
|
897
|
|
|
pass |
|
898
|
|
|
def enter_to_exit(): |
|
899
|
|
|
""" |
|
900
|
|
|
Quit Project by pressing a key. |
|
901
|
|
|
:return:None |
|
902
|
|
|
""" |
|
903
|
|
|
|
|
904
|
|
|
print_line(70, "*") |
|
905
|
|
|
response = input("Enter [R] for restart Qpage and any other key to exit : ") |
|
906
|
|
|
if response.upper() != "R": |
|
907
|
|
|
sys.exit() |
|
908
|
|
|
def wait_func(iteration=2): |
|
909
|
|
|
""" |
|
910
|
|
|
Wait for-in range Iteration. |
|
911
|
|
|
:param iteration: the amount of wait. |
|
912
|
|
|
:type iteration:int |
|
913
|
|
|
:return:None |
|
914
|
|
|
>>> wait_func(4) |
|
915
|
|
|
. |
|
916
|
|
|
. |
|
917
|
|
|
. |
|
918
|
|
|
. |
|
919
|
|
|
>>> wait_func() |
|
920
|
|
|
. |
|
921
|
|
|
. |
|
922
|
|
|
""" |
|
923
|
|
|
for _ in range(iteration): |
|
924
|
|
|
time.sleep(1) |
|
925
|
|
|
print(".") |
|
926
|
|
|
if __name__=="__main__": |
|
927
|
|
|
doctest.testmod() |
|
928
|
|
|
|