diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000..d4e632c
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+worker: python server.py $PORT
\ No newline at end of file
diff --git a/SQLEasy.py b/SQLEasy.py
new file mode 100644
index 0000000..f61de44
--- /dev/null
+++ b/SQLEasy.py
@@ -0,0 +1,228 @@
+import sqlite3
+
+
+class SQLiteEasyException(Exception):
+ pass
+
+
+def compareKey(DBlist, key, type_of_key=lambda x: x, hideIndex=True):
+ if not(type(DBlist) is list):
+ raise SQLiteEasyException(f"function compareKey need List object, unsupported type: {type(DBlist)}")
+
+ if len(DBlist) > 0:
+ if key not in DBlist[0]:
+ raise SQLiteEasyException(f"key '{key}' not founded.")
+ DB_Dictonary = dict()
+ for BD in sorted(DBlist, key=lambda List: List[key]):
+ comparedBD = dict()
+ for Key in BD:
+ if not(Key == key) and hideIndex:
+ comparedBD[Key] = BD[Key]
+ elif not hideIndex:
+ comparedBD[Key] = BD[Key]
+ DB_Dictonary[type_of_key(BD[key])] = comparedBD
+
+ return DB_Dictonary
+
+
+def autoselectID_fromNew_item(DATABASE, TABLE, ID_KEY):
+ TABLE_DATA = DATABASE.getBase(TABLE)
+ TABLE_DATA = compareKey(TABLE_DATA, ID_KEY)
+ TABLE_DATA = [ID for ID in TABLE_DATA]
+ INDEX = 0
+ for DATA_INDEX in TABLE_DATA:
+ if INDEX == DATA_INDEX:
+ INDEX += 1
+ else:
+ return INDEX
+ return INDEX
+
+
+class database:
+ def dict_factory(self, cursor, row):
+ dictDB = {}
+ for idx, col in enumerate(cursor.description):
+ dictDB[col[0]] = row[idx]
+ return dictDB
+
+ def encodeSQLiteType(self, objectum, all_as_str=False):
+ if type(objectum) is str:
+ return "'%s'" % objectum.replace("'", "[SQLEasy_symbol:']")
+ elif objectum is None and all_as_str:
+ return "''"
+ elif objectum is None:
+ return 'NULL'
+ elif type(objectum) is bool and objectum and all_as_str:
+ return "'TRUE'"
+ elif type(objectum) is bool and objectum:
+ return 'TRUE'
+ elif type(objectum) is bool and not(objectum) and all_as_str:
+ return "'FALSE'"
+ elif type(objectum) is bool and not(objectum):
+ return 'FALSE'
+ elif all_as_str and True in [type(objectum) is int, type(objectum) is float]:
+ return "'%s'" % objectum
+ elif not(all_as_str) and True in [type(objectum) is int, type(objectum) is float]:
+ return objectum
+ else:
+ raise SQLiteEasyException(f"Unsupported type: {type(objectum)}")
+
+ def __init__(self, PATH, DatabaseName=None):
+ self.ConnectedFile = sqlite3.connect(PATH, check_same_thread=False)
+ self.databaseChoosed = DatabaseName
+ self.ConnectedFile.row_factory = self.dict_factory
+ self.act_commit = True
+
+ def toggleCommit(self, value=None):
+ if value in (False, True):
+ self.act_commit = value
+ else:
+ if self.act_commit:
+ self.act_commit = False
+ else:
+ self.act_commit = True
+
+ def commit(self):
+ self.ConnectedFile.commit()
+
+ def getBase(self, DatabaseName=None, elementsFromDB='*'):
+ elementsFromDB = str(elementsFromDB)
+ if DatabaseName is None and self.databaseChoosed is None:
+ raise SQLiteEasyException("Database is not choosed")
+ elif DatabaseName is None and not(self.databaseChoosed is None):
+ dbCursore = self.ConnectedFile.cursor()
+ dbCursore.execute(f"select {elementsFromDB} from {self.databaseChoosed}")
+ result = dbCursore.fetchall()
+ else:
+ dbCursore = self.ConnectedFile.cursor()
+ dbCursore.execute(f"select {elementsFromDB} from {DatabaseName}")
+ self.databaseChoosed = DatabaseName
+ result = dbCursore.fetchall()
+
+ for rowID in range(len(result)):
+ row = result[rowID]
+ for cellKey in row:
+ if type(row[cellKey]) is str:
+ result[rowID][cellKey] = row[cellKey].replace('[SQLEasy_symbol:']', "'")
+ return result
+
+ def pop(self, key, value, DatabaseName=None):
+ if type(value) is str:
+ # value = f"'%s'" % value.replace('\'', '\\\'')
+ value = f"'%s'" % value.replace("'", '[SQLEasy_symbol:']')
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+ dbCursore = self.ConnectedFile.cursor()
+ dbCursore.execute('DELETE FROM %s\n\nWHERE %s == %s;' % (DatabaseName, key, value))
+ if self.act_commit:
+ self.ConnectedFile.commit()
+
+ def setItem(self, key, newValue, indexKey, value, DatabaseName=None):
+ newValue = self.encodeSQLiteType(newValue)
+ value = self.encodeSQLiteType(value)
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+ dbCursore = self.ConnectedFile.cursor()
+ if value is None:
+ dbCursore.execute('UPDATE %s SET %s = %s WHERE %s is NULL;' % (DatabaseName, key, newValue, indexKey))
+ else:
+ dbCursore.execute('UPDATE %s SET %s = %s WHERE %s = %s;' % (DatabaseName, key, newValue, indexKey, value))
+ if self.act_commit:
+ self.ConnectedFile.commit()
+
+ def add(self, values, DatabaseName=None):
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+
+ keys = [str(key) for key in values]
+ values = [self.encodeSQLiteType(values[key], all_as_str=True) for key in values]
+
+ dbCursore = self.ConnectedFile.cursor()
+ try:
+ dbCursore.execute('INSERT INTO %s (%s) VALUES (%s)' % (DatabaseName, ', '.join(keys), ', '.join(values)))
+ except:
+ dbCursore.execute('INSERT OR IGNORE INTO %s (%s) VALUES (%s)' % (DatabaseName, ', '.join(keys), ', '.join(values)))
+ if self.act_commit:
+ self.ConnectedFile.commit()
+
+ def uploadFiles(self, binary, DatabaseName=None): # Uwaga! Может работать с ошибками.
+ if not(type(binary) is bytes or type(binary) is bytearray):
+ raise SQLiteEasyException('You can upload only byte or bytearray types!!')
+ dbCursore = self.ConnectedFile.cursor()
+ binary = sqlite3.Binary(binary)
+
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+ # (!) Дописать
+
+ def chooseDataBase(self, DatabaseName):
+ self.getBase(DatabaseName)
+ self.databaseChoosed = DatabaseName
+
+ def currentIndex(self, key, value, DatabaseName=None):
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+
+ DB = self.getBase(DatabaseName)
+
+ ID = 0
+ for Dictonary in sorted(DB, key=lambda dictonary: dictonary[key]):
+ if Dictonary[key] == value:
+ return ID
+ ID += 1
+
+ def currentValue(self, key, value, DatabaseName=None):
+ if DatabaseName is None and not(self.databaseChoosed is None):
+ DatabaseName = self.databaseChoosed
+ elif DatabaseName is None:
+ raise SQLiteEasyException("Database is not choosed")
+
+ DB = self.getBase(DatabaseName)
+
+ for Dictonary in sorted(DB, key=lambda dictonary: dictonary[key]):
+ if Dictonary[key] == value:
+ return Dictonary
+
+ def createColumn(self, columnName, tableName, DatabaseName=None):
+ return # (!) Не реализовано!!
+
+ def getTables(self):
+ dbCursore = self.ConnectedFile.cursor()
+ dbCursore.execute('SELECT name from sqlite_master where type= "table"')
+ return [item['name'] for item in dbCursore.fetchall()]
+
+ def getDict(self):
+ dictonary = dict()
+ tables = self.getTables()
+ for table in tables:
+ dictonary[table] = self.getBase(table)
+ return dictonary
+
+ def execute(self, req):
+ dbCursore = self.ConnectedFile.cursor()
+ dbCursore.execute(req)
+ if self.act_commit:
+ self.ConnectedFile.commit()
+ return dbCursore.fetchall()
+
+
+def formingTable(dictonary, path):
+ pass # В разработке
\ No newline at end of file
diff --git a/database.db b/database.db
new file mode 100644
index 0000000..bc79f8e
Binary files /dev/null and b/database.db differ
diff --git a/mailclient.py b/mailclient.py
new file mode 100644
index 0000000..adee0e2
--- /dev/null
+++ b/mailclient.py
@@ -0,0 +1,53 @@
+import smtplib as smtp
+
+
+class output:
+ def __init__(self):
+ self.debug = False
+
+ def toggleDebug(self, flag=None):
+ if flag is None:
+ if self.debug:
+ self.debug = False
+ else:
+ self.debug = True
+ else:
+ self.debug = flag
+
+ def printf(self, *args, sep=' ', end='\n', file=None):
+ if self.debug:
+ if file is None:
+ print(*args, sep=sep, end=end)
+ else:
+ print(*args, sep=sep, end=end, file=file)
+
+
+output_tool = output()
+smtp.print = output_tool.printf
+
+
+class mail:
+ def __init__(self, email, password):
+ self.email = email
+ self.password = password
+
+ def set_smtp_server(self, url):
+ smtp.SMTP_SSL(url)
+ self.SMTP_SERVER = url
+
+ def send(self, subject, email_text, to_mail):
+ message = 'From: {}\nTo: {}\nSubject: {}\n\n{}'.format(self.email,
+ to_mail,
+ subject,
+ email_text)
+ server = smtp.SMTP_SSL(self.SMTP_SERVER)
+ server.set_debuglevel(1)
+ server.ehlo(self.email)
+ server.login(self.email, self.password)
+ server.auth_plain()
+ server.sendmail(
+ self.email,
+ to_mail,
+ message.encode('utf-8')
+ )
+ server.quit()
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..8ab6294
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+flask
\ No newline at end of file
diff --git a/server.py b/server.py
new file mode 100644
index 0000000..938f131
--- /dev/null
+++ b/server.py
@@ -0,0 +1,766 @@
+from flask import Flask, render_template, request, redirect, url_for, flash, make_response
+import SQLEasy, random, mailclient, traceback, json, time, socket
+
+database = SQLEasy.database('database.db')
+
+app = Flask(__name__)
+
+HOST = '127.0.0.1'
+HOST = socket.gethostbyname(socket.gethostname())
+PORT = 8080
+
+EMAIL = '' # Введите сюда свой адрес электронной почты
+EMAIL_PASSWORD = '' # Введите сюда свой пароль от электронной почты
+# Рекомендуется использовать сервера Яндекса: smtp.yandex.ru
+SMTP_SERVER = 'smtp.yandex.ru' # Укажите свой SMTP сервер (смотрите по сервису, обычно SMTP сервера находятся по адресу smtp.sevise.org, например: smtp.google.com)
+mailObject = mailclient.mail(EMAIL, EMAIL_PASSWORD)
+mailObject.set_smtp_server(SMTP_SERVER)
+
+file_content = '''var type = "auth";
+
+function timeConverter(UNIX_timestamp){
+ var a = new Date(UNIX_timestamp * 1000);
+ var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
+ var year = a.getFullYear();
+ var month = months[a.getMonth()];
+ var date = a.getDate();
+ var hour = a.getHours();
+ var min = a.getMinutes();
+ var sec = a.getSeconds();
+ var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec ;
+ return time;
+}
+
+function buton_regAuth(){
+ if(type == "auth") type = "reg";
+ else type = "auth";
+ if(type == "auth") document.getElementById("authwin").innerHTML = "
\n Регистрация "
+ else document.getElementById("authwin").innerHTML = " \n Авторизация "
+}
+
+function confirmation_mail(mail_adress) {
+ var codeConfirmation = "\n \n "
+
+ var GET_Request = new XMLHttpRequest();
+ GET_Request.open("GET", "http://127.0.0.1:8080/api/confirmation/start?email=" + mail_adress, true);
+ GET_Request.onload = function (){
+ var content = GET_Request.responseText;
+ document.getElementById("authwin").innerHTML = codeConfirmation;
+ }
+ GET_Request.send(null);
+}
+
+function get_cookies(){
+ var cookie_f = document.cookie;
+ var cookies = cookie_f.split('; ');
+ // alert(cookie_f);
+ var returnCookie = {};
+
+ cookies.forEach(function(item, i, cookies) {
+ console.log(item);
+ ItemArray = item.split('=');
+ console.log(ItemArray);
+ console.log(ItemArray[0]);
+ console.log(ItemArray[1]);
+ returnCookie[ItemArray[0]] = ItemArray[1];
+ });
+ console.log(returnCookie)
+
+ return returnCookie;
+}
+
+function update(){
+ var cookies = get_cookies();
+ var xhr = new XMLHttpRequest();
+
+ xhr.open('GET', "http://127.0.0.1:8080/api/user/get_pages?autogroup=1&token=" + cookies.token, false);
+ // alert('ok');
+
+ xhr.send();
+ if (xhr.status != 200) {
+ var ok = 'ok';
+ } else {
+ var values = JSON.parse(xhr.responseText);
+ // alert(xhr.responseText);
+ var groups = values.response;
+ var retV = '';
+ groups.forEach(function(group, i, groups) {
+ var item = '';
+ var clocker = 0;
+ group.forEach(function(cellContent, i, group) {
+ clocker += 1;
+ item += `${cellContent.title} Создано: ${timeConverter(cellContent.created)} Отредактирован: ${timeConverter(cellContent.edited)}
\n`;
+ });
+ retV += `${item}
\n`;
+ });
+ retV += "";
+ document.getElementById("field").innerHTML = retV;
+ }
+}'''
+
+for codePath in ('static/button.js', 'static/script.js', 'static/scripts.js', 'static/source_test_20.js', 'static/scripts/button.js'):
+ content = file_content
+
+ content = content.replace('127.0.0.1:8080', f"{HOST}:{PORT}")
+
+ jsCodeObj = open(codePath, 'wt', encoding='utf-8')
+ jsCodeObj.write(content)
+ jsCodeObj.close()
+
+
+def formatMail(mail):
+ servise = mail.split('@')[-1]
+ domain = mail.split('@')[0]
+ if servise in ('ya.ru', 'yandex.ru', 'yandex.by', 'yandex.ua', 'yandex.kz'):
+ servise = 'yandex.ru'
+ elif servise in ('mail.ru', 'inbox.ru', 'internet.ru', 'bk.ru', 'list.ru'):
+ servise = 'mail.ru'
+
+ return f"{domain}@{servise}"
+
+
+def genToken(LEN=32):
+ TOKEN = ''
+ for _ in range(LEN):
+ TOKEN += '0123456789abcdef'[random.randint(0, 15)]
+ return TOKEN
+
+
+def checkToken(TOKEN):
+ if not(TOKEN):
+ return False
+ data = database.getBase('auths')
+ data = [DATA['token'] for DATA in data]
+ if not(TOKEN in data):
+ return False
+
+ data = SQLEasy.compareKey(database.getBase('auths'), 'token')[TOKEN]
+ return bool(data['active'])
+
+
+def checkMail(MAIL):
+ MAIL = formatMail(MAIL)
+ if not(MAIL):
+ return False
+ data = database.getBase('Users')
+ data = [formatMail(DATA['email']) for DATA in data]
+
+ return MAIL in data
+
+
+def checkPassword(PASS):
+ if not(PASS):
+ return False
+ data = database.getBase('Users')
+ data = [DATA['password'] for DATA in data]
+
+ return PASS in data
+
+
+def getUserData(TOKEN):
+ UserID = SQLEasy.compareKey(database.getBase('auths'), 'token')[TOKEN]['UserID']
+ return SQLEasy.compareKey(database.getBase('Users'), 'ID', hideIndex=False)[UserID]
+
+
+def validData_check(MAIL, PASSWORD):
+ userData = SQLEasy.compareKey(database.getBase('Users'), 'email')[MAIL]
+ return userData['password'] == PASSWORD
+
+
+@app.route('/')
+def index():
+ if not(checkToken(request.cookies.get('token'))):
+ errorCode = ''
+ if request.args.get('error', default=False):
+ errorCode = 'Ошибка: %s
' % request.args.get('error')
+
+ retPage = '''
+
+ Блокнот онлайн
+
+
+
+
+
+
+
+
+ ERROM_MSG
+
+
+'''
+ retPage = retPage.replace('ERROM_MSG', errorCode)
+ return retPage
+ else:
+ return redirect("/note/menu", code=302)
+
+
+@app.route('/logout')
+def logout():
+ res = redirect("/", code=302)
+ res.set_cookie('token', 'NULL', max_age=1)
+ return res
+
+@app.route('/note/id/')
+def pageView(PageID):
+ if checkToken(request.cookies.get('token')):
+ try:
+ PageID = int(PageID)
+ except:
+ return redirect("/", code=302)
+ pageData = SQLEasy.compareKey(database.getBase('Pages'), 'ID', hideIndex=False)[PageID]
+ title = pageData['title']
+ content = pageData['content']
+
+ if getUserData(request.cookies.get('token'))['ID'] != pageData['ownerID']:
+ return redirect("/?error=Отказано в доступе.", code=302)
+
+ if request.args.get('act') != 'edit':
+ HTMLcontent = '''
+
+ NOTETITLE
+
+
+
+
+
+
+ NOTETITLE
+
+
+'''
+ HTMLcontent = HTMLcontent.replace('HOSTPORTION', f"{HOST}:{PORT}")
+ HTMLcontent = HTMLcontent.replace('NOTETITLE', title)
+ HTMLcontent = HTMLcontent.replace('NOTECONTENT', content)
+ return HTMLcontent
+ else:
+ HTMLcontent = '''
+
+ NOTETITLE
+
+
+
+
+
+
+ Редактирование NOTECONTENT
+
+
+'''
+ HTMLcontent = HTMLcontent.replace('HOSTPORTION', f"{HOST}:{PORT}")
+ HTMLcontent = HTMLcontent.replace('NOTETITLE', title)
+ HTMLcontent = HTMLcontent.replace('PAGE_ID', str(PageID))
+ HTMLcontent = HTMLcontent.replace('NOTECONTENT', content)
+ return HTMLcontent
+ else:
+ return redirect("/", code=302)
+
+@app.route('/note/')
+def main_menu(menu_ind):
+ if not(checkToken(request.cookies.get('token'))):
+ return redirect("/", code=302)
+
+ if menu_ind == 'menu':
+ HTMLcontent = '''
+
+ Главная страница
+
+
+
+
+
+
+
+
+ Ваши заметки
+
+
+
+'''
+ HTMLcontent = HTMLcontent.replace('HOSTPORTION', f"{HOST}:{PORT}")
+ return HTMLcontent
+ elif menu_ind == 'add':
+ HTMLcontent = '''
+
+ Новая запись
+
+
+
+
+
+
+ Создать заметку
+
+
+'''
+ HTMLcontent = HTMLcontent.replace('HOSTPORTION', f"{HOST}:{PORT}")
+ return HTMLcontent
+
+@app.route('/file_api//')
+def file_api(method):
+ print('METHOD:', method)
+
+ if not checkToken(request.cookies.get('token')):
+ return redirect("/?error=Для использования файлового API нужно авторизоваться.", code=302)
+
+ if method == 'add':
+ userObj = SQLEasy.compareKey(database.getBase('auths'), 'token')[request.cookies.get('token')]['UserID']
+ userObj = SQLEasy.compareKey(database.getBase('Users'), 'ID', hideIndex=False)[userObj]
+
+ title = request.args.get('title')
+ if len(title) < 3:
+ return redirect("/note/add", code=302)
+ color = request.args.get('color')
+ if len(color) < 3:
+ return redirect("/note/add", code=302)
+ content = request.args.get('content')
+ if len(content) == 0:
+ return redirect("/note/add", code=302)
+
+ newID = SQLEasy.autoselectID_fromNew_item(database, 'Pages', 'ID')
+ database.add({
+ 'ID': newID,
+ 'ownerID': userObj['ID'],
+ 'title': title,
+ 'content': content,
+ 'color': f"#{color}",
+ 'created': int(time.time()),
+ 'edited': int(time.time())
+ }, 'Pages')
+ return redirect("/note/id/%s" % newID, code=302)
+ if method == 'edit':
+ print('FUCK1488!!!')
+ try:
+ noteID = int(request.args.get('id'))
+ except:
+ return redirect("/", code=302)
+
+ userObj = SQLEasy.compareKey(database.getBase('auths'), 'token')[request.cookies.get('token')]['UserID']
+ userObj = SQLEasy.compareKey(database.getBase('Users'), 'ID', hideIndex=False)[userObj]
+
+ title = request.args.get('title')
+ if len(title) < 3:
+ return redirect("/note/id/%s" % noteID, code=302)
+ color = request.args.get('color')
+ if len(color) < 3:
+ return redirect("/note/id/%s" % noteID, code=302)
+ content = request.args.get('content')
+ if len(content) == 0:
+ return redirect("/note/id/%s" % noteID, code=302)
+
+ database.setItem(
+ 'title',
+ title,
+ 'ID',
+ noteID,
+ DatabaseName='Pages'
+ )
+ database.setItem(
+ 'content',
+ content,
+ 'ID',
+ noteID,
+ DatabaseName='Pages'
+ )
+ database.setItem(
+ 'color',
+ f"#{color}",
+ 'ID',
+ noteID,
+ DatabaseName='Pages'
+ )
+ database.setItem(
+ 'edited',
+ int(time.time()),
+ 'ID',
+ noteID,
+ DatabaseName='Pages'
+ )
+
+ return redirect("/note/id/%s" % noteID, code=302)
+
+@app.route('/oauth/')
+def oauth(method):
+ if method == 'auth':
+ email = request.args.get('email', default=None)
+ if email is None:
+ return redirect("/?error=Не введён адрес электронной почты.", code=302)
+ if not checkMail(email):
+ return redirect("/?error=Неверный адрес электронной почты или пароль.", code=302)
+ email = formatMail(email)
+
+ password = request.args.get('password', default=None)
+ if password is None:
+ return redirect("/?error=Не введён пароль", code=302)
+ if len(password) < 8:
+ return redirect("/?error=Поле \"Пароль\" должно содержать не менее 8 символов!", code=302)
+ if not checkPassword(password):
+ return redirect("/?error=Неверный адрес электронной почты или пароль.", code=302)
+ if not validData_check(email, password):
+ return redirect("/?error=Неверный адрес электронной почты или пароль.", code=302)
+
+ while True:
+ token = genToken()
+ if token not in [item['token'] for item in database.getBase('auths')]:
+ break
+
+ database.add({
+ 'token': token,
+ 'UserID': SQLEasy.compareKey(database.getBase('Users'), 'email')[email]['ID'],
+ 'active': 1
+ }, 'auths')
+
+ res = redirect("/", code=302)
+ res.set_cookie('token', token, max_age=60*60*24*365*2)
+
+ return res
+ elif method == 'register':
+ email = request.args.get('email', default=None)
+ if email is None:
+ return redirect("/?error=Не введён адрес электронной почты.", code=302)
+
+ foward_email = request.args.get('fowardemail', default=None)
+ if email != foward_email:
+ print({"foward_email": foward_email, "email": email})
+ return redirect("/?error=Адреса почтовых ящиков не совпадают.", code=302)
+ del foward_email
+
+ if email in SQLEasy.compareKey(database.getBase('Users'), 'email'):
+ return redirect("/?error=Этот ящик уже зарегистрирован.", code=302)
+
+ password = request.args.get('password', default=None)
+ if password is None:
+ return redirect("/?error=Не введён пароль", code=302)
+ if len(password) < 8:
+ return redirect("/?error=Поле \"Пароль\" должно содержать не менее 8 символов!", code=302)
+
+ foward_password = request.args.get('fowardpassword', default=None)
+ if password != foward_password:
+ return redirect("/?error=Пароли не совподают.", code=302)
+ del foward_password
+
+ database.add({
+ 'ID': SQLEasy.autoselectID_fromNew_item(database, 'Users', 'ID'),
+ 'email': formatMail(email),
+ 'password': password,
+ 'verif_code': genToken(8).upper(),
+ 'mail_confirm': 0
+ }, 'Users')
+ return redirect("/oauth/confirmation?mail=%s" % formatMail(email), code=302)
+ elif method == 'confirmation':
+ mail = request.args.get('mail', default=None)
+ finish_code = request.args.get('finish_code', default=None)
+ if mail is None and finish_code is None:
+ return redirect("/?error=Не задан ни почтовый ящик, ни код подтверждения при передаче параметров oauth/confirmation", code=302)
+
+ if mail:
+ codeHTML = '''
+
+ Подтвердите почтовый адрес
+
+
+
+
+
+
+
+
+
+
+ Подтвердите почтовый адрес
+ На ваш почтовый адрес: MAIL_ADRES придёт код активации.
+ Письмо придёт от адреса: BOT_MAIL_ADRES лучше сразу добавьте его в белый список.
+ Продолжить
+
+
+
+'''
+
+ codeHTML = codeHTML.replace('HOSTPORTION', f"{HOST}:{PORT}")
+ codeHTML = codeHTML.replace('BOT_MAIL_ADRES', EMAIL)
+ codeHTML = codeHTML.replace('MAIL_ADRES', mail)
+
+ return codeHTML
+ if finish_code:
+ finish_code = finish_code.upper()
+
+ if finish_code not in [code for code in SQLEasy.compareKey(database.getBase('Users'), 'verif_code')]:
+ return redirect("/?error=Неверный код подтверждения.", code=302)
+ else:
+ userObj = SQLEasy.compareKey(database.getBase('Users'), 'verif_code')[finish_code]
+ database.setItem(
+ 'mail_confirm',
+ 1,
+ 'ID',
+ userObj['ID'],
+ DatabaseName='Users'
+ )
+
+ token = genToken()
+ database.add({
+ 'token': token,
+ 'UserID': userObj['ID'],
+ 'active': 1
+ }, 'auths')
+
+ res = redirect("/", code=302)
+ res.set_cookie('token', token, max_age=60*60*24*365*2)
+
+ return res
+
+ return redirect("/?error=Неизвестный ранее метод oauth", code=302)
+
+@app.route('/api//')
+def API(method_group, method):
+ if method_group == 'user':
+ if method == 'get_pages':
+ token = request.args.get('token', default=None)
+ autogroup = bool(request.args.get('autogroup', default=False))
+ if not checkToken(token):
+ return '{"error": "invalid token"}'
+ session = SQLEasy.compareKey(database.getBase('auths'), 'token')[token]
+ userID = session['UserID']
+ del session
+ userData = SQLEasy.compareKey(database.getBase('Users'), 'ID', hideIndex=False)[userID]
+ mypages = list()
+
+ for page in database.getBase('Pages'):
+ if page['ownerID'] == userData['ID']:
+ mypages.append(page)
+ ret_mypages = mypages.copy()
+ if autogroup:
+ ret_mypages = list()
+
+ MaxIndex = len(mypages) - 1
+ Index = 0
+ for page in mypages:
+ pageGr = list()
+ for _ in range(6):
+ if Index <= MaxIndex:
+ pageGr.append(mypages[Index])
+ Index += 1
+ ret_mypages.append(pageGr)
+ return json.dumps({
+ "response": ret_mypages
+ }, indent="\t", ensure_ascii=False)
+
+ if method_group == 'confirmation':
+ if method == 'start':
+ email = request.args.get('email', default=None)
+ code = 1
+ warn_text = 'null'
+ if email is None:
+ return '{"error": "email address has been missed"}'
+ if email not in [mail for mail in SQLEasy.compareKey(database.getBase('Users'), 'email')]:
+ return '{"error": "this email not founded"}'
+ if SQLEasy.compareKey(database.getBase('Users'), 'email')[email]['mail_confirm']:
+ return '{"error": "this email was been activated"}'
+ if SQLEasy.compareKey(database.getBase('Users'), 'email')[email]['sended']:
+ code = 2
+ warn_text = '"Message was been sended, please, check your mailbox"'
+
+ verificationCode = SQLEasy.compareKey(database.getBase('Users'), 'email')[email]['verif_code']
+ try:
+ mailObject.send('Код подтверждения', f"Код подтверждения: {verificationCode}", str(email))
+ print('sended to %s' % email)
+ database.setItem(
+ 'sended',
+ 1,
+ 'email',
+ email,
+ DatabaseName='Users'
+ )
+ return '{"response": 1, "warning": %s}' % warn_text
+ except Exception as exc:
+ print('FAILED:\n %s' % traceback.format_exc())
+ return '{"error": "failed send message"}'
+
+ return '{"error": "unknown method"}'
+ return '{"error": "unknown method group"}'
+
+@app.route('/index.')
+def trueINDEX(jap):
+ return redirect("/", code=302)
+
+@app.route('/index')
+def trueINDEX_noRasz():
+ return redirect("/", code=302)
+
+
+
+if __name__ == '__main__':
+ app.run(port=PORT, host=HOST) # Сменить хост
\ No newline at end of file
diff --git a/static/button.js b/static/button.js
new file mode 100644
index 0000000..efcaa44
--- /dev/null
+++ b/static/button.js
@@ -0,0 +1,58 @@
+var type = "auth";
+function buton_regAuth(){
+ if(type == "auth") type = "reg";
+ else type = "auth";
+ if(type == "auth") document.getElementById("authwin").innerHTML = " \n Авторизация \n e-mail:
\n password:
\n
\n \n Регистрация "
+ else document.getElementById("authwin").innerHTML = " \n Регистрация \n e-mail:
\n повторите e-mail:
\n password:
\n повторите password:
\n
\n \n Авторизация "
+}
+
+function confirmation_mail(mail_adress) {
+ var codeConfirmation = "\n \n Введите код \n
\n Если письмо не пришло , то проверьте папку \"Спам\" , проверьте ваш чёрный список на наличие почтового адреса бота, проверьте правильность введённых данных при регистрации.
\n
\n \n "
+
+ var GET_Request = new XMLHttpRequest();
+ GET_Request.open("GET", "http://127.0.0.1:8080/api/confirmation/start?email=" + mail_adress, true);
+ GET_Request.onload = function (){
+ var content = GET_Request.responseText;
+ document.getElementById("authwin").innerHTML = codeConfirmation;
+ }
+ GET_Request.send(null);
+}
+
+function get_cookies(){
+ var cookie_f = document.cookie;
+ cookies = cookie_f.split('; ');
+ returnCookie = {};
+
+ cookies.forEach(function(item, i, cookies) {
+ ItemArray = item.split('=');
+ returnCookie[ItemArray[0]] = returnCookie[ItemArray[1]];
+ });
+
+ return returnCookie;
+}
+
+function update(){
+ var cookies = get_cookies();
+ var xhr = new XMLHttpRequest();
+
+ xhr.open('GET', "http://127.0.0.1:8080/api/user/get_pages?autogroup=1&token="
+ + cookies.token, false);
+
+ xhr.send();
+ if (xhr.status != 200) {
+ var ok = 'ok';
+ } else {
+ var values = JSON.parse(xhr.responseText);
+ var groups = values.response;
+ var retV = '';
+ groups.forEach(function(group, i, groups) {
+ var item = '';
+ group.forEach(function(cellContent, i, group) {
+ item += `${cellContent.title}
\n`;
+ });
+ retV += `${item}
\n`;
+ });
+ document.getElementById("field").innerHTML = retV;
+
+ }
+}
\ No newline at end of file
diff --git a/static/icon.ico b/static/icon.ico
new file mode 100644
index 0000000..aa0133f
Binary files /dev/null and b/static/icon.ico differ
diff --git a/static/script.js b/static/script.js
new file mode 100644
index 0000000..a045157
--- /dev/null
+++ b/static/script.js
@@ -0,0 +1,23 @@
+var type = "auth";
+function buton_regAuth(){
+ if(type == "auth") type = "reg";
+ else type = "auth";
+ if(type == "auth") document.getElementById("authwin").innerHTML = " \n Авторизация \n e-mail:
\n password:
\n
\n \n Регистрация "
+ else document.getElementById("authwin").innerHTML = " \n Регистрация \n e-mail:
\n повторите e-mail:
\n password:
\n повторите password:
\n
\n \n Авторизация "
+}
+
+function confirmation_mail(mail_adress) {
+ var codeConfirmation = "\n \n Введите код \n
\n Если письмо не пришло , то проверьте папку \"Спам\" , проверьте ваш чёрный список на наличие почтового адреса бота, проверьте правильность введённых данных при регистрации.
\n
\n \n "
+
+ var GET_Request = new XMLHttpRequest();
+ GET_Request.open("GET", "http://127.0.0.1:8080/api/confirmation/start?email=" + mail_adress, true);
+ GET_Request.onload = function (){
+ var content = GET_Request.responseText;
+ document.getElementById("authwin").innerHTML = codeConfirmation;
+ }
+ GET_Request.send(null);
+
+
+}
+
+function off_pass(){}
\ No newline at end of file
diff --git a/static/scripts.js b/static/scripts.js
new file mode 100644
index 0000000..a045157
--- /dev/null
+++ b/static/scripts.js
@@ -0,0 +1,23 @@
+var type = "auth";
+function buton_regAuth(){
+ if(type == "auth") type = "reg";
+ else type = "auth";
+ if(type == "auth") document.getElementById("authwin").innerHTML = " \n Авторизация \n e-mail:
\n password:
\n
\n \n Регистрация "
+ else document.getElementById("authwin").innerHTML = " \n Регистрация \n e-mail:
\n повторите e-mail:
\n password:
\n повторите password:
\n
\n \n Авторизация "
+}
+
+function confirmation_mail(mail_adress) {
+ var codeConfirmation = "\n \n Введите код \n
\n Если письмо не пришло , то проверьте папку \"Спам\" , проверьте ваш чёрный список на наличие почтового адреса бота, проверьте правильность введённых данных при регистрации.
\n
\n \n "
+
+ var GET_Request = new XMLHttpRequest();
+ GET_Request.open("GET", "http://127.0.0.1:8080/api/confirmation/start?email=" + mail_adress, true);
+ GET_Request.onload = function (){
+ var content = GET_Request.responseText;
+ document.getElementById("authwin").innerHTML = codeConfirmation;
+ }
+ GET_Request.send(null);
+
+
+}
+
+function off_pass(){}
\ No newline at end of file
diff --git a/static/scripts/button.js b/static/scripts/button.js
new file mode 100644
index 0000000..18837b2
--- /dev/null
+++ b/static/scripts/button.js
@@ -0,0 +1,9 @@
+var type = "auth";
+function buton_regAuth(){
+ console.log("Poszel nahui")
+ if(type == "auth") type = "reg";
+ else type = "auth";
+
+ if(type == "auth") document.getElementById("authwin").innerHTML = " \n Авторизация \n e-mail:
\n password:
\n
\n \n Регистрация "
+ else document.getElementById("authwin").innerHTML = " \n Регистрация \n e-mail:
\n повторите e-mail:
\n password:
\n повторите password:
\n
\n \n Авторизация "
+}
\ No newline at end of file
diff --git a/static/source_test_20.js b/static/source_test_20.js
new file mode 100644
index 0000000..67433d1
--- /dev/null
+++ b/static/source_test_20.js
@@ -0,0 +1,81 @@
+var type = "auth";
+
+function timeConverter(UNIX_timestamp){
+ var a = new Date(UNIX_timestamp * 1000);
+ var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
+ var year = a.getFullYear();
+ var month = months[a.getMonth()];
+ var date = a.getDate();
+ var hour = a.getHours();
+ var min = a.getMinutes();
+ var sec = a.getSeconds();
+ var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec ;
+ return time;
+}
+
+function buton_regAuth(){
+ if(type == "auth") type = "reg";
+ else type = "auth";
+ if(type == "auth") document.getElementById("authwin").innerHTML = " \n Авторизация \n e-mail:
\n password:
\n
\n \n Регистрация "
+ else document.getElementById("authwin").innerHTML = " \n Регистрация \n e-mail:
\n повторите e-mail:
\n password:
\n повторите password:
\n
\n \n Авторизация "
+}
+
+function confirmation_mail(mail_adress) {
+ var codeConfirmation = "\n \n Введите код \n
\n Если письмо не пришло , то проверьте папку \"Спам\" , проверьте ваш чёрный список на наличие почтового адреса бота, проверьте правильность введённых данных при регистрации.
\n
\n \n "
+
+ var GET_Request = new XMLHttpRequest();
+ GET_Request.open("GET", "http://127.0.0.1:8080/api/confirmation/start?email=" + mail_adress, true);
+ GET_Request.onload = function (){
+ var content = GET_Request.responseText;
+ document.getElementById("authwin").innerHTML = codeConfirmation;
+ }
+ GET_Request.send(null);
+}
+
+function get_cookies(){
+ var cookie_f = document.cookie;
+ var cookies = cookie_f.split('; ');
+ // alert(cookie_f);
+ var returnCookie = {};
+
+ cookies.forEach(function(item, i, cookies) {
+ console.log(item);
+ ItemArray = item.split('=');
+ console.log(ItemArray);
+ console.log(ItemArray[0]);
+ console.log(ItemArray[1]);
+ returnCookie[ItemArray[0]] = ItemArray[1];
+ });
+ console.log(returnCookie)
+
+ return returnCookie;
+}
+
+function update(){
+ var cookies = get_cookies();
+ var xhr = new XMLHttpRequest();
+
+ xhr.open('GET', "http://127.0.0.1:8080/api/user/get_pages?autogroup=1&token=" + cookies.token, false);
+ // alert('ok');
+
+ xhr.send();
+ if (xhr.status != 200) {
+ var ok = 'ok';
+ } else {
+ var values = JSON.parse(xhr.responseText);
+ // alert(xhr.responseText);
+ var groups = values.response;
+ var retV = '';
+ groups.forEach(function(group, i, groups) {
+ var item = '';
+ var clocker = 0;
+ group.forEach(function(cellContent, i, group) {
+ clocker += 1;
+ item += `${cellContent.title} Создано: ${timeConverter(cellContent.created)} Отредактирован: ${timeConverter(cellContent.edited)}
\n`;
+ });
+ retV += `${item}
\n`;
+ });
+ retV += "";
+ document.getElementById("field").innerHTML = retV;
+ }
+}
\ No newline at end of file
diff --git a/static/sources/icon.ico b/static/sources/icon.ico
new file mode 100644
index 0000000..aa0133f
Binary files /dev/null and b/static/sources/icon.ico differ