This commit is contained in:
SuperSonic 2020-01-25 20:32:24 +08:00
parent a94b739082
commit 4737eeba9b
9 changed files with 420 additions and 178 deletions

View file

@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
"""
Yuuki_Libs
(c) 2019 Star Inc.
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""
__all__ = ["reader", "server"]

View file

@ -11,13 +11,12 @@ import json
import random
import time
from .reader import Yuuki_WebDataReader
from flask import Flask, render_template, Response, request, redirect
from flask_bootstrap import Bootstrap
from gevent.pywsgi import WSGIServer
from .reader import Yuuki_WebDataReader
wa_app = Flask(__name__)
Yuuki_Handle = None
Yuuki_DataHandle = None
@ -25,6 +24,7 @@ Yuuki_DataHandle = None
passports = []
password = str(hash(random.random()))
class Yuuki_WebAdmin:
def __init__(self, Yuuki):
global Yuuki_Handle, Yuuki_DataHandle
@ -40,8 +40,7 @@ class Yuuki_WebAdmin:
if "yuuki_admin" in request.cookies:
if request.cookies["yuuki_admin"] in passports:
return render_template(
'manage.html',
name=Yuuki_Handle.YuukiConfigs["name"],
'manage/index.html',
version=Yuuki_Handle.YuukiConfigs["version"],
LINE_Media_server=Yuuki_Handle.LINE_Media_server,
profileName=Yuuki_Handle.profile.displayName,
@ -62,6 +61,54 @@ class Yuuki_WebAdmin:
version=Yuuki_Handle.YuukiConfigs["version"]
)
@staticmethod
@wa_app.route("/groups")
def groups():
if "yuuki_admin" in request.cookies:
if request.cookies["yuuki_admin"] in passports:
return render_template(
'manage/groups.html'
)
response = redirect("/")
response.set_cookie(
key='yuuki_admin',
value='',
expires=0
)
return response
@staticmethod
@wa_app.route("/helpers")
def helpers():
if "yuuki_admin" in request.cookies:
if request.cookies["yuuki_admin"] in passports:
return render_template(
'manage/groups.html'
)
response = redirect("/")
response.set_cookie(
key='yuuki_admin',
value='',
expires=0
)
return response
@staticmethod
@wa_app.route("/settings")
def settings():
if "yuuki_admin" in request.cookies:
if request.cookies["yuuki_admin"] in passports:
return render_template(
'manage/groups.html'
)
response = redirect("/")
response.set_cookie(
key='yuuki_admin',
value='',
expires=0
)
return response
@staticmethod
@wa_app.route("/verify", methods=['GET', 'POST'])
def verify():
@ -77,7 +124,6 @@ class Yuuki_WebAdmin:
result = {"status": 401}
return Response(json.dumps(result), mimetype='application/json')
@staticmethod
@wa_app.route("/logout")
def logout():
@ -105,6 +151,11 @@ class Yuuki_WebAdmin:
result = Yuuki_DataHandle.get_all_logs()
return Response(json.dumps(result), mimetype='application/json')
@staticmethod
@wa_app.route("/api/i")
def i():
return Yuuki_Handle.YuukiConfigs["name"]
@staticmethod
def set_password(code):
global password

View file

@ -0,0 +1,33 @@
(function () {
$.get("/api/i", function (data) {
name = data;
});
var page_list = {
"/": "Dashboard",
"/groups": "Groups",
"/helpers": "Helpers",
"/settings": "Settings"
};
var nav_list = "";
for (var p_key in page_list) {
if (window.location.pathname === p_key)
nav_list += "<a class=\"nav-link active\" href=\"" + p_key + "\">" + page_list[p_key] + "</a>";
else
nav_list += "<a class=\"nav-link js-lookforward\" data-transition-enter=\"slideleft\" href=\"" + p_key + "\">" + page_list[p_key] + "</a>";
}
var html_text =
"<nav class=\"navbar navbar-expand-md navbar-dark fixed-top bg-dark\">" +
"<a class=\"navbar-brand\" href=\"/\">" + name + " - WebAdmin</a>" +
"<button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarCollapse\"aria-controls=\"navbarCollapse\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">" +
"<span class=\"navbar-toggler-icon\"></span>" +
"</button>" +
"<div class=\"collapse navbar-collapse\" id=\"navbarCollapse\">" +
"<ul class=\"navbar-nav mr-auto\"></ul>" +
"<a href=\"/logout\"><button class=\"btn btn-outline-success my-2 my-sm-0\">Logout</button></a>" +
"</div>" +
"</nav>" +
"<div class=\"nav-scroller bg-white shadow-sm\">" +
"<nav class=\"nav nav-underline\">" + nav_list + "</nav>" +
"</div>";
$("#header").html(html_text);
})();

View file

@ -0,0 +1,127 @@
body {
padding-top: 5rem;
}
.starter-template {
padding: 3rem 1.5rem;
text-align: center;
}
.damage {
color: #ff0000;
}
.password_box {
margin: 0;
position: absolute;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
}
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
html,
body {
overflow-x: hidden;
/* Prevent scroll on narrow devices */
}
body {
padding-top: 56px;
}
@media (max-width: 991.98px) {
.offcanvas-collapse {
position: fixed;
top: 56px;
/* Height of navbar */
bottom: 0;
left: 100%;
width: 100%;
padding-right: 1rem;
padding-left: 1rem;
overflow-y: auto;
visibility: hidden;
background-color: #343a40;
transition: visibility .3s ease-in-out, -webkit-transform .3s ease-in-out;
transition: transform .3s ease-in-out, visibility .3s ease-in-out;
transition: transform .3s ease-in-out, visibility .3s ease-in-out, -webkit-transform .3s ease-in-out;
}
.offcanvas-collapse.open {
visibility: visible;
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
}
.nav-scroller {
position: relative;
z-index: 2;
height: 2.75rem;
overflow-y: hidden;
}
.nav-scroller .nav {
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
padding-bottom: 1rem;
margin-top: -1px;
overflow-x: auto;
color: rgba(255, 255, 255, .75);
text-align: center;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
.nav-underline .nav-link {
padding-top: .75rem;
padding-bottom: .75rem;
font-size: .875rem;
color: #6c757d;
}
.nav-underline .nav-link:hover {
color: #007bff;
}
.nav-underline .active {
font-weight: 500;
color: #343a40;
}
.text-white-50 {
color: rgba(255, 255, 255, .5);
}
.bg-purple {
background-color: #000000;
}
.lh-100 {
line-height: 1;
}
.lh-125 {
line-height: 1.25;
}
.lh-150 {
line-height: 1.5;
}

View file

@ -0,0 +1,18 @@
$(function () {
$('form.login-box').on('submit', function (e) {
$.ajax({
type: "POST",
url: "/verify",
data: $(this).serialize(),
success: function (data) {
if (data.status == 200) {
Cookies.set('yuuki_admin', data.session);
location.reload();
} else {
$(".status").text("Wrong password")
}
}
});
e.preventDefault();
});
});

View file

@ -8,128 +8,9 @@
<!-- Bootstrap CSS -->
{{ bootstrap.load_css() }}
<link rel="stylesheet" href="https://unpkg.com/lookforward@0.1.1/css/lookforward.min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}" />
<style>
body {
padding-top: 5rem;
}
.starter-template {
padding: 3rem 1.5rem;
text-align: center;
}
.damage {
color: #ff0000;
}
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
html,
body {
overflow-x: hidden;
/* Prevent scroll on narrow devices */
}
body {
padding-top: 56px;
}
@media (max-width: 991.98px) {
.offcanvas-collapse {
position: fixed;
top: 56px;
/* Height of navbar */
bottom: 0;
left: 100%;
width: 100%;
padding-right: 1rem;
padding-left: 1rem;
overflow-y: auto;
visibility: hidden;
background-color: #343a40;
transition: visibility .3s ease-in-out, -webkit-transform .3s ease-in-out;
transition: transform .3s ease-in-out, visibility .3s ease-in-out;
transition: transform .3s ease-in-out, visibility .3s ease-in-out, -webkit-transform .3s ease-in-out;
}
.offcanvas-collapse.open {
visibility: visible;
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
}
.nav-scroller {
position: relative;
z-index: 2;
height: 2.75rem;
overflow-y: hidden;
}
.nav-scroller .nav {
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
padding-bottom: 1rem;
margin-top: -1px;
overflow-x: auto;
color: rgba(255, 255, 255, .75);
text-align: center;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
.nav-underline .nav-link {
padding-top: .75rem;
padding-bottom: .75rem;
font-size: .875rem;
color: #6c757d;
}
.nav-underline .nav-link:hover {
color: #007bff;
}
.nav-underline .active {
font-weight: 500;
color: #343a40;
}
.text-white-50 {
color: rgba(255, 255, 255, .5);
}
.bg-purple {
background-color: #000000;
}
.lh-100 {
line-height: 1;
}
.lh-125 {
line-height: 1.25;
}
.lh-150 {
line-height: 1.5;
}
</style>
<title>Star Yuuki BOT - WebAdmin</title>
</head>
@ -153,18 +34,14 @@
<div class="nav-scroller bg-white shadow-sm">
<nav class="nav nav-underline">
<a class="nav-link active" href="#index">Dashboard</a>
<a class="nav-link" href="#friends">
Friends
<a class="nav-link active" href="/">Dashboard</a>
<a class="nav-link js-lookforward" data-transition-enter="slideup" data-transition-leave="slidedown" href="/groups">Groups
<span class="badge badge-pill bg-light align-text-bottom">27</span>
</a>
<a class="nav-link" href="#groups">Groups
<a class="nav-link js-lookforward" data-transition-enter="slideup" data-transition-leave="slidedown" href="/helpers">Helpers
<span class="badge badge-pill bg-light align-text-bottom">27</span>
</a>
<a class="nav-link" href="#helpers">Helpers
<span class="badge badge-pill bg-light align-text-bottom">27</span>
</a>
<a class="nav-link" href="#settings">Settings</a>
<a class="nav-link js-lookforward" data-transition-enter="slideup" data-transition-leave="slidedown" href="/settings">Settings</a>
</nav>
</div>
@ -282,10 +159,14 @@
<a href="/logs" target="_blank">All updates</a>
</small>
</div>
</div>
</main>
<!-- Optional JavaScript -->
{{ bootstrap.load_js() }}
<script src="https://unpkg.com/lookforward@0.1.1/js/lookforward.min.js">
new LookForward('.js-lookforward');
</script>
</body>
</html>

View file

@ -8,29 +8,7 @@
<!-- Bootstrap CSS -->
{{ bootstrap.load_css() }}
<style>
body {
padding-top: 5rem;
}
.starter-template {
padding: 3rem 1.5rem;
text-align: center;
}
.damage {
color: #ff0000;
}
.password_box {
margin: 0;
position: absolute;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
}
</style>
<link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}" />
<title>Star Yuuki BOT - WebAdmin</title>
</head>
@ -75,26 +53,7 @@
<!-- Optional JavaScript -->
{{ bootstrap.load_js() }}
<script src="https://cdn.jsdelivr.net/npm/js-cookie@beta/dist/js.cookie.min.js"></script>
<script>
$(function () {
$('form.login-box').on('submit', function (e) {
$.ajax({
type: "POST",
url: "/verify",
data: $(this).serialize(),
success: function (data) {
if (data.status == 200) {
Cookies.set('yuuki_admin', data.session);
location.reload();
} else {
$(".status").text("Wrong password")
}
}
});
e.preventDefault();
});
});
</script>
<script src="{{ url_for('static', filename='verify.js') }}"></script>
</body>
</html>

View file

@ -0,0 +1,78 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
{{ bootstrap.load_css() }}
<link rel="stylesheet" href="https://unpkg.com/lookforward@0.1.1/css/lookforward.min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}" />
<title>Star Yuuki BOT - WebAdmin</title>
</head>
<body>
{% from 'bootstrap/nav.html' import render_nav_item %}
<div id="header"></div>
<main role="main" class="container">
<div class="my-3 p-3 bg-white rounded shadow-sm">
<h6 class="border-bottom border-gray pb-2 mb-0">Recent updates</h6>
<div class="media text-muted pt-3">
<svg class="bd-placeholder-img mr-2 rounded" width="32" height="32" xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 32x32">
<title>Event</title>
<rect width="100%" height="100%" fill="#007bff" /><text x="50%" y="50%" fill="#007bff"
dy=".3em">32x32</text>
</svg>
<p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
<strong class="d-block text-gray-dark">[Kick Event]</strong>
Yuuki
</p>
</div>
<div class="media text-muted pt-3">
<svg class="bd-placeholder-img mr-2 rounded" width="32" height="32" xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 32x32">
<title>Event</title>
<rect width="100%" height="100%" fill="#e83e8c" /><text x="50%" y="50%" fill="#e83e8c"
dy=".3em">32x32</text>
</svg>
<p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
<strong class="d-block text-gray-dark">[Cancel Event]</strong>
Yuuki
</p>
</div>
<div class="media text-muted pt-3">
<svg class="bd-placeholder-img mr-2 rounded" width="32" height="32" xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 32x32">
<title>Event</title>
<rect width="100%" height="100%" fill="#6f42c1" /><text x="50%" y="50%" fill="#6f42c1"
dy=".3em">32x32</text>
</svg>
<p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
<strong class="d-block text-gray-dark">[Join Event]</strong>
Yuuki
</p>
</div>
<small class="d-block text-right mt-3">
<a href="/logs" target="_blank">All updates</a>
</small>
</div>
</div>
</main>
<!-- Optional JavaScript -->
{{ bootstrap.load_js() }}
<script src="{{ url_for('static', filename='header.js') }}"></script>
<script src="https://unpkg.com/lookforward@0.1.1/js/lookforward.min.js"></script>
<script>
new LookForward('.js-lookforward');
</script>
</body>
</html>

View file

@ -0,0 +1,86 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
{{ bootstrap.load_css() }}
<link rel="stylesheet" href="https://unpkg.com/lookforward@0.1.1/css/lookforward.min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}" />
<title>Star Yuuki BOT - WebAdmin</title>
</head>
<body>
{% from 'bootstrap/nav.html' import render_nav_item %}
<div id="header"></div>
<main role="main" class="container">
<div class="d-flex align-items-center p-3 my-3 text-white-50 bg-purple rounded shadow-sm">
<img class="mr-3" src="{{ LINE_Media_server}}/{{pictureStatus }}" alt="" width="48" height="48">
<div class="lh-100">
<h6 class="mb-0 text-white lh-100">{{ profileName }}</h6>
<small>on {{ name }} {{ version }}</small>
</div>
</div>
<div class="my-3 p-3 bg-white rounded shadow-sm">
<h6 class="border-bottom border-gray pb-2 mb-0">Recent updates</h6>
<div class="media text-muted pt-3">
<svg class="bd-placeholder-img mr-2 rounded" width="32" height="32" xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 32x32">
<title>Event</title>
<rect width="100%" height="100%" fill="#007bff" /><text x="50%" y="50%" fill="#007bff"
dy=".3em">32x32</text>
</svg>
<p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
<strong class="d-block text-gray-dark">[Kick Event]</strong>
Yuuki
</p>
</div>
<div class="media text-muted pt-3">
<svg class="bd-placeholder-img mr-2 rounded" width="32" height="32" xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 32x32">
<title>Event</title>
<rect width="100%" height="100%" fill="#e83e8c" /><text x="50%" y="50%" fill="#e83e8c"
dy=".3em">32x32</text>
</svg>
<p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
<strong class="d-block text-gray-dark">[Cancel Event]</strong>
Yuuki
</p>
</div>
<div class="media text-muted pt-3">
<svg class="bd-placeholder-img mr-2 rounded" width="32" height="32" xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 32x32">
<title>Event</title>
<rect width="100%" height="100%" fill="#6f42c1" /><text x="50%" y="50%" fill="#6f42c1"
dy=".3em">32x32</text>
</svg>
<p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
<strong class="d-block text-gray-dark">[Join Event]</strong>
Yuuki
</p>
</div>
<small class="d-block text-right mt-3">
<a href="/logs" target="_blank">All updates</a>
</small>
</div>
</div>
</main>
<!-- Optional JavaScript -->
{{ bootstrap.load_js() }}
<script src="{{ url_for('static', filename='header.js') }}"></script>
<script src="https://unpkg.com/lookforward@0.1.1/js/lookforward.min.js"></script>
<script>
new LookForward('.js-lookforward');
</script>
</body>
</html>