app.py 4.78 KB
Newer Older
1
from flask import Flask, render_template, redirect, request, abort, flash, url_for, Response, jsonify
2
3
import re, os, yaml, redis, sys
import uuid
4
from url_normalize import url_normalize
5
import json
6

AntonKras's avatar
AntonKras committed
7
app = Flask(__name__)
8
app.secret_key = os.urandom(24)
9
count = 0
AntonKras's avatar
AntonKras committed
10
r = redis.Redis(charset="utf-8", decode_responses=True)
11

12

13
@app.route('/')
AntonKras's avatar
AntonKras committed
14
def main():
15
16
17
18
    """
    функция рендерит шаблон
    :return отрендеренный html-файл:
    """
19
20
21
22
    global count
    count += 1
    if count == 1:  # если первый вход, то читаем из yml и загружаем в redis
        extract_yml_data_and_load_to_redis(sys.argv[1])
23
24
25

    final_dict = r.hgetall('urls_dict')  # достаем словарь из redis и передаем в шаблон
    return render_template('index.html', final_dict=final_dict)  # рендер шаблона
AntonKras's avatar
AntonKras committed
26
27


28
@app.route('/add', methods=['GET', 'POST'])
29
def add() -> Response:
30
    """
31
    функция добавления соответствия в redis
32
    :return redirect(перенаправление на главную страницу):
33
    """
34
    url = request.form["url"]
35
    if check_if_input_is_url(url) is None:
36
        flash('URL введен некорректно!')
37
        return abort(404)
38
39
40
    else:
        short_url = generate_short_url()
        data = {short_url: url}
41
42
43
44
45
46
        # r.mset(data)
        r.hmset('urls_dict', data)

        json_dict = {"url": '/' + short_url}
        # return redirect(url_for('main'))
        return Response(json.dumps(json_dict), status=200, mimetype='application/json')
47
48


49
@app.route('/<path:path>')
50
def redirect_somewhere(path) -> redirect:
51
52
53
54
55
    """
    функция перенаправляет пользователя на соответствующую короткой ссылке страницу
    :param path (передается часть ссылки после /):
    :return redirect or 404 Error:
    """
56

57
58
59
60
    urls_dict = r.hgetall("urls_dict")
    if urls_dict.get(path) != None:
        redirected_url = normalize(urls_dict.get(path))
        return render_template('before_redirect.html', redirected_url=redirected_url)
61
    else:
62
        return abort(404)
AntonKras's avatar
AntonKras committed
63
64


65
def extract_yml_data_and_load_to_redis(urls) -> None:
AntonKras's avatar
AntonKras committed
66
    """
67
    извлекает данные из yml и загружает в redis
68
    :param файл формата yml или yaml:
69
    :return None
AntonKras's avatar
AntonKras committed
70
    """
71
72

    final_dict = {}  # словарь с данными из файла .yml
73
74
    with open(urls, 'r') as stream:
        try:
75
76
            final_dict = yaml.safe_load(stream)  # загрузка данных в словарь
        except yaml.YAMLError as exc:  # обработка исключения
77
            print(exc)
78
79
80
81
82
    # # печать словаря в консоли
    # for key, value in final_dict.items():
    #     print(key + ":" + value)
    # r.mset(final_dict)  # загрузить в redis
    r.hmset("urls_dict", final_dict)
83

84

85
def generate_short_url() -> str:
86
    """
87
    функция генерирования уникальной короткой ссылки из букв и цифр
88
    :return сгенерированная строчка:
89
    """
90
91
    rand_str = uuid.uuid4().hex[:5]
    return rand_str
92
93
94


def check_if_input_is_url(url) -> None or not None:
95
    """
96
97
98
    проверка ссылку на валидность
    :param ссылка:
    :return None or not None:
99
    """
100
101
102
103
    regex = re.compile(
        r'^(?:http|ftp)s?://'  # http:// или https://
        r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'  # домен
        r'localhost|'  # localhost...
104
        r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'  # ...или ip
105
106
107
108
109
110
        r'(?::\d+)?'  # optional port
        r'(?:/?|[/?]\S+)$', re.IGNORECASE)
    answer = re.match(regex, url)
    return answer


111
112
113
def normalize(url: str) -> str:
    """
    нормализация ссылки
114
115
    :param ссылка:
    :return нормализованная ссылка:
116
    """
117
118
    norm_url = url_normalize(url)
    return norm_url
AntonKras's avatar
AntonKras committed
119
120
121


if __name__ == '__main__':
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
    while 1:
        c = int(input('Ввести логин/пароль для redis?\n1.Да\n2.Нет\n'))
        if c == 1:
            host = int(input('Введите хост: '))
            port = int(input('\nВведите порт: '))
            username = input('\nВведите логин:')
            password = input('\nВведите пароль: ')
            r = redis.Redis(charset="utf-8", decode_responses=True, host=host, port=port, username=username,
                            password=password)
            break
        if c == 2:
            r = redis.Redis(charset="utf-8", decode_responses=True)
            break
        else:
            print('Введена неверная команда\n')

138
    app.run()