V4.0.0 Release Open Source Version

This commit is contained in:
Bigsk 2022-10-11 00:46:59 +08:00
parent c167152654
commit 91a942a59e
5 changed files with 542 additions and 0 deletions

115
404.html Normal file
View File

@ -0,0 +1,115 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ghink Universe - 404</title>
<link rel="icon" href="https://cdn.ghink.net/image/ghink/favicon.ico" type="image/x-icon">
<style>
body {
background-color: #2F3242;
}
svg {
position: absolute;
top: 50%;
left: 50%;
margin-top: -250px;
margin-left: -400px;
}
.message-box {
height: 200px;
width: 380px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: 50px;
color: #FFF;
font-family: Roboto;
font-weight: 300;
}
.message-box h1 {
font-size: 60px;
line-height: 46px;
margin-bottom: 40px;
}
.buttons-con .action-link-wrap {
margin-top: 40px;
}
.buttons-con .action-link-wrap a {
background: #68c950;
padding: 8px 25px;
border-radius: 4px;
color: #FFF;
font-weight: bold;
font-size: 14px;
transition: all 0.3s linear;
cursor: pointer;
text-decoration: none;
margin-right: 10px
}
.buttons-con .action-link-wrap a:hover {
background: #5A5C6C;
color: #fff;
}
#Polygon-1 , #Polygon-2 , #Polygon-3 , #Polygon-4 , #Polygon-4, #Polygon-5 {
animation: float 1s infinite ease-in-out alternate;
}
#Polygon-2 {
animation-delay: .2s;
}
#Polygon-3 {
animation-delay: .4s;
}
#Polygon-4 {
animation-delay: .6s;
}
#Polygon-5 {
animation-delay: .8s;
}
@keyframes float {
100% {
transform: translateY(20px);
}
}
@media (max-width: 450px) {
svg {
position: absolute;
top: 50%;
left: 50%;
margin-top: -250px;
margin-left: -190px;
}
.message-box {
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -190px;
text-align: center;
}
}
</style>
</head>
<body>
<svg width="380px" height="500px" viewBox="0 0 837 1045" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<path d="M353,9 L626.664028,170 L626.664028,487 L353,642 L79.3359724,487 L79.3359724,170 L353,9 Z" id="Polygon-1" stroke="#007FB2" stroke-width="6" sketch:type="MSShapeGroup"></path>
<path d="M78.5,529 L147,569.186414 L147,648.311216 L78.5,687 L10,648.311216 L10,569.186414 L78.5,529 Z" id="Polygon-2" stroke="#EF4A5B" stroke-width="6" sketch:type="MSShapeGroup"></path>
<path d="M773,186 L827,217.538705 L827,279.636651 L773,310 L719,279.636651 L719,217.538705 L773,186 Z" id="Polygon-3" stroke="#795D9C" stroke-width="6" sketch:type="MSShapeGroup"></path>
<path d="M639,529 L773,607.846761 L773,763.091627 L639,839 L505,763.091627 L505,607.846761 L639,529 Z" id="Polygon-4" stroke="#F2773F" stroke-width="6" sketch:type="MSShapeGroup"></path>
<path d="M281,801 L383,861.025276 L383,979.21169 L281,1037 L179,979.21169 L179,861.025276 L281,801 Z" id="Polygon-5" stroke="#36B455" stroke-width="6" sketch:type="MSShapeGroup"></path>
</g>
</svg>
<div class="message-box">
<h1>404</h1>
<p>Page not found 页面找不到了</p>
<div class="buttons-con">
<div class="action-link-wrap">
<a onclick="history.back(-1)" class="link-button link-back-button">Go Back 返回</a>
<a href="https://www.ghink.net" class="link-button">Go Home 返回主页</a>
</div>
</div>
</div>
</body>
</html>

16
config.json Normal file
View File

@ -0,0 +1,16 @@
{
"DEBUG": false,
"DB": {
"host": "localhost",
"user": "root",
"password": "root",
"database": "short_link"
},
"KEYS": [
"Example"
],
"LISTEN": [
"0.0.0.0",
50002
]
}

226
index.html Normal file

File diff suppressed because one or more lines are too long

163
main.py Normal file
View File

@ -0,0 +1,163 @@
import time, random, json, threading
import pymysql
from flask import Flask, request, redirect
with open("config.json", "r") as fb:
config = json.loads(fb.read())
DB = config["DB"]
KEYS = config["KEYS"]
LISTEN = config["LISTEN"]
DEBUG = config["DEBUG"]
app = Flask("Ghink Short Link Service")
db = pymysql.connect(
host=DB["host"],
user=DB["user"],
password=DB["password"],
database=DB["database"]
)
field_map = {
'A': 0, 'a': 1, 'B': 2, 'b': 3,
'C': 4, 'c': 5, 'D': 6, 'd': 7,
'1': 8, 'E': 9, 'e': 10, 'F': 11,
'f': 12, 'G': 13, 'g': 14, 'H': 15,
'h': 16, '2': 17, 'I': 18, 'i': 19,
'J': 20, 'j': 21, 'K': 22, 'k': 23,
'L': 24, 'l': 25, '3': 26, 'M': 27,
'm': 28, 'N': 29, 'n': 30, 'O': 31,
'o': 32, 'P': 33, 'p': 34, '4': 35,
'Q': 36, 'q': 37, 'R': 38, 'r': 39,
'S': 40, 's': 41, 'T': 42, 't': 43,
'5': 44, 'U': 45, 'u': 46, 'V': 47,
'v': 48, 'W': 49, 'w': 50, 'X': 51,
'x': 52, '6': 53, 'Y': 54, 'y': 55,
'Z': 56, 'z': 57, '7': 58, '8': 59,
'9': 60, '0': 61}
@app.route("/", methods=["GET"])
def index():
with open("index.html", "r", encoding="utf-8") as fb:
return fb.read()
@app.route("/<string:link_id>", methods=["GET"])
def route(link_id: str):
global db
for char in link_id:
if char not in tuple(field_map.keys()):
return redirect("https://www.ghink.net")
link_id_converted = 0
for i in range(len(link_id)):
link_id_converted += field_map[link_id[::-1][i]] * 56 ** i
try:
db.ping()
except pymysql.err.InterfaceError:
db = pymysql.connect(
host=DB["host"],
user=DB["user"],
password=DB["password"],
database=DB["database"]
)
cursor = db.cursor()
cursor.execute('SELECT link, validity FROM links WHERE id=%s', link_id_converted)
db.commit()
link = cursor.fetchone()
if link is None or link[0] is None:
with open("404.html", "r", encoding="utf-8") as fb:
return fb.read(), 404
if link[1] is not None and link[1] < time.time():
remove_thread = threading.Thread(target=remove_link, args=(link_id_converted,))
remove_thread.start()
with open("404.html", "r", encoding="utf-8") as fb:
return fb.read(), 404
return redirect(link[0])
@app.route("/", methods=["POST"])
def add():
global db
key = request.form.get("key")
link = request.form.get("link")
validity = request.form.get("validity")
# Judge whether fields are empty
if key == "" or link == "":
return json.dumps({"ok": False, "message": "bad field(s)", "id": ""})
# No access
if key not in KEYS:
return json.dumps({"ok": False, "message": "forbidden", "id": ""})
# Check validity
if validity:
if validity.isdecimal() and int(validity) > time.time():
validity = int(validity)
else:
return json.dumps({"ok": False, "message": "bad field(s)", "id": ""})
else:
validity = None
# Random
while True:
link_id_random = ''.join(random.sample(tuple(field_map.keys()), 6))
link_id_converted = 0
for i in range(len(link_id_random)):
link_id_converted += field_map[link_id_random[::-1][i]] * 56 ** i
# Get Cursor
try:
db.ping()
except pymysql.err.InterfaceError:
db = pymysql.connect(
host=DB["host"],
user=DB["user"],
password=DB["password"],
database=DB["database"]
)
cursor = db.cursor()
cursor.execute('SELECT link FROM links WHERE id=%s', link_id_converted)
db.commit()
link_selected = cursor.fetchone()
if link_selected is None:
break
# Insert
cursor.execute("INSERT INTO `links` VALUES (%s, %s, %s)", [link_id_converted, link, validity])
db.commit()
return json.dumps({"ok": True, "message": "successful", "id": link_id_random})
@app.route("/", methods=["PATCH"])
def reload():
global config, DB, KEYS, LISTEN, DEBUG
with open("config.json", "r") as fb:
config = json.loads(fb.read())
DB = config["DB"]
KEYS = config["KEYS"]
LISTEN = config["LISTEN"]
DEBUG = config["DEBUG"]
return json.dumps({"ok": True, "message": "successful"})
def remove_link(id):
global db
# Get Cursor
try:
db.ping()
except pymysql.err.InterfaceError:
db = pymysql.connect(
host=DB["host"],
user=DB["user"],
password=DB["password"],
database=DB["database"]
)
cursor = db.cursor()
cursor.execute('DELETE FROM links WHERE id=%s', id)
db.commit()
if __name__ == "__main__":
app.run(LISTEN[0], LISTEN[1], DEBUG)
db.close()

22
short_link.sql Normal file
View File

@ -0,0 +1,22 @@
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
CREATE TABLE `links` (
`id` bigint(20) NOT NULL,
`link` text NOT NULL,
`validity` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `links`
ADD PRIMARY KEY (`id`);
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;