Completed
Push — master ( 4a8f4d...692ff1 )
by Sepand
57s
created

read_lorem()   B

Complexity

Conditions 4

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

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