删除历史版本, 初始化仓库

This commit is contained in:
MarkusJoe
2022-06-02 18:50:09 +08:00
commit 91c9c2ba7c
37 files changed
+1773

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/3/25
# @File Name: __init__.py
import os
from flask import Flask
from flask_sslify import SSLify
from .main import main as main_blueprint
from .api import api as api_blueprint
from .config import config
from .utils.password import generate_pwd
def create_app(config_name):
"""
创建 app
:param config_name:
:return:
"""
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
if app.config['SSL_REDIRECT']:
SSLify(app)
app.register_blueprint(main_blueprint)
app.register_blueprint(api_blueprint, url_prefix='/api/v1/')
access_key = os.getenv('ACCESS_KEY')
secret = app.config['SECRET_KEY']
try:
if not access_key and not secret:
access_key = generate_pwd(16)
elif not access_key and secret:
access_key = secret
finally:
os.environ['ACCESS_KEY'] = access_key
app.logger.info('访问密钥: {}'.format(access_key))
return app
__all__ = [
'db',
'main',
'tests',
'utils',
'create_app'
]
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/4/9
# @File Name: __init__.py.py
from flask import Blueprint
api = Blueprint('api', __name__)
from . import views, errors
__all__ = [
'api',
'views',
'errors'
]
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: Pycharm
# @Create Time: 2022/5/2
# @File Name: auth.py
import os
from flask import request
from flask_httpauth import HTTPTokenAuth
auth = HTTPTokenAuth()
@auth.verify_token
def verify_token(token):
secret_key = os.getenv('ACCESS_KEY')
key = request.args.get('key')
if token or key == secret_key:
return True
elif (token == 'unittest' or
key == 'unittest') and \
'system' in request.path.split('/'): # 限定在system这个接口使用unittest密钥获取数据
return True
return False
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/4/9
# @File Name: errors.py
from . import api
from .auth import auth
from flask import jsonify
@api.errorhandler(403)
@auth.error_handler
def forbidden(e):
return jsonify(
{
'code': 403,
'msg': 'API: Permission Denied.',
'data': None
}
), 403
@api.errorhandler(404)
def page_not_found(e):
return jsonify(
{
'code': 404,
'msg': 'API: Page Not Found.',
'data': None
}
), 404
@api.errorhandler(500)
def internal_server_error(e):
return jsonify(
{
'code': 500,
'msg': 'API: Internal Server Error.',
'data': None
}
), 500
+172
View File
@@ -0,0 +1,172 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/4/9
# @File Name: views.py
import sys
import psutil
import platform
from flask import jsonify
from flask import request
from flask import send_file
from ..db.db import SQLite as db
from . import api
from .auth import auth
@api.route('/test/', methods=['GET', 'POST'])
def test_api():
"""
测试专用接口
:return:
"""
data = db().fetch('test-example')
return str(data[1])
@api.route('/overall/', methods=['GET', 'POST'])
def overall():
"""
查询ReqCount表内所有的源数据
:return:
"""
limit = request.args.get('limit', type=int)
try:
data = db().exec('select * from reqcount;')
format_data = []
for i in data:
format_data.append({'name': i[0], 'times': i[1]})
return jsonify(
{
'code': 200,
'msg': 'Success. Total: %s row(s)' % len(data),
'data': format_data[:limit]
}
), 200
except Exception as e:
return jsonify(
{
'code': -200,
'msg': 'Error',
'data': e
}
), 500
@api.route('/query/', methods=['GET', 'POST'])
def query():
"""
查询指定名称的计数数据
:return:
"""
name = request.args.get('name', type=str)
nochange = request.args.get('nochange', type=bool)
if nochange:
nochange = True
if not db().exists_name(name):
return jsonify(
{
'code': -200,
'msg': 'Failed. No such name',
'data': None
}
), 404
else:
data = db().fetch(name, nochange)
return jsonify(
{
'code': 200,
'msg': 'Success',
'data': data
}
), 200
@api.route('/theme/', methods=['GET', 'POST'])
def theme():
"""
查询数据库内主题的源数据
:return:
"""
_theme = request.args.get('name', type=str)
if not db().exists_table(_theme):
return jsonify(
{
'code': 404,
'msg': 'Failed. No such theme',
'data': None
}
), 404
else:
data = db().fetching_table(_theme)
return jsonify(
{
'code': 200,
'msg': 'Success',
'data': data
}
), 200
@api.route('/alltables/', methods=['GET', 'POST'])
def all_tables():
"""
查询所有已有表
:return:
"""
data = db().show_tables
return jsonify(
{
'code': 200,
'msg': 'Success',
'data': data
}
), 200
@api.route('/export/', methods=['GET', 'POST'])
@auth.login_required
def export():
"""
导出数据库文件
:return:
"""
return send_file('./db/data.sqlite', as_attachment=True), 200
@api.route('/system/', methods=['GET', 'POST'])
@auth.login_required
def system_info():
"""
获取当前部署服务器的系统状态信息
:return:
"""
_platform = platform.system()
_cpu_count = psutil.cpu_count()
_memory_size = psutil.virtual_memory()
_total_memory_size = round(_memory_size[0] / 1024 / 1024 / 1024, 2)
_free_memory_size = round(_memory_size[4] / 1024 / 1024 / 1024, 2)
_used_memory_size = round(_memory_size[3] / 1024 / 1024 / 1024, 2)
_percent = _memory_size[2]
_py_version = sys.version
return jsonify(
{
'code': 200,
'msg': 'Success',
'data': {
'Platform': _platform,
'CPU-Count': _cpu_count,
'Memory-Size(GigaBytes)': {
'Total': _total_memory_size,
'used': _used_memory_size,
'Free': _free_memory_size,
'Percent': _percent
},
'Python': _py_version
}
}
), 200
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/4/5
# @File Name: config.py
import os
import logging
import platform
from logging.handlers import *
class Config:
JSON_SORT_KEYS = False
JSON_AS_ASCII = False
SSL_REDIRECT = False
SECRET_KEY = ''
@staticmethod
def init_app(app):
if not os.path.exists('./app/logs'):
os.mkdir('./app/logs')
formatter = logging.Formatter(
fmt='[%(asctime)s] |%(filename)s[%(funcName)s:%(lineno)d] |%(levelname)-8s |%(message)s',
datefmt='%H:%M:%S')
handler = logging.handlers.RotatingFileHandler(filename='./app/logs/access.log',
maxBytes=10240,
backupCount=10)
handler.setFormatter(formatter)
handler.setLevel(logging.DEBUG)
if platform.system() == 'Linux':
syslog_handler = SysLogHandler()
syslog_handler.setLevel(logging.INFO)
app.logger.addHandler(syslog_handler)
app.logger.addHandler(handler)
class DevelopmentConfig(Config):
DEBUG = True
class ProductionConfig(Config):
DEBUG = False
class HerokuConfig(ProductionConfig):
SSL_REDIRECT = True
class ProfessionalConfig(ProductionConfig):
SSL_REDIRECT = True
class VersionConfig:
# 暂未开放/Not available
version = ['v0.2.4']
config = {
'development': DevelopmentConfig,
'production': ProductionConfig,
'professional': ProfessionalConfig,
'heroku': HerokuConfig,
'default': DevelopmentConfig
}
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/3/25
# @File Name: __init__.py.py
import os
import sys
import requests
def download():
res = requests.get('https://filebase.vercel.app/download/data.sqlite')
with open('./app/db/data.sqlite', 'wb') as fp:
fp.write(res.content)
if not os.path.exists('./app/db/data.sqlite'):
try:
download()
except requests.exceptions as error:
sys.exit(1)
__all__ = [
'db'
]
+151
View File
@@ -0,0 +1,151 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/3/25
# @File Name: db.py
import sqlite3
from typing import List, Any
class SQLite:
"""操作SQLite数据库"""
def __init__(self) -> None:
"""
初始化SQLite对象
完成后会自动提交, 自动关闭
"""
self.__path = './app/db/data.sqlite'
self.__conn = sqlite3.connect(self.__path)
self.__cursor = self.__conn.cursor()
def __del__(self) -> None:
"""
自动提交
自动关闭连接
:return:
"""
self.__conn.commit()
self.__cursor.close()
self.__conn.close()
@property
def show_tables(self) -> list:
"""
列出所有在数据库内的表
:return:
"""
self.__cursor.execute('select * from sqlite_master where type="table"')
tables = self.__cursor.fetchall()
lst = []
for table in tables:
if table[1] != 'reqcount':
lst.append(table[1])
del tables
return lst
def exists_name(self, name: str) -> bool:
"""
判断当前名称是否在数据库内
调用self.fetch()方法
:param name:
:return:
"""
status = self.fetch(name, True)
if not bool(status):
return False
else:
return True
def exists_table(self, table: str) -> bool:
"""
判断表是否在数据库内
调用self.fetching_table()方法
:param table:
:return:
"""
tables = self.show_tables
if table in tables:
return True
else:
return False
def insert(self, name: str, times: int = 0) -> bool:
"""
插入数据
:param name:
:param times:
:return:
"""
self.__cursor.execute(
'insert into reqcount (name, times) values("%(name)s", %(times)s)' % {'name': name, 'times': times})
return True
def delete(self, name: str) -> bool:
"""
删除数据
暂时不会用到此接口
:param name:
:return:
"""
self.__cursor.execute('delete from reqcount where name="%(name)s"' % {'name': name})
return True
def fetch(self, name: str, is_check: bool = False) -> tuple:
"""
抓取数据
:param name:
:param is_check:
:return:
"""
self.__cursor.execute('select * from reqcount where name="%(name)s"' % {'name': name})
data = self.__cursor.fetchone()
if not is_check:
self.update(name, data[-1])
self.__cursor.execute('select * from reqcount where name="%(name)s"' % {'name': name})
data = self.__cursor.fetchone()
return data
def update(self, name: str, times: int) -> bool:
"""
更新数据
:param name:
:param times:
:return:
"""
self.__cursor.execute(
'update reqcount set times=%(times)s where name="%(name)s"' % {'times': times + 1, 'name': name})
return True
def fetching_table(self, table: str) -> List[dict]:
"""
抓取主题表的数据
:param table:
:return:
"""
status = self.exists_table(table)
if status:
tables = self.__cursor.execute('select * from %(table)s' % {'table': table})
lst = []
for data in tables:
lst.append({'index': data[0],
'url': data[1],
'width': data[2],
'height': data[3]})
del tables
return lst
else:
return []
def exec(self, cmd: str) -> List[Any]:
"""
执行特殊sql语句
:param cmd:
:return:
"""
self.__cursor.execute(cmd)
result = self.__cursor.fetchall()
return result
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/3/25
# @File Name: __init__.py.py
from flask import Blueprint
main = Blueprint('main', __name__)
from . import views, errors
__all__ = [
'main',
'views',
'errors'
]
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/3/25
# @File Name: errors.py
from . import main
from flask import jsonify
@main.app_errorhandler(404)
def page_not_found(e):
return jsonify(
{
'code': 404,
'msg': '页面未找到',
'data': None
}
), 404
@main.app_errorhandler(500)
def internal_server_error(e):
return jsonify(
{
'code': 500,
'msg': '服务器内部错误',
'data': None
}
), 500
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/3/25
# @File Name: views.py
from flask import abort
from flask import request
from flask import make_response
from flask import render_template
from ..db.db import SQLite as db
from ..utils.response import index_
from . import main
@main.route('/', methods=['GET', 'POST'])
def index():
"""
主页
:return:
"""
return render_template('index.html', remote_address=request.remote_addr)
@main.route('/count/<string:name>', methods=['GET', 'POST'])
def home(name: str):
"""
主视图
:param name:
:return:
"""
length = request.args.get('length', 7, type=int)
theme = request.args.get('theme', 'lewd', type=str)
if not db().exists_name(name):
db().insert(name)
if not db().exists_table(theme):
abort(500)
if 7 <= length <= 10:
data = db().fetch(name)
if len(str(data[1])) >= 10: # 计数的数据长度超过最大位数将次数设为1
db().update(name, 0)
# 使用设置的长度减去已有数据的长度, 将结果转换为string类型, 再和数据库内的数据进行拼接
number = '0' * (length - len(str(data[-1]))) + str(data[-1])
response = make_response(index_(theme, int(length), name, number))
response.headers['Content-Type'] = 'image/svg+xml; charset=utf-8'
response.headers['cache-control'] = 'max-age=0, no-cache, no-store, must-revalidate'
return response
return abort(500)
Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

+15
View File
@@ -0,0 +1,15 @@
.intro {
text-align: center;
}
.head {
text-align: center;
}
.example {
text-align: center;
}
a {
color: green;
}
+10
View File
@@ -0,0 +1,10 @@
function request_async(){
// 使用fetch()函数进行异步请求如果服务端响应速度极慢则不会阻塞页面
fetch('/api/v1/test').then(
response => response.text()
).then(
text => {
document.getElementById('fast_test_example_text').innerText = text
}
)
}
+73
View File
@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Request Counter | {{ remote_address }}</title>
<link href="{{ url_for('static', filename='favicon.ico') }}" rel="shortcut icon">
<link rel="stylesheet" href="{{ url_for('static', filename='index.css') }}">
<script type="text/javascript" src="{{ url_for('static', filename='request.js') }}"></script>
</head>
<body>
<div class="head">
<h1>
应用名: 访问次数计数器
</h1>
<h3>
简介: 可以使用SVG矢量图的形式来显示页面的访问次数
<br>
或者通过API的方式获取原始计数数据
</h3>
</div>
<div class="intro">
<div class="current_deployment_test">
<i><a href="{{ url_for('main.home', name='test-example') }}">点击查看当但实例调用示例</a></i>
</div>
<div class="remote_deployment_test">
<i><a href="https://requestcounter.herokuapp.com/count/test-example">点击查看已部署好的调用示例</a></i>
</div>
<div class="note">
<i><b>注: 调用支持POST 和 GET 方法请求</b></i>
</div>
<div class="open_source_protocol">
<i>项目开源协议: <b>Apache-2.0</b> 即:
<br>
你可以直接使用该项目提供的功能, 无需任何授权
<br>
你可以在注明来源版权信息的情况下对源代码进行任意分发和修改以及衍生
</i>
</div>
<div class="documents">
<div class="vercel">
<i><a href="https://request-counter-docs.vercel.app/#/" target="_blank">点击查看托管在<i>Vercel</i>上的文档</a></i>
</div>
<div class="github">
<i><a href="https://markusjoe.github.io/RequestCounter/" target="_blank">点击查看托管在<i>GitHub</i>上的文档</a></i>
</div>
</div>
<div class="ip_address">
<i><b>请求地址来源: {{ remote_address }}</b></i>
</div>
</div>
<div class="example">
<div class="svg">
<img src="https://static-file-hosting.vercel.app/static/lewd/6" alt="fast_test_example_svg">
<img src="https://static-file-hosting.vercel.app/static/lewd/1" alt="fast_test_example_svg">
<img src="https://static-file-hosting.vercel.app/static/lewd/5" alt="fast_test_example_svg">
<img src="https://static-file-hosting.vercel.app/static/lewd/9" alt="fast_test_example_svg">
<img src="https://static-file-hosting.vercel.app/static/lewd/0" alt="fast_test_example_svg">
<img src="https://static-file-hosting.vercel.app/static/lewd/3" alt="fast_test_example_svg">
<img src="https://static-file-hosting.vercel.app/static/lewd/7" alt="fast_test_example_svg">
<img src="https://static-file-hosting.vercel.app/static/lewd/8" alt="fast_test_example_svg">
<img src="https://static-file-hosting.vercel.app/static/lewd/2" alt="fast_test_example_svg">
<img src="https://static-file-hosting.vercel.app/static/lewd/4" alt="fast_test_example_svg">
</div>
<div class="api">
<button onclick="request_async()">点击获取计数数值</button>
<div class="result">
<i><b>test-example</b>当前计数数据值: </i>
<p id="fast_test_example_text"></p>
</div>
</div>
</div>
</body>
</html>
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="{{ general_width }}" height="{{ general_height }}" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>{{ title }} | {{ address }}</title>
<g>
{% for value in context %}
<image x="{{ value.position }}" y="0" width="{{ value.width }}" height="{{ value.height }}"
xlink:href="{{ value.url }}"></image>
{% endfor %}
</g>
</svg>

After

Width:  |  Height:  |  Size: 488 B

+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/3/26
# @File Name: __init__.py.py
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: Pycharm
# @Create Time: 2022/5/1
# @File Name: test_api.py
import random
import unittest
import requests
class TestAPI(unittest.TestCase):
def setUp(self) -> None:
self.api = 'http://127.0.0.1:5000/api/v1/'
def test_query(self):
res = requests.post(self.api + 'query', params={'name': 'test-example'})
self.assertEqual(res.status_code, 200)
def test_query_failed(self):
letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
r_name = ''.join(random.choice(letters) for _ in range(10))
res = requests.post(self.api + 'query', params={'name': r_name})
self.assertEqual(res.status_code, 404)
def test_overall(self):
res = requests.post(self.api + 'overall')
self.assertEqual(res.status_code, 200)
def test_alltables(self):
res = requests.post(self.api + 'alltables')
self.assertEqual(res.status_code, 200)
def test_test(self):
res = int(requests.post(self.api + 'test').text)
self.assertIs(type(res), int)
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: Pycharm
# @Create Time: 2022/5/2
# @File Name: test_auth.py
import random
import requests
import unittest
class TestAuth(unittest.TestCase):
def setUp(self) -> None:
self.api = 'http://127.0.0.1:5000/api/v1/'
@property
def r_pwd(self):
letters = 'abcdefghijklmnopqrstuvwxyz'
r_pwd = ''.join(random.choice(letters) for _ in range(16))
return r_pwd
def test_api_system_header(self):
res = requests.post(self.api + 'system', headers={'Authorization': 'bearer unittest'})
self.assertEqual(res.status_code, 200)
def test_api_system_query(self):
res = requests.post(self.api + 'system', params={'key': 'unittest'})
self.assertEqual(res.status_code, 200)
def test_api_system_header_failed(self):
res = requests.post(self.api + 'system', headers={'Authorization': f'bearer {self.r_pwd}'})
self.assertEqual(res.status_code, 403)
def test_api_system_query_failed(self):
res = requests.post(self.api + 'system', params={'key': self.r_pwd})
self.assertEqual(res.status_code, 403)
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: Pycharm
# @Create Time: 2022/5/1
# @File Name: test_count.py
import requests
import unittest
class TestCount(unittest.TestCase):
def setUp(self) -> None:
self.api = 'http://127.0.0.1:5000/'
def test_index(self):
res = requests.post(self.api).text
self.assertIsNotNone(res)
def test_count(self):
res = requests.post(self.api + 'count/test-example').text
self.assertIsNotNone(res)
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: Pycharm
# @Create Time: 2022/5/1
# @File Name: test_resources.py
import requests
import unittest
class TestResources(unittest.TestCase):
def setUp(self) -> None:
self.resources_urls = {
'docs': [
'https://request-counter-docs.vercel.app/#/',
'https://markusjoe.github.io/RequestCounter/#/'
],
'database': 'https://filebase.vercel.app/download/data.sqlite',
'themes':
{
'lewd': 'https://static-file-hosting.vercel.app/static/lewd/0',
'gelbooru': 'https://static-file-hosting.vercel.app/static/gelbooru/0',
'moebooru': 'https://static-file-hosting.vercel.app/static/moebooru/0',
'blacked': 'https://static-file-hosting.vercel.app/static/blacked/0',
'lisu': 'https://static-file-hosting.vercel.app/static/lisu/0'
}
}
def test_doc_vercel(self):
res = requests.post(self.resources_urls['docs'][0]).text
self.assertIsNotNone(res)
def test_doc_github(self):
res = requests.post(self.resources_urls['docs'][1]).text
self.assertIsNotNone(res)
def test_database(self):
res = requests.post(self.resources_urls['database'])
self.assertEqual(res.status_code, 200)
def test_themes(self):
for t in self.resources_urls['themes']:
res = requests.get(self.resources_urls['themes'][t])
self.assertEqual(res.status_code, 200)
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: Pycharm
# @Create Time: 2022/5/2
# @File Name: test_view.py
import random
import requests
import unittest
class TestViews(unittest.TestCase):
def setUp(self) -> None:
self.api = 'http://127.0.0.1:5000/'
@property
def r_name(self):
letters = 'abcdefghijklmnopqrstuvwxyz'
r_name = [random.choice(letters) for _ in range(10)]
return r_name
def test_not_found(self):
res = requests.get(self.api + 'not_exist_page')
self.assertEqual(res.status_code, 404)
def test_server_internal_error(self):
res = requests.get(self.api + f'count/{self.r_name}', params={'length': 0})
self.assertEqual(res.status_code, 500)
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/3/25
# @File Name: __init__.py.py
__all__ = [
'response',
'password'
]
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/4/11
# @File Name: password.py
import random
def generate_pwd(length):
"""
生成随机密码
:param length:
:return:
"""
letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
return ''.join(random.choice(letters) for _ in range(length))
+79
View File
@@ -0,0 +1,79 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: PyCharm
# @Create Time: 2022/3/25
# @File Name: response.py
from ..db.db import SQLite as db
from flask import request
from flask import render_template
from typing import Tuple
def index_(theme: str, length: int, name: str, count: str) -> str or Tuple[bool, str]:
"""
渲染模板
:param theme:
:param length:
:param name:
:param count:
:return:
"""
datas = db().fetching_table(theme)
context = []
for i in count:
if i == '0':
context.append({'url': datas[0]['url'],
'width': datas[0]['width'],
'height': datas[0]['height']})
elif i == '1':
context.append({'url': datas[1]['url'],
'width': datas[1]['width'],
'height': datas[1]['height']})
elif i == '2':
context.append({'url': datas[2]['url'],
'width': datas[2]['width'],
'height': datas[2]['height']})
elif i == '3':
context.append({'url': datas[3]['url'],
'width': datas[3]['width'],
'height': datas[3]['height']})
elif i == '4':
context.append({'url': datas[4]['url'],
'width': datas[4]['width'],
'height': datas[4]['height']})
elif i == '5':
context.append({'url': datas[5]['url'],
'width': datas[5]['width'],
'height': datas[5]['height']})
elif i == '6':
context.append({'url': datas[6]['url'],
'width': datas[6]['width'],
'height': datas[6]['height']})
elif i == '7':
context.append({'url': datas[7]['url'],
'width': datas[7]['width'],
'height': datas[7]['height']})
elif i == '8':
context.append({'url': datas[8]['url'],
'width': datas[8]['width'],
'height': datas[8]['height']})
elif i == '9':
context.append({'url': datas[9]['url'],
'width': datas[9]['width'],
'height': datas[9]['height']})
for p, i in zip(context, range(0, length)):
p['position'] = i * p['width'] # 设置每张图片对应的位置
general_width = datas[0]['width'] * length # 计算出图片总长度
general_height = datas[0]['height'] # 总宽度
return render_template('view.html',
context=context,
title=name,
address=request.remote_addr,
general_height=general_height,
general_width=general_width)
+79
View File
@@ -0,0 +1,79 @@
#!/usr/bin/env python3
# -- coding:utf-8 --
# @Author: markushammered@gmail.com
# @Development Tool: Pycharm
# @Create Time: 2022/4/29
# @File Name: update.py
import os
import base64
import logging
import requests
from ..config import VersionConfig
from typing import Dict, List
class SelfUpdateVersion:
"""更新本体 -> 更新单个文件"""
def __init__(self, logger: logging.Logger):
self.api = 'https://api.github.com/repos/MarkusJoe/RequestCounter/tags'
self.headers = {'Authorization': 'token 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'}
self.resp = requests.get(self.api, headers=self.headers).json()
self.logger = logger
def commit_details(self):
"""
获取提交细节
:return:
"""
commit_url = self.resp[0]['commit']['url']
res = requests.get(commit_url, headers=self.headers).json()
files = res['files']
modified = []
deleted = []
for f in files:
file_path = f['filename']
base64_content = requests.get(f['contents_url'], headers=self.headers).json()['content'] # 直接获取修改文件的base64
if f['status'] in ['modified', 'added']:
modified.append({'filename': f'./{file_path}', 'content': base64.b64decode(base64_content)})
else:
deleted.append(f'./{file_path}')
self.apply_change(modified, deleted)
def apply_change(self, modified: List[Dict], deleted: List):
"""
应用已经更改的文件
:param modified:
:param deleted:
:return:
"""
for d in deleted:
os.remove(d)
self.logger.info(f'删除了: {d}')
for m in modified:
with open(m['filename'], 'wb') as modify:
modify.write(m['content'])
self.logger.info(f'修改了: {m["filename"]}')
with open('./app/config.py', 'wb') as update_config:
content = requests.get('https://api.github.com/repos/MarkusJoe/RequestCounter/contents/app/config.py',
headers=self.headers).json()['content']
update_config.write(base64.b64decode(content))
exit()
def check(self):
current = VersionConfig.version[0]
newest = self.resp[0]['name']
if current != newest:
self.logger.warning(f'当前版本已经落后于最新版本. 当前: {current} -> 远程: {newest}')
self.commit_details()
return False
else:
self.logger.info('当前版本为最新版本')
return True