Skip to content

Commit 185f766

Browse files
committed
JTools v3.14.0
功能变动: - **迁移到新版数据源** - 日志记录迁移到 sshared - 更新鸣谢名单 - 升级构建时使用的 Caddy 镜像版本
2 parents bd74892 + 39b06d3 commit 185f766

23 files changed

+680
-589
lines changed

Dockerfile.frontend

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ RUN bun install --prod --frozen-lockfile
88
COPY frontend .
99
RUN bun run build
1010

11-
FROM caddy:2.7-alpine
11+
FROM caddy:2.8-alpine
1212

1313
WORKDIR /app
1414

backend/api/v1/articles.py

Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from datetime import datetime, timedelta
2-
from typing import Annotated, Any, Dict, Optional, cast
2+
from typing import Annotated, Dict, Optional
33

4-
from bson import ObjectId
54
from jkit.article import Article
65
from jkit.constants import ARTICLE_SLUG_REGEX
76
from jkit.exceptions import ResourceUnavailableError
@@ -19,8 +18,10 @@
1918
success,
2019
)
2120

21+
from models.jianshu.article_earning_ranking_record import (
22+
ArticleEarningRankingRecordDocument,
23+
)
2224
from utils.config import config
23-
from utils.db import ARTICLE_FP_RANK_COLLECTION
2425

2526
# fmt: off
2627
splitter = AbilityJiebaPossegSplitterV1(
@@ -36,88 +37,71 @@
3637

3738

3839
async def get_latest_onrank_record(
39-
author_url: str, *, minimum_ranking: Optional[int] = None
40-
) -> Optional[Dict[str, Any]]:
41-
cursor = (
42-
ARTICLE_FP_RANK_COLLECTION.find(
43-
{
44-
"author.url": author_url,
45-
"ranking": {
46-
"$lte": minimum_ranking if minimum_ranking else 100,
47-
},
48-
}
49-
)
50-
.sort("date", -1)
51-
.limit(1)
40+
author_slug: str, *, minimum_ranking: Optional[int] = None
41+
) -> Optional[ArticleEarningRankingRecordDocument]:
42+
# TODO
43+
return await ArticleEarningRankingRecordDocument.find_one(
44+
{
45+
"authorSlug": author_slug,
46+
"ranking": { # type: ignore
47+
"$lte": minimum_ranking if minimum_ranking else 100,
48+
},
49+
},
50+
sort={"date": "DESC"},
5251
)
5352

54-
try:
55-
return await cursor.next()
56-
except StopAsyncIteration:
57-
return None
58-
5953

6054
async def get_pervious_onrank_record(
61-
onrank_record: Dict[str, Any], minimum_ranking: Optional[int] = None
62-
) -> Optional[Dict[str, Any]]:
63-
cursor = (
64-
ARTICLE_FP_RANK_COLLECTION.find(
65-
{
66-
"_id": {"$lt": ObjectId(onrank_record["_id"])},
67-
"author.url": onrank_record["author"]["url"],
68-
"ranking": {
69-
"$lte": minimum_ranking if minimum_ranking else 100,
70-
},
71-
}
72-
)
73-
.sort("_id", -1)
74-
.limit(1)
55+
onrank_record: ArticleEarningRankingRecordDocument,
56+
minimum_ranking: Optional[int] = None,
57+
) -> Optional[ArticleEarningRankingRecordDocument]:
58+
return await ArticleEarningRankingRecordDocument.find_one(
59+
{
60+
"_id": {"$lt": onrank_record._id},
61+
"authorSlug": onrank_record.author_slug,
62+
"ranking": { # type: ignore
63+
"$lte": minimum_ranking if minimum_ranking else 100,
64+
},
65+
},
66+
sort={"_id": "DESC"},
7567
)
7668

77-
try:
78-
return await cursor.next()
79-
except StopAsyncIteration:
80-
return None
81-
8269

83-
async def caculate_next_can_recommend_date(author_url: str) -> Optional[datetime]:
84-
counted_article_urls = set()
70+
async def get_earliest_can_recommend_date(author_slug: str) -> Optional[datetime]:
71+
counted_article_slugs = set()
8572

8673
latest_onrank_record = await get_latest_onrank_record(
87-
author_url, minimum_ranking=85
74+
author_slug, minimum_ranking=85
8875
)
8976
if not latest_onrank_record:
90-
# 作者没有上榜文章,或全部上榜文章均低于 85 名
9177
return None
9278

93-
interval_days = 10 if latest_onrank_record["ranking"] <= 30 else 7
94-
counted_article_urls.add(latest_onrank_record["article"]["url"])
79+
interval_days = 10 if latest_onrank_record.ranking <= 30 else 7
80+
counted_article_slugs.add(latest_onrank_record.article.slug)
9581

9682
now_record = latest_onrank_record
9783
while True:
9884
pervious_record = await get_pervious_onrank_record(
9985
now_record, minimum_ranking=85
10086
)
10187
if not pervious_record:
102-
# 没有更多文章
103-
return cast(datetime, now_record["date"]) + timedelta(days=interval_days)
104-
if pervious_record["article"]["url"] in counted_article_urls:
105-
# 该文章之前计算过间隔
88+
return latest_onrank_record.date + timedelta(days=interval_days)
89+
if pervious_record.article.slug in counted_article_slugs:
10690
now_record = pervious_record
10791
continue
10892

109-
counted_article_urls.add(pervious_record["article"]["url"])
93+
counted_article_slugs.add(pervious_record.article.slug)
11094

11195
if (
112-
now_record["ranking"] <= 30
113-
and (now_record["date"] - pervious_record["date"]).days + 1 >= 10
96+
now_record.ranking <= 30
97+
and (now_record.date - pervious_record.date).days + 1 >= 10
11498
) or (
115-
now_record["ranking"] > 30
116-
and (now_record["date"] - pervious_record["date"]).days + 1 >= 7
99+
now_record.ranking > 30
100+
and (now_record.date - pervious_record.date).days + 1 >= 7
117101
):
118-
return cast(datetime, now_record["date"]) + timedelta(days=interval_days)
102+
return latest_onrank_record.date + timedelta(days=interval_days)
119103

120-
if pervious_record["ranking"] <= 30:
104+
if pervious_record.ranking <= 30:
121105
interval_days += 10
122106
else:
123107
interval_days += 7
@@ -231,10 +215,10 @@ async def get_LP_recommend_check_handler( # noqa: N802
231215

232216
article_info = await article.info
233217

234-
author_url = article_info.author_info.to_user_obj().url
218+
author_slug = article_info.author_info.to_user_obj().slug
235219
article_title = article_info.title
236220
article_fp_reward = article_info.earned_fp_amount
237-
article_next_can_recommend_date = await caculate_next_can_recommend_date(author_url)
221+
article_next_can_recommend_date = await get_earliest_can_recommend_date(author_slug)
238222

239223
can_recommend_now = article_fp_reward < 35 and (
240224
not article_next_can_recommend_date

backend/api/v1/jpep/ftn_macket.py

Lines changed: 45 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from asyncio import gather
22
from datetime import datetime, timedelta
3-
from typing import Annotated, Any, Dict, Literal, Optional
3+
from typing import Annotated, Dict, Literal, Optional
44

55
from jkit.jpep.platform_settings import PlatformSettings
66
from litestar import Response, Router, get
@@ -13,7 +13,7 @@
1313
)
1414
from sspeedup.time_helper import get_start_time
1515

16-
from utils.db import JPEP_FTN_MACKET_COLLECTION
16+
from models.jpep.ftn_trade_order import FTNTradeOrderDocument
1717

1818
RANGE_TO_TIMEDELTA: Dict[str, timedelta] = {
1919
"24h": timedelta(hours=24),
@@ -32,92 +32,72 @@
3232

3333

3434
async def get_data_update_time() -> datetime:
35-
result = (
36-
await JPEP_FTN_MACKET_COLLECTION.find(
37-
{},
38-
{
39-
"_id": 0,
40-
"fetch_time": 1,
41-
},
42-
)
43-
.sort("fetch_time", -1)
44-
.limit(1)
45-
.next()
46-
)
47-
return result["fetch_time"]
35+
latest_record = await FTNTradeOrderDocument.find_one(sort={"fetchTime": "DESC"})
36+
37+
return latest_record.fetch_time # type: ignore
4838

4939

50-
async def get_latest_order(type_: Literal["buy", "sell"]) -> Optional[Dict[str, Any]]:
40+
async def get_latest_order(
41+
type_: Literal["buy", "sell"],
42+
) -> Optional[FTNTradeOrderDocument]:
5143
time = await get_data_update_time()
52-
try:
53-
return (
54-
await JPEP_FTN_MACKET_COLLECTION.find(
55-
{
56-
"fetch_time": time,
57-
"trade_type": type_,
58-
"amount.tradable": {"$ne": 0},
59-
}
60-
)
61-
.sort("price", 1 if type_ == "buy" else -1)
62-
.limit(1)
63-
.next()
64-
)
65-
except StopAsyncIteration: # 该侧没有挂单
66-
return None
44+
45+
return await FTNTradeOrderDocument.find_one(
46+
{"fetchTime": time, "type": type_, "amount.tradable": {"$ne": 0}},
47+
sort={"price": "ASC" if type_ == "buy" else "DESC"},
48+
)
6749

6850

6951
async def get_current_amount(type_: Literal["buy", "sell"]) -> Optional[int]:
7052
time = await get_data_update_time()
7153

72-
try:
73-
result = await JPEP_FTN_MACKET_COLLECTION.aggregate(
74-
[
75-
{
76-
"$match": {
77-
"fetch_time": time,
78-
"trade_type": type_,
79-
}
80-
},
81-
{
82-
"$group": {
83-
"_id": None,
84-
"sum": {
85-
"$sum": "$amount.tradable",
86-
},
54+
result = await FTNTradeOrderDocument.aggregate_one(
55+
[
56+
{
57+
"$match": {
58+
"fetchTime": time,
59+
"type": type_,
60+
}
61+
},
62+
{
63+
"$group": {
64+
"_id": None,
65+
"sum": {
66+
"$sum": "$amount.tradable",
8767
},
8868
},
89-
]
90-
).next()
91-
return result["sum"]
92-
except StopIteration: # 该侧没有挂单
93-
return None
69+
},
70+
]
71+
)
72+
73+
return result["sum"] if result else None
9474

9575

9676
async def get_price_history(
9777
type_: Literal["buy", "sell"], td: timedelta, time_unit: str
9878
) -> Dict[datetime, float]:
99-
result = JPEP_FTN_MACKET_COLLECTION.aggregate(
79+
result = FTNTradeOrderDocument.aggregate_many(
10080
[
10181
{
10282
"$match": {
103-
"trade_type": type_,
104-
"fetch_time": {
83+
"fetchTime": {
10584
"$gte": get_start_time(td),
10685
},
86+
"type": type_,
10787
},
10888
},
10989
{
11090
"$group": {
11191
"_id": (
11292
{
11393
"$dateTrunc": {
114-
"date": "$fetch_time",
94+
"date": "$fetchTime",
11595
"unit": time_unit,
11696
},
11797
}
11898
)
11999
if time_unit != "minute"
120-
else "$fetch_time",
100+
else "$fetchTime",
121101
"price": {
122102
"$min" if type_ == "buy" else "$max": "$price",
123103
},
@@ -137,19 +117,19 @@ async def get_price_history(
137117
async def get_amount_history(
138118
type_: Literal["buy", "sell"], td: timedelta, time_unit: str
139119
) -> Dict[datetime, float]:
140-
result = JPEP_FTN_MACKET_COLLECTION.aggregate(
120+
result = FTNTradeOrderDocument.aggregate_many(
141121
[
142122
{
143123
"$match": {
144-
"trade_type": type_,
145-
"fetch_time": {
124+
"fetchTime": {
146125
"$gte": get_start_time(td),
147126
},
127+
"type": type_,
148128
},
149129
},
150130
{
151131
"$group": {
152-
"_id": "$fetch_time",
132+
"_id": "$fetchTime",
153133
"amount": {
154134
"$sum": "$amount.tradable",
155135
},
@@ -189,12 +169,12 @@ async def get_current_amount_distribution(
189169
) -> Dict[float, int]:
190170
time = await get_data_update_time()
191171

192-
result = JPEP_FTN_MACKET_COLLECTION.aggregate(
172+
result = FTNTradeOrderDocument.aggregate_many(
193173
[
194174
{
195175
"$match": {
196-
"fetch_time": time,
197-
"trade_type": type_,
176+
"fetchTime": time,
177+
"type": type_,
198178
},
199179
},
200180
{
@@ -272,8 +252,8 @@ async def get_current_price_handler() -> Response:
272252
get_latest_order("buy"), get_latest_order("sell")
273253
)
274254

275-
buy_price = buy_order["price"] if buy_order else None
276-
sell_price = sell_order["price"] if sell_order else None
255+
buy_price = buy_order.price if buy_order else None
256+
sell_price = sell_order.price if sell_order else None
277257

278258
return success(
279259
data=GetCurrentPriceResponse(

0 commit comments

Comments
 (0)