From 9df44d5a722e71d48099c2e14f6ce02cf858702e Mon Sep 17 00:00:00 2001
From: John Xina
Date: Wed, 12 Jul 2023 22:52:47 +0800
Subject: [PATCH] add several features
---
app.py | 82 +++++++++++++++++++++++++++++++++----------
extra.py | 6 +++-
main.py | 11 +++---
shared.py | 8 ++++-
static/css/main.css | 15 ++++++++
templates/bar.html | 23 +++++++++---
templates/thread.html | 18 ++++++++++
7 files changed, 131 insertions(+), 32 deletions(-)
diff --git a/app.py b/app.py
index 1e3a7aa..28f89b5 100644
--- a/app.py
+++ b/app.py
@@ -2,7 +2,6 @@ import asyncio
import aiotieba
from aioflask import render_template, request, escape
-from flask_caching import Cache
from urllib.parse import quote_plus
from datetime import datetime
@@ -14,6 +13,21 @@ from extra import *
######################################################################
+# Clean a leading part and append the text.
+def append_with_leading_clean(orig, content):
+ if orig.endswith('
'):
+ return orig[:-4] + content
+ else:
+ return orig + content
+
+# Return the corresponding user name for an id.
+async def cache_name_from_id(c, i):
+ if not cache.get(i):
+ r = await c.get_user_info(i, require=aiotieba.enums.ReqUInfo.USER_NAME)
+ cache.set(i, r)
+
+######################################################################
+
# Convert a timestamp to its simpliest readable date format.
@app.template_filter('simpledate')
def _jinja2_filter_simpledate(ts):
@@ -44,28 +58,44 @@ def _jinja2_filter_trim(text):
# Format fragments to its equiviant HTML.
@app.template_filter('translate')
-def _jinja2_filter_translate(frags):
+async def _jinja2_filter_translate(frags, reply_id=0):
htmlfmt = ''
+
+ if reply_id:
+ htmlfmt += f'@{ cache.get(reply_id) } '
- for frag in frags:
+ for i in range(len(frags)):
+ frag = frags[i]
if isinstance(frag, FragText):
subfrags = frag.text.split('\n')
for subfrag in subfrags:
- htmlfmt += '' + str(escape(subfrag)) + '
'
+ htmlfmt += str(escape(subfrag)) + '
'
elif isinstance(frag, FragImage_p):
htmlfmt += \
f'' \
f''
elif isinstance(frag, FragEmoji_p):
- clear_leading = False
- if htmlfmt.endswith('
'):
- clear_leading = True
- htmlfmt = htmlfmt.rstrip('')
- htmlfmt += f''
- if clear_leading:
- htmlfmt += ''
-
+ htmlfmt = append_with_leading_clean(htmlfmt,
+ f'')
+ if i+1 < len(frags) and isinstance(frags[i+1], FragImage_p):
+ htmlfmt += '
'
+ elif isinstance(frag, FragLink):
+ markup = '{ frag.title }'
+ htmlfmt = append_with_leading_clean(htmlfmt, markup)
+ elif isinstance(frag, FragAt):
+ htmlfmt = append_with_leading_clean(htmlfmt,
+ f'{ frag.text }')
+ else:
+ print('Unhandled: ', type(frag))
+ print(frag)
+
return htmlfmt
######################################################################
@@ -77,23 +107,39 @@ async def thread_view(tid):
async with aiotieba.Client() as tieba:
# Default to 15 posts per page, confirm to tieba.baidu.com
- thread_info = await tieba.get_posts(tid, rn=15, pn=pn)
+ thread_info = await tieba.get_posts(tid, rn=15, pn=pn,
+ with_comments=should_fetch_comments)
- for post in thread_info:
- print(post.comments)
-
+ available_users = []
+ for floor in thread_info:
+ for comment in floor.comments:
+ available_users.append(comment.author_id)
+ cache.set(comment.author_id, comment.user.user_name)
+
+ all_users = {}
+ for floor in thread_info:
+ for comment in floor.comments:
+ if not comment.reply_to_id in available_users:
+ all_users[comment.reply_to_id] = ''
+ all_users.pop(0, None)
+ all_users = list(all_users.keys())
+
+ await asyncio.gather(*(cache_name_from_id(tieba, i) for i in all_users))
+
+
return await render_template('thread.html', info=thread_info)
@app.route('/f')
async def forum_view():
fname = request.args['kw']
pn = int(request.args.get('pn') or 1)
+ sort = int(request.args.get('sort') or 0)
async with aiotieba.Client() as tieba:
forum_info, threads = await asyncio.gather(awaitify(find_tieba_info)(fname),
- tieba.get_threads(fname, rn=50, pn=pn))
+ tieba.get_threads(fname, rn=50, pn=pn, sort=sort))
- return await render_template('bar.html', info=forum_info, threads=threads)
+ return await render_template('bar.html', info=forum_info, threads=threads, sort=sort)
if __name__ == '__main__':
app.run(debug=True)
diff --git a/extra.py b/extra.py
index 2bfa4e1..9cd533b 100644
--- a/extra.py
+++ b/extra.py
@@ -6,9 +6,13 @@ import re
from shared import *
+# TODO: known bug, can't extract from super old editor images.
def extract_image_name(url):
match = re.search(r'/(\w+)\.jpg', url)
- return match.group(1) + '.jpg'
+ try:
+ return match.group(1) + '.jpg'
+ except:
+ return '404.jpg'
@cache.cached(timeout=60, key_prefix='tieba_info')
def find_tieba_info(tname):
diff --git a/main.py b/main.py
index a02b03c..aaa0056 100644
--- a/main.py
+++ b/main.py
@@ -138,11 +138,12 @@ class ReverseProxyResource(Resource):
# To start this function for testing: python -c 'import main; main.twisted_start()'
def twisted_start():
- flask_res = proxy.ReverseProxyResource('127.0.0.1', 5000, b'')
+ flask_port = int(app.config['SERVER_NAME'].split(':')[1])
+ flask_res = proxy.ReverseProxyResource('127.0.0.1', flask_port, b'')
flask_res.putChild(b'proxy', ReverseProxyResource(b'/proxy'))
flask_res.putChild(b'static', File('static'))
- flask_port = int(app.config['SERVER_NAME'].split(':')[1])
+ print(f' *** SERVER IS RUNNING ON PORT {flask_port-1} ***')
site = server.Site(flask_res)
reactor.listenTCP(flask_port-1, site)
@@ -154,11 +155,7 @@ def flask_start():
# If we're executed directly, also start the flask daemon.
if __name__ == '__main__':
- flask_port = int(app.config['SERVER_NAME'].split(':')[1])
- print(f' *** SERVER IS RUNNING ON PORT {flask_port-1} ***')
-
- twisted_start()
-
flask_task = multiprocessing.Process(target=flask_start)
flask_task.daemon = True # Exit the child if the parent was killed :-(
flask_task.start()
+ twisted_start()
diff --git a/shared.py b/shared.py
index 87adbef..f0b0f98 100644
--- a/shared.py
+++ b/shared.py
@@ -12,7 +12,13 @@ def awaitify(sync_func):
app = Flask(__name__)
-app.config['SERVER_NAME'] = ':6666'
+######################################################################
+
+app.config['SERVER_NAME'] = '127.0.0.1:8886'
+
+should_fetch_comments = True
+
+######################################################################
app.config['CACHE_TYPE'] = 'SimpleCache'
cache = Cache(app)
diff --git a/static/css/main.css b/static/css/main.css
index a85c19a..6b188a2 100644
--- a/static/css/main.css
+++ b/static/css/main.css
@@ -2,6 +2,21 @@
max-width: 5% !important;
}
+.vlist {
+ display: flex;
+ justify-content: space-between;
+}
+
+.vlist > div {
+ flex: 1;
+ text-align: center;
+ margin: 0.5em;
+}
+
+.current-sel {
+ color: inherit !important;
+}
+
/* global styling */
:root {
--bg-color: #eeeecc;
diff --git a/templates/bar.html b/templates/bar.html
index 73c38c2..ae3e047 100644
--- a/templates/bar.html
+++ b/templates/bar.html
@@ -21,6 +21,16 @@
+
{% for t in threads %}
+
+ {% if t.title %}
{{ t.text[(t.title|length):]|trim }}
+ {% endif %}
@@ -47,13 +60,13 @@
{% if threads.page.current_page > 1 %}
-
首页
+
首页
{% endif %}
{% for i in range(5) %}
{% set np = threads.page.current_page - 5 + i %}
{% if np > 0 %}
-
{{ np }}
+
{{ np }}
{% endif %}
{% endfor %}
@@ -62,12 +75,12 @@
{% for i in range(5) %}
{% set np = threads.page.current_page + 1 + i %}
{% if np <= threads.page.total_page %}
-
{{ np }}
+
{{ np }}
{% endif %}
{% endfor %}
{% if threads.page.current_page < threads.page.total_page %}
-
尾页
+
尾页
{% endif %}
diff --git a/templates/thread.html b/templates/thread.html
index 2e5be92..fc06ed5 100644
--- a/templates/thread.html
+++ b/templates/thread.html
@@ -30,6 +30,24 @@
{{ p.create_time|date }}
{{ p.floor }}
+ {% if p.comments %}
+
+ {% for comment in p.comments %}
+
+
+
+
+
+ {{ comment.contents|translate(comment.reply_to_id)|safe }}
+
+
{{ comment.create_time|date }}
+
+
+ {% endfor %}
+
+ {% endif %}
{% endfor %}