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
|
|
|
|
13
|
|
|
meta_input = "" |
14
|
|
|
|
15
|
|
|
|
16
|
|
|
def convert_bytes(num): |
17
|
|
|
""" convert num to idiomatic byte unit |
18
|
|
|
|
19
|
|
|
:param num: the input number. |
20
|
|
|
""" |
21
|
|
|
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']: |
22
|
|
|
if num < 1024.0: |
23
|
|
|
return "%3.1f %s" % (num, x) |
24
|
|
|
num /= 1024.0 |
25
|
|
|
|
26
|
|
|
|
27
|
|
|
def file_size(): |
28
|
|
|
""" Print the size of output file |
29
|
|
|
|
30
|
|
|
""" |
31
|
|
|
list_of_files = os.listdir(out_dir) |
32
|
|
|
response = 0 |
33
|
|
|
for file in list_of_files: |
34
|
|
|
file_info = os.stat(os.path.join(out_dir, file)) |
35
|
|
|
response += file_info.st_size |
36
|
|
|
print_line(70, "*") |
37
|
|
|
print("Used Space --> " + convert_bytes(response)) |
38
|
|
|
print_line(70, "*") |
39
|
|
|
|
40
|
|
|
|
41
|
|
|
def download_badge(address): |
42
|
|
|
""" Download badge for website |
43
|
|
|
|
44
|
|
|
:param address: the address that should get badge |
45
|
|
|
""" |
46
|
|
|
r = requests.get(address, stream=True) |
47
|
|
|
with open(os.path.join(image_dir, "badge.svg"), 'wb') as f: |
48
|
|
|
shutil.copyfileobj(r.raw, f) |
49
|
|
|
|
50
|
|
|
|
51
|
|
|
def random_badge_color(): |
52
|
|
|
"""return a random color for badge |
53
|
|
|
|
54
|
|
|
""" |
55
|
|
|
random_index = random.randint(0, len(badge_color_list) - 1) |
56
|
|
|
return badge_color_list[random_index] |
57
|
|
|
|
58
|
|
|
|
59
|
|
|
def system_details(): |
60
|
|
|
""" Show detail of system that code is runnig on |
61
|
|
|
|
62
|
|
|
""" |
63
|
|
|
return platform.node() + " , " + platform.processor() + " , " + platform.platform() |
64
|
|
|
|
65
|
|
|
|
66
|
|
|
def generation_time(time_1=None): |
67
|
|
|
""" Calculate the generation time |
68
|
|
|
|
69
|
|
|
:param time_1: time that passed but not counted in generation time |
70
|
|
|
:return :the amount of time that passed . |
71
|
|
|
""" |
72
|
|
|
if time_1 is None: |
73
|
|
|
return time.perf_counter() |
74
|
|
|
else: |
75
|
|
|
return time.perf_counter() - time_1 |
76
|
|
|
|
77
|
|
|
|
78
|
|
|
def find_global_ip(): |
79
|
|
|
""" Find the ip for use in API |
80
|
|
|
|
81
|
|
|
:return: return the IP. |
82
|
|
|
""" |
83
|
|
|
try: |
84
|
|
|
response = requests.get(ip_finder_api) |
85
|
|
|
return response.text[:-1] |
86
|
|
|
except: |
87
|
|
|
return "0.0.0.0" |
88
|
|
|
|
89
|
|
|
|
90
|
|
|
def create_badge(subject="qpage", status=version, color="blue", random=False): |
91
|
|
|
if random: |
92
|
|
|
color = random_badge_color() |
93
|
|
|
else: |
94
|
|
|
if color not in badge_color_list: |
95
|
|
|
color = "orange" |
96
|
|
|
badge_adr = adv_badge_static + subject + "-" + status + "-" + color + '.svg' |
97
|
|
|
if internet(): |
98
|
|
|
download_badge(badge_adr) |
99
|
|
|
return os.path.join(image_dir, "badge.svg") |
100
|
|
|
else: |
101
|
|
|
return badge_adr |
102
|
|
|
|
103
|
|
|
|
104
|
|
|
def is_sample_downloaded(): |
105
|
|
|
""" Check the sample site material is downloaded |
106
|
|
|
|
107
|
|
|
:return : list of the materials |
108
|
|
|
""" |
109
|
|
|
download_list = [] |
110
|
|
|
if "profile.png" not in os.listdir(image_dir): |
111
|
|
|
download_list.append(0) |
112
|
|
|
if "font.TTF" not in os.listdir(font_dir): |
113
|
|
|
download_list.append(1) |
114
|
|
|
if "resume.pdf" not in os.listdir(doc_dir) and "resume.txt" not in os.listdir(doc_dir): |
115
|
|
|
download_list.extend([2, 3]) |
116
|
|
|
if "icon.ico" not in os.listdir(image_dir): |
117
|
|
|
download_list.append(4) |
118
|
|
|
return download_list |
119
|
|
|
|
120
|
|
|
|
121
|
|
|
def download_lorem(): |
122
|
|
|
""" Download the lorem file |
123
|
|
|
|
124
|
|
|
""" |
125
|
|
|
if internet(): |
126
|
|
|
urllib.request.urlretrieve("http://www.qpage.ir/sample/Latin-Lipsum.txt", "Latin-Lipsum.txt") |
127
|
|
|
else: |
128
|
|
|
print("Error In Download Lorem") |
129
|
|
|
|
130
|
|
|
|
131
|
|
|
def read_lorem(char=100): |
132
|
|
|
""" find and read lorem |
133
|
|
|
|
134
|
|
|
:param char: the amount of char that needed |
135
|
|
|
:return : the lorme string |
136
|
|
|
""" |
137
|
|
|
try: |
138
|
|
|
if "Latin-Lipsum.txt" not in os.listdir(work_dir): |
139
|
|
|
download_lorem() |
140
|
|
|
lorem_file = open("Latin-Lipsum.txt", "r") |
141
|
|
|
lorem_text = lorem_file.read() |
142
|
|
|
lorem_file.close() |
143
|
|
|
return " ".join(lorem_text.split(" ")[:char]) |
144
|
|
|
except: |
145
|
|
|
return None |
146
|
|
|
|
147
|
|
|
|
148
|
|
|
def sample_site_download(item_list): |
149
|
|
|
"""Download sample material for make a fake site |
150
|
|
|
|
151
|
|
|
:param item_list: Download items form item_list |
152
|
|
|
""" |
153
|
|
|
try: |
154
|
|
|
if internet(): |
155
|
|
|
for i in item_list: |
156
|
|
|
print("Downloading " + sample_dict_message[i] + " . . . [" + str(i + 1) + "/5]") |
157
|
|
|
print_line(70) |
158
|
|
|
urllib.request.urlretrieve(list(sample_dict_addr.values())[i], |
159
|
|
|
os.path.join(image_dir, list(sample_dict_addr.keys())[i])) |
160
|
|
|
print("Done! All Material Downloaded") |
161
|
|
|
print_line(70) |
162
|
|
|
else: |
163
|
|
|
print("Error In Internet Connection!") |
164
|
|
|
print_line(70) |
165
|
|
|
except: |
166
|
|
|
print("Error in downloading sample files check your internet conection") |
167
|
|
|
print_line(70) |
168
|
|
|
|
169
|
|
|
|
170
|
|
|
def logger(status=False, perf_time=None): |
171
|
|
|
"""Show the log of the app |
172
|
|
|
|
173
|
|
|
:param status: show status of app. |
174
|
|
|
:param perf_time : show the time passed for generate files |
175
|
|
|
""" |
176
|
|
|
file = open("build_log.txt", "a") |
177
|
|
|
if not status: |
178
|
|
|
file.write("Failed " + str(datetime.datetime.now()) + "\n") |
179
|
|
|
else: |
180
|
|
|
file.write("Success " + str(datetime.datetime.now()) + "\n") |
181
|
|
|
file.write("Generation Time: " + str(perf_time) + "\n") |
182
|
|
|
file.close() |
183
|
|
|
|
184
|
|
|
|
185
|
|
|
def print_line(number, char="-"): |
186
|
|
|
""" Print a Line |
187
|
|
|
|
188
|
|
|
:param number: the amount char that in lien |
189
|
|
|
:param char : the char that used to draw line |
190
|
|
|
""" |
191
|
|
|
line = "" |
192
|
|
|
for i in range(number): |
193
|
|
|
line += char |
194
|
|
|
print(line) |
195
|
|
|
|
196
|
|
|
|
197
|
|
|
def name_standard(name): |
198
|
|
|
""" return the Standard version of the input word |
199
|
|
|
|
200
|
|
|
:param name: the name that should be standard |
201
|
|
|
:return name: the standard form of word |
202
|
|
|
""" |
203
|
|
|
reponse_name = name[0].upper() + name[1:].lower() |
204
|
|
|
return reponse_name |
205
|
|
|
|
206
|
|
|
|
207
|
|
|
def address_print(): |
208
|
|
|
"""Print the working directory |
209
|
|
|
|
210
|
|
|
""" |
211
|
|
|
print_line(70, "*") |
212
|
|
|
print("Where --> " + work_dir) |
213
|
|
|
print_line(70, "*") |
214
|
|
|
|
215
|
|
|
|
216
|
|
|
def create_folder(): |
217
|
|
|
"""This Function Create Empty Folder At Begin |
218
|
|
|
|
219
|
|
|
""" |
220
|
|
|
folder_flag = 0 |
221
|
|
|
list_of_folders = os.listdir(work_dir) |
222
|
|
|
for i in ["doc", "image", "output", "font"]: |
223
|
|
|
if i not in list_of_folders: |
224
|
|
|
os.mkdir(i) |
225
|
|
|
folder_flag += 1 |
226
|
|
|
if i == "doc": |
227
|
|
|
file = open(os.path.join(doc_dir, "index.txt"), "w") |
228
|
|
|
if read_lorem() is None: |
229
|
|
|
file.write("This is For First Page . . .") |
230
|
|
|
else: |
231
|
|
|
file.write(read_lorem()) |
232
|
|
|
file.close() |
233
|
|
|
return bool(folder_flag) |
234
|
|
|
|
235
|
|
|
|
236
|
|
|
def page_name_update(): |
237
|
|
|
"""This Function Update Page Names |
238
|
|
|
|
239
|
|
|
""" |
240
|
|
|
for i in os.listdir(doc_dir): |
241
|
|
|
if i.find(".txt") != -1 and i[:-4].upper() != "INDEX": |
242
|
|
|
actual_name.append(i[:-4]) |
243
|
|
|
page_name.append(i[:-4]) |
244
|
|
|
|
245
|
|
|
|
246
|
|
|
def menu_maker(): |
247
|
|
|
"""Top Menu Maker In each html page |
248
|
|
|
|
249
|
|
|
""" |
250
|
|
|
result = "<center>" |
251
|
|
|
for i in range(len(page_name)): |
252
|
|
|
if page_name[i] == "Home": |
253
|
|
|
targets_blank = "" |
254
|
|
|
else: |
255
|
|
|
targets_blank = 'target="blank"' |
256
|
|
|
# Hyper Link To Each Page In HTML File |
257
|
|
|
result += '\t<a href="' \ |
258
|
|
|
+ actual_name[i] + '.html"' + targets_blank + '>' + name_standard(page_name[i]) + "</a>\n" |
259
|
|
|
result += " \n" |
260
|
|
|
result += "</center>" |
261
|
|
|
result = result + "\t\t" + break_line # Add Break line to End Of The Menu |
262
|
|
|
return result # Return All Of The Menu |
263
|
|
|
|
264
|
|
|
|
265
|
|
|
def menu_writer(): # |
266
|
|
|
"""Write menu_maker output in html and close file after |
267
|
|
|
|
268
|
|
|
""" |
269
|
|
|
message = menu_maker() |
270
|
|
|
for i in range(len(page_name)): |
271
|
|
|
file = open(os.path.join(out_dir, actual_name[i] + ".html"), "a") |
272
|
|
|
file.write(message) |
273
|
|
|
file.close() |
274
|
|
|
|
275
|
|
|
|
276
|
|
|
def print_meta(): |
277
|
|
|
"""Add meta to html files |
278
|
|
|
|
279
|
|
|
:return static_meta: The meta that created |
280
|
|
|
""" |
281
|
|
|
global meta_input |
282
|
|
|
meta_input = input("Please Enter Your Name : ") |
283
|
|
|
static_meta = '<meta name="description" content="Welcome to homepage of ' + meta_input + '"/>\n' |
284
|
|
|
static_meta += '<meta property="og:title" content="' + meta_input + '"/>\n' |
285
|
|
|
static_meta += '<meta property="og:site_name" content="' + meta_input + '"/>\n' |
286
|
|
|
static_meta += '<meta property="og:image" content="favicon.ico" />\n' |
287
|
|
|
if len(meta_input) < 4: |
288
|
|
|
warnings.append("[Warning] Your input for name is too short!!") |
289
|
|
|
return static_meta |
290
|
|
|
|
291
|
|
|
|
292
|
|
|
def html_init(name): |
293
|
|
|
"""Create Initial Form Of each Html Page Like Title And HTML And Body Tag. |
294
|
|
|
|
295
|
|
|
:param name: the name of html file. |
296
|
|
|
""" |
297
|
|
|
|
298
|
|
|
html_name = os.path.join(out_dir, name + ".html") |
299
|
|
|
file = open(html_name, "w") |
300
|
|
|
file.write("<html>\n") |
301
|
|
|
file.write("\t<head>\n") |
302
|
|
|
if name == "index": |
303
|
|
|
file.write("\t\t<title>Welcome To My Homepage</title>\n") |
304
|
|
|
else: |
305
|
|
|
file.write("\t\t<title>" + name_standard(name) + "</title>\n") |
306
|
|
|
file.write('<link rel="stylesheet" href="styles.css" type="text/css"/>\n') |
307
|
|
|
css_link = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css' |
308
|
|
|
file.write('<link rel="stylesheet" href= ' + css_link + ' type="text/style"/>\n') |
309
|
|
|
|
310
|
|
|
if name == 'index': # Add meta only for index page |
311
|
|
|
file.write(print_meta()) |
312
|
|
|
|
313
|
|
|
file.write("\t</head>\n") |
314
|
|
|
file.write('\t<body class="body_tag">\n') |
315
|
|
|
file.close() |
316
|
|
|
|
317
|
|
|
|
318
|
|
|
def html_end(name): |
319
|
|
|
"""Create End Of The Html and close file |
320
|
|
|
|
321
|
|
|
:param name: The name of html file. |
322
|
|
|
""" |
323
|
|
|
html_name = os.path.join(out_dir, name + ".html") |
324
|
|
|
file = open(html_name, "a") |
325
|
|
|
file.write("\t</body>\n") |
326
|
|
|
file.write("</html>") |
327
|
|
|
file.close() |
328
|
|
|
|
329
|
|
|
|
330
|
|
|
def close_files(): |
331
|
|
|
"""Close all the files. |
332
|
|
|
|
333
|
|
|
""" |
334
|
|
|
for i in files: |
335
|
|
|
i.close() |
336
|
|
|
|
337
|
|
|
|
338
|
|
|
def LSM_translate(line, center): |
339
|
|
|
# TODO : write a document for this function |
340
|
|
|
""" ???? |
341
|
|
|
|
342
|
|
|
:param line: the input line. |
343
|
|
|
:param center: put it in center |
344
|
|
|
|
345
|
|
|
:return : return a list contain text header end and header begin |
346
|
|
|
""" |
347
|
|
|
line.strip() |
348
|
|
|
text = line |
349
|
|
|
header_start = '<h4 class="color_tag">' |
350
|
|
|
header_end = "</h4>" |
351
|
|
|
if line.find("[L]") != -1: |
352
|
|
|
header_start = '<h2 class="color_tag">' |
353
|
|
|
header_end = "</h2>" |
354
|
|
|
text = line[3:] |
355
|
|
|
elif line.find("[S]") != -1: |
356
|
|
|
header_start = '<h5 class="color_tag">' |
357
|
|
|
header_end = "</h5>" |
358
|
|
|
text = line[3:] |
359
|
|
|
elif line.find("[M]") != -1: |
360
|
|
|
text = line[3:] |
361
|
|
|
if center: # Centuries Text If Condition Is True For Manual Centering |
362
|
|
|
header_start = "<center>" + header_start |
363
|
|
|
header_end += "</center>" |
364
|
|
|
if text.find("[center]") != -1: # Find Center Tag In Each Line |
365
|
|
|
header_start = "<center>" + header_start |
366
|
|
|
header_end += "</center>" |
367
|
|
|
text = text[:text.find("[center]")] |
368
|
|
|
return [text, header_end, header_start] |
369
|
|
|
|
370
|
|
|
|
371
|
|
|
def print_text(text_file, file, center=False, close=False): # Write Text Part Of Each Page |
372
|
|
|
"""Write the text part of each page |
373
|
|
|
|
374
|
|
|
:param text_file: Text tha should be written. |
375
|
|
|
:param file : The file that text will be written inside. |
376
|
|
|
:param center : put the text in center. |
377
|
|
|
:param close : close file after done editing |
378
|
|
|
|
379
|
|
|
:type close : bool |
380
|
|
|
:type center: bool |
381
|
|
|
|
382
|
|
|
""" |
383
|
|
|
|
384
|
|
|
text_code = "" |
385
|
|
|
for line in text_file: |
386
|
|
|
if len(line) == 1: |
387
|
|
|
text_code = space |
388
|
|
|
else: |
389
|
|
|
text_header = LSM_translate(line, center) |
390
|
|
|
text = text_header[0] |
391
|
|
|
header_end = text_header[1] |
392
|
|
|
header_start = text_header[2] |
393
|
|
|
text_code = header_start + text + header_end + "\n" |
394
|
|
|
file.write(text_code) |
395
|
|
|
if close: |
396
|
|
|
file.close() |
397
|
|
|
|
398
|
|
|
|
399
|
|
|
def print_image(file, image_format="jpg", close=False): |
400
|
|
|
"""Write Image Part OF The Page. |
401
|
|
|
|
402
|
|
|
:param file: The file that images will be added. |
403
|
|
|
:param close : close file after done editing. |
404
|
|
|
:param image_format: the format of image |
405
|
|
|
|
406
|
|
|
:type close : bool |
407
|
|
|
""" |
408
|
|
|
for i in range(len(size_box)): |
409
|
|
|
print(i, "-", size_box[i]) |
410
|
|
|
image_size = int(input("Please Enter Profile Image Size : ")) # Choose Profile Image Size |
411
|
|
|
image_size_string = size_box[2] # Getting Html String From size_box list default mode (Medium) |
412
|
|
|
if 0 <= image_size < len(size_box): |
413
|
|
|
image_size_string = size_box[image_size] |
414
|
|
|
image_code = '<center><img src="image.' + image_format + '"' + ', width=' + image_size_string + ' alt="profile image"></img></center>\n' |
415
|
|
|
file.write(image_code) |
416
|
|
|
if close: |
417
|
|
|
file.close() |
418
|
|
|
|
419
|
|
|
|
420
|
|
|
def print_download(file, name, link, center=False, close=False): |
421
|
|
|
""" Create Download Link in page |
422
|
|
|
|
423
|
|
|
:param file: The file that contain html of page. |
424
|
|
|
:param name: The name of the link |
425
|
|
|
:param link: The place that name is Linked |
426
|
|
|
:param center: put the text in center |
427
|
|
|
:param close : close file after done editing |
428
|
|
|
|
429
|
|
|
:type center: bool |
430
|
|
|
:type close : bool |
431
|
|
|
|
432
|
|
|
""" |
433
|
|
|
link_code = "<a href=" + '"' + link + '"' + target_blank + '>' + name + "</a>" |
434
|
|
|
if center: |
435
|
|
|
link_code = "<center>" + link_code + "</center>" |
436
|
|
|
file.write(link_code + "\n") |
437
|
|
|
file.write(break_line) |
438
|
|
|
if close: |
439
|
|
|
file.close() |
440
|
|
|
|
441
|
|
|
|
442
|
|
|
def print_adv(file, close=True): |
443
|
|
|
""" Print the advertisement. |
444
|
|
|
|
445
|
|
|
:param file : The file that should ad to it. |
446
|
|
|
:param close : Close file after add ad |
447
|
|
|
""" |
448
|
|
|
file.write(break_line) |
449
|
|
|
file.write( |
450
|
|
|
'<center>' + "<p>" + "Generated " + today_time + " By" + "</p>" + '<a href=' + '"' + homepage + '"' + target_blank + '>' + '<img src="' + create_badge( |
451
|
|
|
random=True) + '"alt="Qpage">' + '</a> </center>') |
452
|
|
|
if close: |
453
|
|
|
file.close() |
454
|
|
|
|
455
|
|
|
|
456
|
|
|
def build_index(file): |
457
|
|
|
""" Find and build index page |
458
|
|
|
|
459
|
|
|
:param file: The index file. |
460
|
|
|
""" |
461
|
|
|
image_name = "" |
462
|
|
|
img_format = "jpg" |
463
|
|
|
file_of_images = os.listdir(image_dir) |
464
|
|
|
for i in range(len(file_of_images)): |
465
|
|
|
for form in imformat_box: |
466
|
|
|
if file_of_images[i].find("." + form) != -1: |
467
|
|
|
image_name = os.path.join(image_dir, file_of_images[i]) |
468
|
|
|
img_format = form |
469
|
|
|
global image_counter |
470
|
|
|
image_counter = 1 |
471
|
|
|
break |
472
|
|
|
shutil.copyfile(image_name, os.path.join(out_dir, "image." + img_format)) |
473
|
|
|
print_image(file, img_format) |
474
|
|
|
|
475
|
|
|
|
476
|
|
|
def build_resume(file): |
477
|
|
|
""" Find and build resume page. |
478
|
|
|
|
479
|
|
|
:param file: The resume file. |
480
|
|
|
""" |
481
|
|
|
resume_name = "" |
482
|
|
|
file_of_docs = os.listdir(doc_dir) |
483
|
|
|
for i in range(len(file_of_docs)): |
484
|
|
|
if file_of_docs[i].find(".pdf") != -1: |
485
|
|
|
resume_name = os.path.join(doc_dir, file_of_docs[i]) |
486
|
|
|
global pdf_counter |
487
|
|
|
pdf_counter = 1 |
488
|
|
|
break |
489
|
|
|
shutil.copyfile(resume_name, os.path.join(out_dir, "Resume.pdf")) |
490
|
|
|
print_download(file, "Download Full Version", "Resume.pdf", center=True) |
491
|
|
|
|
492
|
|
|
|
493
|
|
|
def contain(name): |
494
|
|
|
"""main function That Open Each Page HTML File and call other function to write data in it |
495
|
|
|
|
496
|
|
|
:param name: the name of the file that should be written |
497
|
|
|
""" |
498
|
|
|
# |
499
|
|
|
file = open(os.path.join(out_dir, name + ".html"), "a") |
500
|
|
|
text_file = open(os.path.join(doc_dir, name + ".txt"), "r") |
501
|
|
|
files.append(file) |
502
|
|
|
files.append(text_file) |
503
|
|
|
|
504
|
|
|
if name.upper() == "INDEX": |
505
|
|
|
build_index(file) |
506
|
|
|
elif name.upper() == "RESUME": |
507
|
|
|
build_resume(file) |
508
|
|
|
|
509
|
|
|
print_text(text_file, file) |
510
|
|
|
print_adv(file) |
511
|
|
|
|
512
|
|
|
|
513
|
|
|
def clear_folder(path): |
514
|
|
|
"""This Function Get Path Of Foldr And Delete Its Contains |
515
|
|
|
|
516
|
|
|
:param path: the path that gonna be deleted. |
517
|
|
|
""" |
518
|
|
|
|
519
|
|
|
if os.path.exists(path): |
520
|
|
|
list_of_files = os.listdir(path) |
521
|
|
|
for file in list_of_files: |
522
|
|
|
os.remove(os.path.join(path, file)) |
523
|
|
|
else: |
524
|
|
|
os.mkdir(path) |
525
|
|
|
|
526
|
|
|
|
527
|
|
|
def print_warning(): |
528
|
|
|
""" Print Warinigns! |
529
|
|
|
|
530
|
|
|
""" |
531
|
|
|
print(str(len(warnings)) + " Warning , 0 Error") |
532
|
|
|
for i in range(len(warnings)): |
533
|
|
|
print(str(i + 1) + "-" + warnings[i]) |
534
|
|
|
|
535
|
|
|
|
536
|
|
|
def get_color_code(): |
537
|
|
|
"""Ask for selecting color of text and background |
538
|
|
|
|
539
|
|
|
:return list: background and text color |
540
|
|
|
""" |
541
|
|
|
for i in range(len(color_box)): |
542
|
|
|
print(i, "-", color_box[i]) |
543
|
|
|
back_color_code = int(input("Please enter your background color : ")) |
544
|
|
|
if back_color_code not in range(7): |
545
|
|
|
back_color_code = 0 |
546
|
|
|
text_color_code = int(input("Please enter your text color : ")) |
547
|
|
|
if text_color_code not in range(7): |
548
|
|
|
text_color_code = 1 |
549
|
|
|
return [back_color_code, text_color_code] |
550
|
|
|
|
551
|
|
|
|
552
|
|
|
def color_code_map(): |
553
|
|
|
""" Check and insert colors that is chosen. |
554
|
|
|
|
555
|
|
|
:return list: background and text color |
556
|
|
|
""" |
557
|
|
|
[back_color_code, text_color_code] = get_color_code() |
558
|
|
|
if text_color_code == back_color_code: |
559
|
|
|
warnings.append(warning_dict["color_warning"] + " Your text color and background color are same!!") |
560
|
|
|
background_color = color_box[back_color_code] # convert code to color string in color_box |
561
|
|
|
text_color = color_box[text_color_code] # convert code to color string in color_box |
562
|
|
|
return [background_color, text_color] |
563
|
|
|
|
564
|
|
|
|
565
|
|
|
def css_font(font_folder): |
566
|
|
|
""" Search and file all fonts. |
567
|
|
|
|
568
|
|
|
:param font_folder: the folder to search. |
569
|
|
|
:return list : font_flag and the current format |
570
|
|
|
""" |
571
|
|
|
font_flag = 0 # 0 If there is no font file in font_folder |
572
|
|
|
current_font_format = None |
573
|
|
|
for i in font_folder: |
574
|
|
|
for j in range(len(font_format)): # search for other font format in font box |
575
|
|
|
if i.lower().find(font_format[j]) != -1: # If there is a font in font folder |
576
|
|
|
shutil.copyfile(os.path.join(font_dir, i), |
577
|
|
|
os.path.join(out_dir, "qpage" + font_format[j])) # copy font file to output folder |
578
|
|
|
font_flag = 1 # Turn Flag On |
579
|
|
|
current_font_format = font_format[j] # font format of current selected font for css editing |
580
|
|
|
return [font_flag, current_font_format] |
581
|
|
|
|
582
|
|
|
|
583
|
|
|
def font_creator(css_file, font_section): |
584
|
|
|
""" Ask and Select font. |
585
|
|
|
|
586
|
|
|
:param css_file: the file that font css will be added to. |
587
|
|
|
:param font_section: the font section of css file |
588
|
|
|
|
589
|
|
|
:return font_section: the font section of css after edit |
590
|
|
|
""" |
591
|
|
|
font_folder = os.listdir(font_dir) |
592
|
|
|
details = css_font(font_folder) |
593
|
|
|
current_font_format = details[1] |
594
|
|
|
font_flag = details[0] |
595
|
|
|
|
596
|
|
|
if font_flag == 1: # check flag if it is 1 |
597
|
|
|
css_file.write( |
598
|
|
|
"@font-face{\nfont-family:qpagefont;\nsrc:url(qpage" |
599
|
|
|
+ current_font_format |
600
|
|
|
+ ");\n}\n") # Write font-face in html |
601
|
|
|
|
602
|
|
|
font_section = "font-family:qpagefont;\n" # Update Font Section For Body Tag |
603
|
|
|
for i in range(len(fontstyle_box)): |
604
|
|
|
print(i, "-", fontstyle_box[i]) |
605
|
|
|
font_style = int(input(" Please choose your font style ")) |
606
|
|
|
if font_style < len(fontstyle_box): |
607
|
|
|
font_style = fontstyle_box[font_style] |
608
|
|
|
else: |
609
|
|
|
font_style = "normal" |
610
|
|
|
font_section = font_section + "font-style:" + font_style + ";\n" |
611
|
|
|
else: |
612
|
|
|
warnings.append(warning_dict["font_warning"] + " There is no specific font set for this website!!") |
613
|
|
|
return font_section |
614
|
|
|
|
615
|
|
|
|
616
|
|
|
def css_creator(): |
617
|
|
|
"""Ask For background and text color in and make css """ |
618
|
|
|
font_section = 'font-family : Georgia , serif;\n' |
619
|
|
|
colors = color_code_map() |
620
|
|
|
background_color = colors[0] |
621
|
|
|
text_color = colors[1] |
622
|
|
|
|
623
|
|
|
css_file = open(os.path.join(out_dir, "styles.css"), "w") # open css file |
624
|
|
|
font_section = font_creator(css_file, font_section) |
625
|
|
|
|
626
|
|
|
css_file.write( |
627
|
|
|
".body_tag{\n" |
628
|
|
|
+ "background-color:" |
629
|
|
|
+ background_color |
630
|
|
|
+ ";\n" |
631
|
|
|
+ font_section |
632
|
|
|
+ css_margin |
633
|
|
|
+ css_animation_1 |
634
|
|
|
+ "}\n") # write body tag |
635
|
|
|
|
636
|
|
|
css_file.write(".color_tag{\n" + "color:" + text_color + ";\n}") # write color_tag in css |
637
|
|
|
css_file.write(css_animation_2) |
638
|
|
|
css_file.close() # close css file |
639
|
|
|
|
640
|
|
|
|
641
|
|
|
def preview(): |
642
|
|
|
"""Preview website in browser """ |
643
|
|
|
# TODO: not working on unix |
644
|
|
|
|
645
|
|
|
webbrowser.open(os.path.join(out_dir, "index.html")) |
646
|
|
|
|
647
|
|
|
|
648
|
|
|
def error_finder(): |
649
|
|
|
""" Check and find error that display it""" |
650
|
|
|
error_vector = [] |
651
|
|
|
pass_vector = [] |
652
|
|
|
pdf_counter = 0 |
653
|
|
|
image_list = os.listdir(image_dir) |
654
|
|
|
doc_list = os.listdir(doc_dir) |
655
|
|
|
if image_counter == 1: |
656
|
|
|
pass_vector.append("[Pass] Your profile image in OK!!") |
657
|
|
|
else: |
658
|
|
|
error_vector.append(error_dict["image_error"] + " Your profile image is not in correct format") |
659
|
|
|
if len(doc_list) == 0: |
660
|
|
|
error_vector.append(error_dict["empty_error"] + "There is no file in doc folder ( index.txt and .pdf file in " |
661
|
|
|
"necessary)") |
662
|
|
|
else: |
663
|
|
|
if "index.txt" in doc_list: |
664
|
|
|
pass_vector.append("[Pass] index.txt file OK!") |
665
|
|
|
else: |
666
|
|
|
error_vector.append(error_dict["firstpage_error"] + " index.txt is not in doc folder!") |
667
|
|
|
if pdf_counter == 0: |
668
|
|
|
error_vector.append(error_dict["resume_error"] + "[Error] Where Is Your Resume File? It should be in doc " |
669
|
|
|
"folder") |
670
|
|
|
else: |
671
|
|
|
pass_vector.append("[Pass] Your Resume File is OK!!") |
672
|
|
|
return [error_vector, pass_vector] |
673
|
|
|
|
674
|
|
|
|
675
|
|
|
def icon_creator(): |
676
|
|
|
""" Find .ico file and use it as favicon of website.""" |
677
|
|
|
icon_flag = 0 |
678
|
|
|
for file in os.listdir(image_dir): |
679
|
|
|
if file.endswith('ico'): |
680
|
|
|
shutil.copy(os.path.join(image_dir, file), out_dir) |
681
|
|
|
os.rename(os.path.join(out_dir, file), os.path.join(out_dir, 'favicon.ico')) |
682
|
|
|
icon_flag = 1 |
683
|
|
|
break |
684
|
|
|
if "favicon.ico" in os.listdir(work_dir) and icon_flag == 0: |
685
|
|
|
shutil.copy(os.path.join(work_dir, "favicon.ico"), out_dir) |
686
|
|
|
warnings.append(warning_dict["icon_warning"] + " There is no icon for this website") |
687
|
|
|
|
688
|
|
|
|
689
|
|
|
def robot_maker(): |
690
|
|
|
""" Create Robots.txt for pages """ |
691
|
|
|
robots = open(os.path.join(out_dir, "robots.txt"), "w") |
692
|
|
|
robots.write("User-agent: *\n") |
693
|
|
|
robots.write("Disallow: ") |
694
|
|
|
robots.close() |
695
|
|
|
|
696
|
|
|
|
697
|
|
|
def internet(host="8.8.8.8", port=53, timeout=3): |
698
|
|
|
""" Check Internet Connections. |
699
|
|
|
|
700
|
|
|
:param host: the host that check connection to |
701
|
|
|
:param port: port that check connection with |
702
|
|
|
:param timeout: times that check the connnection |
703
|
|
|
|
704
|
|
|
:return bool: True if Connection is Stable |
705
|
|
|
""" |
706
|
|
|
try: |
707
|
|
|
socket.setdefaulttimeout(timeout) |
708
|
|
|
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port)) |
709
|
|
|
return True |
710
|
|
|
except Exception as ex: |
711
|
|
|
return False |
712
|
|
|
|
713
|
|
|
|
714
|
|
|
def server(): |
715
|
|
|
"""Get Server response.""" |
716
|
|
|
global meta_input |
717
|
|
|
headers = {'content-type': 'application/json', "NAME": meta_input, "Version": version, "SYSTEM": system_details(), |
718
|
|
|
"IP": find_global_ip()} |
719
|
|
|
response = requests.get(server_api, headers=headers) |
720
|
|
|
# print(response) |
721
|
|
|
# TODO : use the server response |
722
|
|
|
|
723
|
|
|
|
724
|
|
|
def version_control(): |
725
|
|
|
""" Check and update Versions. """ |
726
|
|
|
|
727
|
|
|
try: |
728
|
|
|
# print("Check for new version . . .") |
729
|
|
|
# print_line(70) |
730
|
|
|
version_pattern = r"last_version:(.+)" |
731
|
|
|
if internet(): |
732
|
|
|
response = requests.get("http://www.qpage.ir/releases.html") |
733
|
|
|
body = response.text |
734
|
|
|
last_version = float(re.findall(version_pattern, body)[0][:-3]) |
735
|
|
|
if last_version > float(version): |
736
|
|
|
print_line(70) |
737
|
|
|
print("**New Version Of Qpage Is Available Now (Version " + str(last_version) + ")**") |
738
|
|
|
print("Download Link -->" + "https://github.com/sepandhaghighi/qpage/archive/v" + str( |
739
|
|
|
last_version) + ".zip") |
740
|
|
|
print_line(70) |
741
|
|
|
else: |
742
|
|
|
# TODO : fix version control else |
743
|
|
|
pass |
744
|
|
|
# print("Already Updated!!!") |
745
|
|
|
# print_line(70) |
746
|
|
|
except: |
747
|
|
|
pass |
748
|
|
|
|
749
|
|
|
|
750
|
|
|
def enter_to_exit(): |
751
|
|
|
"""Quit Project by pressing a key. |
752
|
|
|
|
753
|
|
|
""" |
754
|
|
|
|
755
|
|
|
print_line(70, "*") |
756
|
|
|
response = input("Enter [R] for restart Qpage and any other key to exit : ") |
757
|
|
|
if response.upper() != "R": |
758
|
|
|
sys.exit() |
759
|
|
|
|
760
|
|
|
|
761
|
|
|
def wait_func(iteration): |
762
|
|
|
"""Wait for-in range Iteration. |
763
|
|
|
|
764
|
|
|
:param iteration: the amount of wait. |
765
|
|
|
""" |
766
|
|
|
|
767
|
|
|
for _ in range(iteration): |
768
|
|
|
time.sleep(1) |
769
|
|
|
print(".") |
770
|
|
|
|