diff --git a/README.md b/README.md
index 762e693..b6f69c3 100644
--- a/README.md
+++ b/README.md
@@ -25,8 +25,7 @@ $ . venv/bin/activate
## 配置方法
-打开 `shared.py` 修改 `app.config['SERVER_NAME']` 中冒号后的数字来改变端口号。
-因为 twisted 的原因,你需要将代理指向那个端口号 -1 的端口上。
+打开 `shared.py` 修改 `port` 后的数字来改变端口号。
其中的 `should_fetch_comments` 用于控制是否获取楼中楼。如果浏览性能不佳可以考虑
关闭楼中楼获取。
diff --git a/app.py b/app.py
index 728899a..840cfc4 100644
--- a/app.py
+++ b/app.py
@@ -1,5 +1,6 @@
import asyncio
import aiotieba
+import uvicorn
from aioflask import render_template, request, escape
from urllib.parse import quote_plus
@@ -8,6 +9,8 @@ from datetime import datetime
from aiotieba.api.get_posts._classdef import *
from aiotieba.api._classdef.contents import *
+from proxify import AsgiproxifyHandler
+
from shared import *
from extra import *
@@ -26,6 +29,10 @@ async def cache_name_from_id(c, i):
r = await c.get_user_info(i, require=aiotieba.enums.ReqUInfo.USER_NAME)
cache.set(i, r)
+# Normalize unicode characters to ASCII form.
+def normalize_utf8(s):
+ return s.encode('unicode_escape').decode('ascii').replace('\\', '')
+
######################################################################
# Convert a timestamp to its simpliest readable date format.
@@ -78,7 +85,7 @@ async def _jinja2_filter_translate(frags, reply_id=0):
elif isinstance(frag, FragEmoji_p):
htmlfmt = append_with_leading_clean(htmlfmt,
f'')
+ f'src="/static/emoticons/{ normalize_utf8(frag.desc) }.png">')
if i+1 < len(frags) and isinstance(frags[i+1], FragImage_p):
htmlfmt += '
'
elif isinstance(frag, FragLink):
@@ -136,21 +143,17 @@ async def forum_view():
sort = int(request.args.get('sort') or 0)
async with aiotieba.Client() as tieba:
- if only_use_native_api:
- forum_info, threads = await asyncio.gather(tieba.get_forum_detail(fname),
- tieba.get_threads(fname, pn=pn, sort=sort))
- if hasattr(forum_info, 'slogan'):
- forum_info = { 'avatar': extract_image_name(forum_info.origin_avatar),
- 'topic': forum_info.post_num, 'thread': forum_info.post_num,
- 'member': forum_info.member_num, 'desc': forum_info.slogan,
- 'name': forum_info.fname }
- else:
- forum_info = { 'avatar': 'a6efce1b9d16fdfa6291460ab98f8c5495ee7b51.jpg',
- 'topic': forum_info.post_num, 'thread': forum_info.post_num,
- 'member': forum_info.member_num, 'desc': '贴吧描述暂不可用', 'name': forum_info.fname }
+ forum_info, threads = await asyncio.gather(tieba.get_forum_detail(fname),
+ tieba.get_threads(fname, pn=pn, sort=sort))
+ if hasattr(forum_info, 'slogan'):
+ forum_info = { 'avatar': extract_image_name(forum_info.origin_avatar),
+ 'topic': forum_info.post_num, 'thread': forum_info.post_num,
+ 'member': forum_info.member_num, 'desc': forum_info.slogan,
+ 'name': forum_info.fname }
else:
- forum_info, threads = await asyncio.gather(awaitify(find_tieba_info)(fname),
- tieba.get_threads(fname, pn=pn, sort=sort))
+ forum_info = { 'avatar': 'a6efce1b9d16fdfa6291460ab98f8c5495ee7b51.jpg',
+ 'topic': forum_info.post_num, 'thread': forum_info.post_num,
+ 'member': forum_info.member_num, 'desc': '贴吧描述暂不可用', 'name': forum_info.fname }
if threads.page.current_page > threads.page.total_page or pn < 1:
return await render_template('error.html', msg = \
@@ -195,5 +198,17 @@ async def runtime_error_view(e):
async def general_error_view(e):
return await render_template('error.html', msg=e)
+######################################################################
+
+@proxified.register('/proxy/avatar/')
+class AvatarProxyHandler(AsgiproxifyHandler):
+ def make_request_url(self):
+ return 'http://tb.himg.baidu.com/sys/portraith/item/' + self.scope['path'][14:]
+
+@proxified.register('/proxy/pic/')
+class PictureProxyHandler(AsgiproxifyHandler):
+ def make_request_url(self):
+ return 'http://imgsa.baidu.com/forum/pic/item/' + self.scope['path'][11:]
+
if __name__ == '__main__':
- app.run(debug=True)
+ uvicorn.run(proxified, host=host, port=port)
diff --git a/extra.py b/extra.py
index 2565ada..ef5fe68 100644
--- a/extra.py
+++ b/extra.py
@@ -12,38 +12,4 @@ def extract_image_name(url):
try:
return match.group(1) + '.jpg'
except:
- return '404.jpg'
-
-@cache.memoize(timeout=60)
-def find_tieba_info(tname):
- """Get the tiebat avatar for the forum name.
-
- :param tname: the name of the target forum.
- :returns: the internal ID of the corresponding avatar.
-
- """
- info = { 'name': tname }
-
- res = requests.get('https://tieba.baidu.com/f',
- params={'kw': tname},
- allow_redirects=False)
-
- # Baidu will bring us to the search page, so we ignore it.
- if res.status_code == 302:
- raise ValueError('您搜索的贴吧不存在')
-
- soup = bs4.BeautifulSoup(res.text, 'html.parser')
-
- elems = soup.select('#forum-card-head')
- info['avatar'] = extract_image_name(elems[0]['src'])
-
- footer = soup.select('.th_footer_l')[0]
- stat_elems = footer.findAll('span', {'class': 'red_text'}, recursive=False)
- stats = list(map(lambda x: int(x.text), stat_elems))
-
- info |= { 'topic': stats[0], 'thread': stats[1], 'member': stats[2] }
-
- slogan = soup.select('.card_slogan')[0]
- info['desc'] = slogan.text
-
- return info
+ return 'a6efce1b9d16fdfa6291460ab98f8c5495ee7b51.jpg'
diff --git a/main.py b/main.py
deleted file mode 100644
index aaa0056..0000000
--- a/main.py
+++ /dev/null
@@ -1,161 +0,0 @@
-import multiprocessing
-
-from app import app
-
-from urllib.parse import quote as urlquote, urlparse, urlunparse
-from twisted.web.http import _QUEUED_SENTINEL, HTTPChannel, HTTPClient, Request
-from twisted.web.resource import Resource
-from twisted.web import proxy, server
-from twisted.web.static import File
-from twisted.internet.protocol import ClientFactory
-from twisted.internet import reactor, utils
-
-plain_cookies = {}
-
-################################################################################
-# Modified Dynamic Proxy (from twisted)
-################################################################################
-
-class ProxyClient(HTTPClient):
- _finished = False
-
- def __init__(self, command, rest, version, headers, data, father):
- self.father = father
- self.command = command
- self.rest = rest
- if b"proxy-connection" in headers:
- del headers[b"proxy-connection"]
- headers[b"connection"] = b"close"
- headers.pop(b"keep-alive", None)
- self.headers = headers
- self.data = data
-
- def connectionMade(self):
- self.sendCommand(self.command, self.rest)
- for header, value in self.headers.items():
- self.sendHeader(header, value)
- self.endHeaders()
- self.transport.write(self.data)
-
- def handleStatus(self, version, code, message):
- self.father.setResponseCode(int(code), message)
-
- def handleHeader(self, key, value):
- if key.lower() in [b"server", b"date", b"content-type"]:
- self.father.responseHeaders.setRawHeaders(key, [value])
- else:
- self.father.responseHeaders.addRawHeader(key, value)
-
- def handleResponsePart(self, buffer):
- self.father.write(buffer)
-
- def handleResponseEnd(self):
- if not self._finished:
- self._finished = True
- self.father.notifyFinish().addErrback(lambda x: None)
- self.transport.loseConnection()
-
-class ProxyClientFactory(ClientFactory):
- protocol = ProxyClient
-
- def __init__(self, command, rest, version, headers, data, father):
- self.father = father
- self.command = command
- self.rest = rest
- self.headers = headers
- self.data = data
- self.version = version
-
- def buildProtocol(self, addr):
- return self.protocol(
- self.command, self.rest, self.version, self.headers, self.data, self.father
- )
-
- def clientConnectionFailed(self, connector, reason):
- self.father.setResponseCode(501, b"Gateway error")
- self.father.responseHeaders.addRawHeader(b"Content-Type", b"text/html")
- self.father.write(b"