From 49fe419232ead01cb10ec28abee9f0e91872e289 Mon Sep 17 00:00:00 2001 From: skimrme Date: Mon, 22 Dec 2025 16:55:31 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=81=E7=A7=BB=E5=9F=BA=E6=9C=AC=E5=AE=8C?= =?UTF-8?q?=E6=88=90=EF=BC=8C=E8=BF=98=E6=9C=89=E4=B8=80=E4=BA=9B=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E9=9C=80=E8=A6=81=E6=A0=B8=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- blueprint/blog_views.py | 35 ++++++++++++- database.py | 2 +- main.py | 38 ++++++++++++++- static/js/alpine.js | 5 ++ static/robots.txt | 7 +++ static/sitemap.xml | 23 +++++++++ templates/about.html | 1 + templates/home.html | 60 ++++++++++++++++++----- templates/list.html | 100 ++++++++++++++++++++++++++++++++++++++ templates/mirrors.html | 28 +++++++++++ templates/posts.html | 14 ++++++ templates/sitemap.xml | 16 ++++++ templates/study/base.html | 13 +++-- templates/study/home.html | 2 +- templates/study/new.html | 4 +- 16 files changed, 327 insertions(+), 24 deletions(-) mode change 100644 => 100755 .gitignore create mode 100644 static/js/alpine.js create mode 100644 static/robots.txt create mode 100644 static/sitemap.xml create mode 100644 templates/list.html create mode 100644 templates/mirrors.html create mode 100644 templates/posts.html create mode 100644 templates/sitemap.xml diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index b76c873..bca1a64 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ **/*.db **/*.sql **/*.db.back -databases/* \ No newline at end of file +databases/* +mirrors/* \ No newline at end of file diff --git a/blueprint/blog_views.py b/blueprint/blog_views.py index e4e49b1..e606127 100755 --- a/blueprint/blog_views.py +++ b/blueprint/blog_views.py @@ -1,20 +1,51 @@ -from flask import Blueprint, render_template +from flask import Blueprint, render_template, request, url_for, flash, redirect from database import get_owp_db import os +import sqlite3 +def get_owp_db_conn(): + conn = sqlite3.connect('/var/open-ww3-project-ww3-tw/databases/sqlite/owp.db') + conn.row_factory = sqlite3.Row + return conn blog_bp = Blueprint('blog', __name__) @blog_bp.route('/') def home(): db = get_owp_db() - return render_template('home.html') + conn = get_owp_db_conn() + sql_logs = "SELECT * from logs;" + sql_posts = "SELECT * from posts;" + logs = conn.execute(sql_logs).fetchall() + posts = conn.execute(sql_posts).fetchall() + conn.close() + return render_template('home.html', logs=logs[::-1], posts=posts[::-1]) @blog_bp.route('/about/') def about(): return render_template('about.html') pass +@blog_bp.route('/posts/') +def posts_list(): + conn = get_owp_db_conn() + sql_posts = "SELECT * from posts;" + posts = conn.execute(sql_posts).fetchall() + conn.close() + return render_template('list.html', posts=posts[::-1]) + +@blog_bp.route('/posts//') +def show_posts_id(posts_id): + conn = get_owp_db_conn() + sql_posts = "SELECT * FROM posts WHERE id = ?" + posts = conn.execute(sql_posts, (posts_id,)).fetchone() + conn.close() + return render_template('posts.html', posts=posts) + + + + +# 数据库测试 @blog_bp.route('/db_test/') def test_db(): db = get_owp_db() diff --git a/database.py b/database.py index 8823f07..a2221dc 100755 --- a/database.py +++ b/database.py @@ -1,7 +1,7 @@ import sqlite3 from flask import g -DATABASE_owp = '/var/databases/sqlite/owp.db' +DATABASE_owp = '/var/open-ww3-project-ww3-tw/databases/sqlite/owp.db' def get_owp_db(): db = getattr(g, '_database', None) diff --git a/main.py b/main.py index dfe1d2d..15a5e23 100755 --- a/main.py +++ b/main.py @@ -1,11 +1,21 @@ -from flask import Flask, render_template, redirect, url_for, g +from flask import Flask, render_template, redirect, url_for, send_from_directory, make_response, g from blueprint.blog_views import blog_bp from blueprint.study_views import study_bp +from flask_autoindex import AutoIndex # from blueprint.admin_views import admin_bp import os +import sqlite3 + +def get_owp_db_conn(): + conn = sqlite3.connect('/var/open-ww3-project-ww3-tw/databases/sqlite/owp.db') + conn.row_factory = sqlite3.Row + return conn app = Flask(__name__, static_url_path='/static/') +index_path = '/var/open-ww3-project-ww3-tw/mirrors/' +index = AutoIndex(app, browse_root=index_path, add_url_rules=False) + # session #app.secret_key = "508948973a8651f160baf3b26f18c47d" app.secret_key = '玩鵬畝遜溉痕叛課還擇鼇粹拜溜泉聰倡效蘭鱅都凍芝西鄂' @@ -21,7 +31,7 @@ app.register_blueprint(study_bp, url_prefix='/study') @app.route('/') def repage(): # return '' - return redirect(url_for('study.home')) + return redirect(url_for('blog.home')) @app.route('/greet//') @@ -35,5 +45,29 @@ def close_connection(exception): if db is not None: db.close() + +@app.route('/mirrors/') +@app.route('/mirrors/') +def autoindex(path='.'): + return index.render_autoindex(path, template='mirrors.html') + +@app.route('/robots.txt/') +def robots(): + return send_from_directory(app.static_folder, 'robots.txt') + + +@app.route('/sitemap.xml/') +def sitemap(): + conn = get_owp_db_conn() + sql_posts = "SELECT * from posts;" + posts = conn.execute(sql_posts).fetchall() + conn.close() + template = render_template('sitemap.xml', posts=posts[::-1], base_url="https://open-ww3-project.ww3.tw/blog/") + response = make_response(template) + response.headers['Content-Type'] = 'application/xml' + return response + + + if __name__ == '__main__': app.run(host="0.0.0.0", port=8085, debug=True) \ No newline at end of file diff --git a/static/js/alpine.js b/static/js/alpine.js new file mode 100644 index 0000000..2a6849c --- /dev/null +++ b/static/js/alpine.js @@ -0,0 +1,5 @@ +(()=>{var nt=!1,it=!1,G=[],ot=-1;function Ut(e){In(e)}function In(e){G.includes(e)||G.push(e),$n()}function Wt(e){let t=G.indexOf(e);t!==-1&&t>ot&&G.splice(t,1)}function $n(){!it&&!nt&&(nt=!0,queueMicrotask(Ln))}function Ln(){nt=!1,it=!0;for(let e=0;ee.effect(t,{scheduler:r=>{st?Ut(r):r()}}),at=e.raw}function ct(e){N=e}function Yt(e){let t=()=>{};return[n=>{let i=N(n);return e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),F(i))},i},()=>{t()}]}function Oe(e,t){let r=!0,n,i=N(()=>{let o=e();JSON.stringify(o),r?n=o:queueMicrotask(()=>{t(o,n),n=o}),r=!1});return()=>F(i)}var Xt=[],Zt=[],Qt=[];function er(e){Qt.push(e)}function re(e,t){typeof t=="function"?(e._x_cleanups||(e._x_cleanups=[]),e._x_cleanups.push(t)):(t=e,Zt.push(t))}function Re(e){Xt.push(e)}function Te(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function lt(e,t){e._x_attributeCleanups&&Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}function tr(e){for(e._x_effects?.forEach(Wt);e._x_cleanups?.length;)e._x_cleanups.pop()()}var ut=new MutationObserver(mt),ft=!1;function pe(){ut.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),ft=!0}function dt(){jn(),ut.disconnect(),ft=!1}var de=[];function jn(){let e=ut.takeRecords();de.push(()=>e.length>0&&mt(e));let t=de.length;queueMicrotask(()=>{if(de.length===t)for(;de.length>0;)de.shift()()})}function m(e){if(!ft)return e();dt();let t=e();return pe(),t}var pt=!1,Ce=[];function rr(){pt=!0}function nr(){pt=!1,mt(Ce),Ce=[]}function mt(e){if(pt){Ce=Ce.concat(e);return}let t=[],r=new Set,n=new Map,i=new Map;for(let o=0;o{s.nodeType===1&&s._x_marker&&r.add(s)}),e[o].addedNodes.forEach(s=>{if(s.nodeType===1){if(r.has(s)){r.delete(s);return}s._x_marker||t.push(s)}})),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{lt(s,o)}),n.forEach((o,s)=>{Xt.forEach(a=>a(s,o))});for(let o of r)t.some(s=>s.contains(o))||Zt.forEach(s=>s(o));for(let o of t)o.isConnected&&Qt.forEach(s=>s(o));t=null,r=null,n=null,i=null}function Me(e){return k(B(e))}function D(e,t,r){return e._x_dataStack=[t,...B(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function B(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?B(e.host):e.parentNode?B(e.parentNode):[]}function k(e){return new Proxy({objects:e},Fn)}var Fn={ownKeys({objects:e}){return Array.from(new Set(e.flatMap(t=>Object.keys(t))))},has({objects:e},t){return t==Symbol.unscopables?!1:e.some(r=>Object.prototype.hasOwnProperty.call(r,t)||Reflect.has(r,t))},get({objects:e},t,r){return t=="toJSON"?Bn:Reflect.get(e.find(n=>Reflect.has(n,t))||{},t,r)},set({objects:e},t,r,n){let i=e.find(s=>Object.prototype.hasOwnProperty.call(s,t))||e[e.length-1],o=Object.getOwnPropertyDescriptor(i,t);return o?.set&&o?.get?o.set.call(n,r)||!0:Reflect.set(i,t,r)}};function Bn(){return Reflect.ownKeys(this).reduce((t,r)=>(t[r]=Reflect.get(this,r),t),{})}function ne(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0||typeof s=="object"&&s!==null&&s.__v_skip)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function Ne(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>zn(n,i),s=>ht(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function zn(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function ht(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),ht(e[t[0]],t.slice(1),r)}}var ir={};function y(e,t){ir[e]=t}function K(e,t){let r=Hn(t);return Object.entries(ir).forEach(([n,i])=>{Object.defineProperty(e,`$${n}`,{get(){return i(t,r)},enumerable:!1})}),e}function Hn(e){let[t,r]=_t(e),n={interceptor:Ne,...t};return re(e,r),n}function or(e,t,r,...n){try{return r(...n)}catch(i){ie(i,e,t)}}function ie(...e){return sr(...e)}var sr=Kn;function ar(e){sr=e}function Kn(e,t,r=void 0){e=Object.assign(e??{message:"No error message given."},{el:t,expression:r}),console.warn(`Alpine Expression Error: ${e.message} + +${r?'Expression: "'+r+`" + +`:""}`,t),setTimeout(()=>{throw e},0)}var oe=!0;function De(e){let t=oe;oe=!1;let r=e();return oe=t,r}function T(e,t,r={}){let n;return x(e,t)(i=>n=i,r),n}function x(...e){return cr(...e)}var cr=xt;function lr(e){cr=e}var ur;function fr(e){ur=e}function xt(e,t){let r={};K(r,e);let n=[r,...B(e)],i=typeof t=="function"?Vn(n,t):Un(n,t,e);return or.bind(null,e,t,i)}function Vn(e,t){return(r=()=>{},{scope:n={},params:i=[],context:o}={})=>{if(!oe){me(r,t,k([n,...e]),i);return}let s=t.apply(k([n,...e]),i);me(r,s)}}var gt={};function qn(e,t){if(gt[e])return gt[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e.trim())||/^(let|const)\s/.test(e.trim())?`(async()=>{ ${e} })()`:e,o=(()=>{try{let s=new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`);return Object.defineProperty(s,"name",{value:`[Alpine] ${e}`}),s}catch(s){return ie(s,t,e),Promise.resolve()}})();return gt[e]=o,o}function Un(e,t,r){let n=qn(t,r);return(i=()=>{},{scope:o={},params:s=[],context:a}={})=>{n.result=void 0,n.finished=!1;let c=k([o,...e]);if(typeof n=="function"){let l=n.call(a,n,c).catch(u=>ie(u,r,t));n.finished?(me(i,n.result,c,s,r),n.result=void 0):l.then(u=>{me(i,u,c,s,r)}).catch(u=>ie(u,r,t)).finally(()=>n.result=void 0)}}}function me(e,t,r,n,i){if(oe&&typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>me(e,s,r,n)).catch(s=>ie(s,i,t)):e(o)}else typeof t=="object"&&t instanceof Promise?t.then(o=>e(o)):e(t)}function dr(...e){return ur(...e)}function pr(e,t,r={}){let n={};K(n,e);let i=[n,...B(e)],o=k([r.scope??{},...i]),s=r.params??[];if(t.includes("await")){let a=Object.getPrototypeOf(async function(){}).constructor,c=/^[\n\s]*if.*\(.*\)/.test(t.trim())||/^(let|const)\s/.test(t.trim())?`(async()=>{ ${t} })()`:t;return new a(["scope"],`with (scope) { let __result = ${c}; return __result }`).call(r.context,o)}else{let a=/^[\n\s]*if.*\(.*\)/.test(t.trim())||/^(let|const)\s/.test(t.trim())?`(()=>{ ${t} })()`:t,l=new Function(["scope"],`with (scope) { let __result = ${a}; return __result }`).call(r.context,o);return typeof l=="function"&&oe?l.apply(o,s):l}}var wt="x-";function C(e=""){return wt+e}function mr(e){wt=e}var ke={};function d(e,t){return ke[e]=t,{before(r){if(!ke[r]){console.warn(String.raw`Cannot find directive \`${r}\`. \`${e}\` will use the default order of execution`);return}let n=J.indexOf(r);J.splice(n>=0?n:J.indexOf("DEFAULT"),0,e)}}}function hr(e){return Object.keys(ke).includes(e)}function _e(e,t,r){if(t=Array.from(t),e._x_virtualDirectives){let o=Object.entries(e._x_virtualDirectives).map(([a,c])=>({name:a,value:c})),s=Et(o);o=o.map(a=>s.find(c=>c.name===a.name)?{name:`x-bind:${a.name}`,value:`"${a.value}"`}:a),t=t.concat(o)}let n={};return t.map(xr((o,s)=>n[o]=s)).filter(br).map(Gn(n,r)).sort(Jn).map(o=>Wn(e,o))}function Et(e){return Array.from(e).map(xr()).filter(t=>!br(t))}var yt=!1,he=new Map,_r=Symbol();function gr(e){yt=!0;let t=Symbol();_r=t,he.set(t,[]);let r=()=>{for(;he.get(t).length;)he.get(t).shift()();he.delete(t)},n=()=>{yt=!1,r()};e(r),n()}function _t(e){let t=[],r=a=>t.push(a),[n,i]=Yt(e);return t.push(i),[{Alpine:z,effect:n,cleanup:r,evaluateLater:x.bind(x,e),evaluate:T.bind(T,e)},()=>t.forEach(a=>a())]}function Wn(e,t){let r=()=>{},n=ke[t.type]||r,[i,o]=_t(e);Te(e,t.original,o);let s=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,i),n=n.bind(n,e,t,i),yt?he.get(_r).push(n):n())};return s.runCleanups=o,s}var Pe=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),Ie=e=>e;function xr(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=yr.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var yr=[];function se(e){yr.push(e)}function br({name:e}){return wr().test(e)}var wr=()=>new RegExp(`^${wt}([^:^.]+)\\b`);function Gn(e,t){return({name:r,value:n})=>{let i=r.match(wr()),o=r.match(/:([a-zA-Z0-9\-_:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var bt="DEFAULT",J=["ignore","ref","data","id","anchor","bind","init","for","model","modelable","transition","show","if",bt,"teleport"];function Jn(e,t){let r=J.indexOf(e.type)===-1?bt:e.type,n=J.indexOf(t.type)===-1?bt:t.type;return J.indexOf(r)-J.indexOf(n)}function Y(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}function P(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>P(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)P(n,t,!1),n=n.nextElementSibling}function E(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}var Er=!1;function vr(){Er&&E("Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems."),Er=!0,document.body||E("Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's ` diff --git a/templates/list.html b/templates/list.html new file mode 100644 index 0000000..55bc55a --- /dev/null +++ b/templates/list.html @@ -0,0 +1,100 @@ + + + + + 文章列表 + + + +
+ 返回首页 +

全部文章

+
+
文章如下↓
+
+
+
+
+ {% for posts in posts %} +
+
+
+ 文章id:{{ posts['id'] }} +
+ 文章标题:{{ posts['title'] }} +
+ 页面跳转__{{ posts['date'] }} +
+
+
+ {% endfor %} +
+
+ + {# 随机变换图床api #} + {% set wallpaper_apis =[ + 'https://www.loliapi.com/acg/pc/', + 'https://api.sretna.cn/api/pc.php', + 'https://www.api.plus/API/dongman/', + 'https://moe.jitsu.top/img/?sort=pc', + 'https://www.dmoe.cc/random.php', + 'https://api.r10086.com/樱道随机图片api接口.php?图片系列=猫娘1', + 'https://api.mtyqx.cn/tapi/random.php'] %} + {% set wallpaper = wallpaper_apis | random %} + + + + \ No newline at end of file diff --git a/templates/mirrors.html b/templates/mirrors.html new file mode 100644 index 0000000..de6b687 --- /dev/null +++ b/templates/mirrors.html @@ -0,0 +1,28 @@ +{% extends '__autoindex__/autoindex.html' %} + +{% block header %} +

index of .

+
+
+
+ +{% endblock %} + +{% block footer %} +
+
+ © 2025 open-ww3-project +
+{% endblock %} \ No newline at end of file diff --git a/templates/posts.html b/templates/posts.html new file mode 100644 index 0000000..88cb33d --- /dev/null +++ b/templates/posts.html @@ -0,0 +1,14 @@ + + + + {{ posts['title'] }} + + + 返回上级 +
+ {{ posts['title'] }} +
+
+ {{ posts['content'] | safe}} + + \ No newline at end of file diff --git a/templates/sitemap.xml b/templates/sitemap.xml new file mode 100644 index 0000000..544e5c3 --- /dev/null +++ b/templates/sitemap.xml @@ -0,0 +1,16 @@ + + + + {{ base_url }} + daily + 1.0 + + {% for posts in posts %} + + {{ base_url }}posts/{{ posts['id'] }} + {{ posts.updated_at }} + monthly + 0.8 + + {% endfor %} + diff --git a/templates/study/base.html b/templates/study/base.html index 508123a..f0499e3 100755 --- a/templates/study/base.html +++ b/templates/study/base.html @@ -24,8 +24,13 @@ -
- 新建文章 +
+
子功能
+
+ +
@@ -51,4 +56,6 @@ color: rgb(0, 0, 0); text-decoration: none; } - \ No newline at end of file + + + \ No newline at end of file diff --git a/templates/study/home.html b/templates/study/home.html index 64ff184..7f946a0 100755 --- a/templates/study/home.html +++ b/templates/study/home.html @@ -7,7 +7,7 @@ {% block content %}

学习如何搭建一个blog

欢迎访问一个学习如何搭建一个blog的页面

- + {% for posts in posts %} diff --git a/templates/study/new.html b/templates/study/new.html index 3e23171..9f306cb 100755 --- a/templates/study/new.html +++ b/templates/study/new.html @@ -5,7 +5,9 @@ {% block title %} 新建文章 {% endblock %} {% block content %} - +
+
+