comment search

This commit is contained in:
BennyThink
2021-09-23 18:24:24 +08:00
parent 9d73aecce8
commit 120c797acb
6 changed files with 213 additions and 80 deletions

176
API.md
View File

@@ -11,12 +11,15 @@
- [x] API变更登录时需要验证码
- [x] API变更like API变更 PATCH `/api/user/` --> PATCH `/api/like/`
- [x] 删除评论admin only
- [x] ME:搜索API返回变更目前包含了评论的结果使用 `type`区分
- [ ] 搜索页面通过评论ID只显示该评论
- [ ] **独立公告和最近更新到新的页面**
- [ ] **对评论的反应**
- [ ] **分类**
- [ ] 添加下载地址到已有资源
- [ ] 新增资源
- [ ] 删除资源、删除已有资源的下载
- [ ] 对评论的反应
- [ ] 更改用户信息(添加邮箱)
- [ ] 分类
- [ ] 评论通知(浏览器通知,暂时隐藏了)
# BE
@@ -46,71 +49,119 @@
## 搜索
同时搜索资源和评论会以type字段区分评论会额外返回 `comment_id`能根据这个ID过滤评论最好了
* GET `/api/resource?keyword=逃避`
```json
{
"data": [
{
"data": {
"info": {
"id": 34812,
"cnname": "逃避可耻却有用",
"enname": "NIGERUHA HAJIDAGA YAKUNITATSU",
"aliasname": "逃避虽可耻但有用 / 雇佣妻子(港) / 月薪娇妻(台) / 逃跑是可耻但是有用 / 逃避虽可耻但很有用 / 逃避可耻但有用",
"channel": "tv",
"channel_cn": "日剧",
"area": "日本",
"show_type": "",
"expire": "1610399344",
"views": 1201,
"year": [
2016,
2017,
2021
]
}
}
"id": 10733,
"cnname": "权力的游戏",
"enname": "Game of Thrones",
"aliasname": "冰与火之歌 / 权力的游戏下载 / 权利的游戏 / 冰火",
"channel": "tv",
"channel_cn": "美剧",
"area": "美国",
"show_type": "",
"expire": "1610372082",
"views": 34,
"year": [
2011
],
"type": "🎦"
},
{
"data": {
"info": {
"id": 29540,
"cnname": "无法逃避",
"enname": "Inescapable",
"aliasname": "无法避免",
"channel": "movie",
"channel_cn": "电影",
"area": "加拿大",
"show_type": "",
"expire": "1610396227",
"views": 1,
"year": [
2012
]
}
}
"id": 35844,
"cnname": "权力的游戏:征服与反抗",
"enname": "Game of Thrones: Conquest and Rebellion",
"aliasname": "",
"channel": "movie",
"channel_cn": "电影",
"area": "美国",
"show_type": "",
"expire": "1610399882",
"views": 1,
"year": [
2017
],
"type": "🎦"
},
{
"data": {
"info": {
"id": 37089,
"cnname": "逃避者",
"enname": "Shirkers",
"aliasname": "",
"channel": "movie",
"channel_cn": "电影",
"area": "美国",
"show_type": "",
"expire": "1610400512",
"views": 0,
"year": [
2018
]
}
}
"cnname": "我用阿里云盘分享了「权力的游戏.1-8季无删减版.1080P......",
"enname": "👉︎👉︎👉︎ happy69",
"aliasname": "我用阿里云盘分享了「权力的游戏.1-8季无删减版.1080P」,你可以不限速下载🚀\n复制这段内容打开「阿里云盘」App 即可获取\n链接https://www.aliyundrive.com/s/zf3WotW6oiC",
"channel_cn": "happy69",
"type": "💬",
"id": 233,
"comment_id": "614bfc698510b2408c1926b5"
},
{
"cnname": "我用阿里云盘分享了「权力的游戏人人影视版」,你可以不限速下载......",
"enname": "👉︎👉︎👉︎ jadydou",
"aliasname": "我用阿里云盘分享了「权力的游戏人人影视版」,你可以不限速下载🚀\n复制这段内容打开「阿里云盘」App 即可获取\n链接https://www.aliyundrive.com/s/WDsKgqyxGps",
"channel_cn": "jadydou",
"type": "💬",
"id": 10733,
"comment_id": "6147fa307af3626caa5523a1"
},
{
"cnname": "我用阿里云盘分享了「权力的游戏.1-8季无删减版.1080P......",
"enname": "👉︎👉︎👉︎ 18103421965",
"aliasname": "我用阿里云盘分享了「权力的游戏.1-8季无删减版.1080P」,你可以不限速下载🚀\n复制这段内容打开「阿里云盘」App 即可获取\n链接https://www.aliyundrive.com/s/A5qPZoP2Jrt",
"channel_cn": "18103421965",
"type": "💬",
"id": 10733,
"comment_id": "614798052afd8de53754bedb"
},
{
"cnname": "我用阿里云盘分享了「权力的游戏.1-8季无删减版.1080P......",
"enname": "👉︎👉︎👉︎ 18103421965",
"aliasname": "我用阿里云盘分享了「权力的游戏.1-8季无删减版.1080P」,你可以不限速下载🚀\n复制这段内容打开「阿里云盘」App 即可获取\n链接https://www.aliyundrive.com/s/A5qPZoP2Jrt",
"channel_cn": "18103421965",
"type": "💬",
"id": 10914,
"comment_id": "614797cd7af3626caa54cf47"
},
{
"cnname": "我用阿里云盘分享了「权力的游戏.1-8季无删减版.1080P......",
"enname": "👉︎👉︎👉︎ kevinluo",
"aliasname": "我用阿里云盘分享了「权力的游戏.1-8季无删减版.1080P」,你可以不限速下载🚀\n复制这段内容打开「阿里云盘」App 即可获取\n链接https://www.aliyundrive.com/s/o58i7s3dcYJ",
"channel_cn": "kevinluo",
"type": "💬",
"id": 10733,
"comment_id": "6146458e2afd8de537529caa"
},
{
"cnname": "网盘目录 Game.of.Thrones.权力的游戏.txt......",
"enname": "👉︎👉︎👉︎ zzzyusa",
"aliasname": "网盘目录 Game.of.Thrones.权力的游戏.txt: https://url90.ctfile.com/f/2536190-513324961-96c675 访问密码5413",
"channel_cn": "zzzyusa",
"type": "💬",
"id": 10733,
"comment_id": "613cbca484bab96c4fa32aef"
},
{
"cnname": "我用阿里云盘分享了「权力的游戏.1-8季无删减版.1080P......",
"enname": "👉︎👉︎👉︎ 牛啊牛啊",
"aliasname": "我用阿里云盘分享了「权力的游戏.1-8季无删减版.1080P」你可以不限速下载https://www.aliyundrive.com/s/NPqweJ6GL6c",
"channel_cn": "牛啊牛啊",
"type": "💬",
"id": 10733,
"comment_id": "61363b5d2f17def162a66c26"
},
{
"cnname": "<reply value=\"60ef0913898cc061......",
"enname": "👉︎👉︎👉︎ Benny",
"aliasname": "<reply value=\"60ef0913898cc06157c5847c\">@408188289@qq.com</reply>目前Resilio Sync 只有黑寡妇这个有,别的我都没做种……😂权力的游戏的话,我硬盘里有,等哪天我有空更新下吧",
"channel_cn": "Benny",
"type": "💬",
"id": 233,
"comment_id": "60efb14c898cc06157c617a7"
}
]
],
"extra": []
}
```
@@ -496,6 +547,7 @@ response
分页支持URL参数
* resource_id: 资源idid为233是留言板id为-1会返回最新评论
* comment_id: 指定该参数,会只返回这条评论
* size: 每页评论数量默认5
* page: 当前页默认1
* inner_size: 内嵌评论数量默认5
@@ -562,6 +614,18 @@ response
}
```
## 搜索评论
* GET `/api/comment/search`
分页支持URL参数
* size: 每页评论数量默认5
* page: 当前页默认1
* keyword: 关键字
返回值与获取评论相同
## 子评论分页
* GET `/api/comment/child`

Submodule YYeTsFE updated: ec00c3ee0b...d96a4610aa

View File

@@ -182,7 +182,11 @@ class CommentMongoResource(CommentResource, Mongo):
def get_comment(self, resource_id: int, page: int, size: int, **kwargs) -> dict:
self.inner_page = kwargs.get("inner_page", 1)
self.inner_size = kwargs.get("inner_size", 5)
comment_id = kwargs.get("comment_id")
condition = {"resource_id": resource_id, "deleted_at": {"$exists": False}, "type": {"$ne": "child"}}
if comment_id:
condition.update(_id=ObjectId(comment_id))
count = self.db["comment"].count_documents(condition)
data = self.db["comment"].find(condition, self.projection) \
@@ -361,26 +365,39 @@ class CommentNewestMongoResource(CommentNewestResource, CommentMongoResource, Mo
self.page = 1
self.size = 5
self.projection = {"ip": False, "parent_id": False, "children": False}
self.condition = {"deleted_at": {"$exists": False}}
self.condition: "dict" = {"deleted_at": {"$exists": False}}
def get_comment(self, page: int, size: int) -> dict:
def get_comment(self, page: int, size: int, keyword="") -> dict:
# ID时间用户名用户组资源名资源id
condition = {"deleted_at": {"$exists": False}}
count = self.db["comment"].count_documents(condition)
data = self.db["comment"].find(condition, self.projection) \
count = self.db["comment"].count_documents(self.condition)
data = self.db["comment"].find(self.condition, self.projection) \
.sort("_id", pymongo.DESCENDING).limit(size).skip((page - 1) * size)
data = list(data)
self.convert_objectid(data)
self.get_user_group(data)
for i in data:
resource_id = i.get("resource_id", 233)
res = self.db["yyets"].find_one({"data.info.id": resource_id})
i["cnname"] = res["data"]["info"]["cnname"]
self.extra_info(data)
return {
"data": data,
"count": count,
}
def extra_info(self, data):
for i in data:
resource_id = i.get("resource_id", 233)
res = self.db["yyets"].find_one({"data.info.id": resource_id})
if res:
i["cnname"] = res["data"]["info"]["cnname"]
class CommentSearchMongoResource(CommentNewestMongoResource):
def get_comment(self, page: int, size: int, keyword="") -> dict:
self.condition.update(content={'$regex': f'.*{keyword}.*', "$options": "-i"})
return super(CommentSearchMongoResource, self).get_comment(page, size, keyword)
def extra_info(self, data):
pass
class GrafanaQueryMongoResource(GrafanaQueryResource, Mongo):
def get_grafana_data(self, date_series) -> str:
@@ -477,11 +494,14 @@ class ResourceMongoResource(ResourceResource, Mongo):
return data
def search_resource(self, keyword: str) -> dict:
final = []
returned = {}
projection = {'_id': False,
'data.info': True,
}
data = self.db["yyets"].find({
resource_data = self.db["yyets"].find({
"$or": [
{"data.info.cnname": {'$regex': f'.*{keyword}.*', "$options": "-i"}},
{"data.info.enname": {'$regex': f'.*{keyword}.*', "$options": "-i"}},
@@ -489,10 +509,30 @@ class ResourceMongoResource(ResourceResource, Mongo):
]},
projection
)
data = list(data)
returned = {}
if data:
returned = dict(data=data)
for item in resource_data:
item["data"]["info"]["type"] = "🎦"
final.append(item["data"]["info"])
# get comment
r = CommentSearchMongoResource().get_comment(1, 100, keyword)
c_search = []
for c in r.get("data", []):
cnname = c["content"][:30] + "......"
enname = f'👉︎👉︎👉︎ {c["username"]}'
channel_cn = c["username"]
aliasname = c["content"]
resource_id = c["resource_id"]
c_search.append(
dict(
cnname=cnname, enname=enname, aliasname=aliasname, channel_cn=channel_cn,
type="💬", id=resource_id, comment_id=c["id"]
)
)
final.extend(c_search)
if final:
returned = dict(data=final)
returned["extra"] = []
else:
extra = self.fansub_search(ZimuxiaOnline.__name__, keyword) or \
@@ -975,7 +1015,7 @@ class ResourceLatestMongoResource(ResourceLatestResource, Mongo):
projection = {"_id": False, "status": False, "info": False}
episode_data = {}
for res in tqdm(col.find(projection=projection), total=col.count()):
for season in res["data"]["list"]:
for season in res["data"].get("list",[]):
for item in season["items"].values():
for single in item:
ts = single["dateline"]

View File

@@ -174,7 +174,7 @@ class CommentChildResource:
class CommentNewestResource:
def get_comment(self, page: int, size: int) -> dict:
def get_comment(self, page: int, size: int, keyword=None) -> dict:
pass

View File

@@ -358,10 +358,16 @@ class CommentHandler(BaseHandler):
page = int(self.get_argument("page", "1"))
inner_size = int(self.get_argument("inner_size", "5"))
inner_page = int(self.get_argument("inner_page", "1"))
comment_id = self.get_argument("comment_id", None)
if not resource_id:
self.set_status(HTTPStatus.BAD_REQUEST)
return {"status": False, "message": "请提供resource id"}
comment_data = self.instance.get_comment(resource_id, page, size, inner_size=inner_size, inner_page=inner_page)
comment_data = self.instance.get_comment(
resource_id, page, size,
inner_size=inner_size, inner_page=inner_page,
comment_id=comment_id
)
self.hide_phone((comment_data["data"]))
return comment_data
@@ -490,6 +496,27 @@ class CommentNewestHandler(CommentHandler):
self.write(resp)
class CommentSearchHandler(CommentHandler):
class_name = f"CommentSearch{adapter}Resource"
# from Mongo import CommentNewestResource
# instance = CommentNewestResource()
@run_on_executor()
def search_comment(self):
size = int(self.get_argument("size", "5"))
page = int(self.get_argument("page", "1"))
keyword = self.get_argument("keyword", "")
comment_data = self.instance.get_comment(page, size, keyword)
self.hide_phone((comment_data["data"]))
return comment_data
@gen.coroutine
def get(self):
resp = yield self.search_comment()
self.write(resp)
class AnnouncementHandler(BaseHandler):
class_name = f"Announcement{adapter}Resource"

View File

@@ -12,6 +12,7 @@ import os
import platform
import pytz
import tornado.autoreload
from apscheduler.schedulers.background import BackgroundScheduler
from tornado import httpserver, ioloop, options, web
from tornado.log import enable_pretty_logging
@@ -19,10 +20,10 @@ from tornado.log import enable_pretty_logging
from handler import (AnnouncementHandler, BlacklistHandler, CaptchaHandler,
CategoryHandler, CommentChildHandler, CommentHandler,
CommentNewestHandler, CommentReactionHandler,
DBDumpHandler, DoubanHandler, DoubanReportHandler,
GrafanaIndexHandler, GrafanaQueryHandler,
GrafanaSearchHandler, IndexHandler, LikeHandler,
MetricsHandler, NameHandler, NotFoundHandler,
DBDumpHandler, DoubanHandler,
DoubanReportHandler, GrafanaIndexHandler,
GrafanaQueryHandler, GrafanaSearchHandler, IndexHandler,
LikeHandler, MetricsHandler, NameHandler, NotFoundHandler,
NotificationHandler, ResourceHandler,
ResourceLatestHandler, TopHandler, UserEmailHandler,
UserHandler)
@@ -80,8 +81,9 @@ class RunServer:
def run_server(port, host):
tornado_server = httpserver.HTTPServer(RunServer.application, xheaders=True)
tornado_server.bind(port, host)
if platform.uname().system == "Windows":
if platform.uname().system in ("Windows", "Darwin"):
tornado_server.start(1)
tornado.autoreload.start()
else:
tornado_server.start(0)
@@ -98,7 +100,7 @@ if __name__ == "__main__":
scheduler = BackgroundScheduler(timezone=timez)
scheduler.add_job(OtherMongoResource().reset_top, 'cron', hour=0, minute=0, day=1)
scheduler.add_job(sync_douban, 'cron', hour=0, minute=0, day=1)
scheduler.add_job(ResourceLatestMongoResource().refresh_latest_resource, 'cron', minute=0)
# scheduler.add_job(ResourceLatestMongoResource().refresh_latest_resource, 'cron', hour=1)
scheduler.start()
options.define("p", default=8888, help="running port", type=int)
options.define("h", default='127.0.0.1', help="listen address", type=str)