mirror of
https://github.com/Nezumi-2711/astrbot_plugin_qq_group_daily_analysis.git
synced 2026-09-22 13:38:43 +00:00
feat(scrapbook): 群贤毕至添加头像
This commit is contained in:
@@ -77,16 +77,19 @@ async def debug_render(
|
||||
content="代码写得好,下班走得早。",
|
||||
sender="张三",
|
||||
reason="深刻揭示了程序员的生存法则",
|
||||
qq=123456789,
|
||||
),
|
||||
GoldenQuote(
|
||||
content="这个Bug我不修,它就是个Feature。",
|
||||
sender="李四",
|
||||
reason="经典的开发辩解",
|
||||
qq=987654321,
|
||||
),
|
||||
GoldenQuote(
|
||||
content="PHP是世界上最好的语言!",
|
||||
sender="王五",
|
||||
reason="引发了长达3小时的群聊大讨论",
|
||||
qq=112233445,
|
||||
),
|
||||
],
|
||||
emoji_count=156,
|
||||
|
||||
@@ -152,7 +152,12 @@ class GoldenQuoteAnalyzer(BaseAnalyzer):
|
||||
("http", "www", "/")
|
||||
):
|
||||
interesting_messages.append(
|
||||
{"sender": nickname, "time": msg_time, "content": text}
|
||||
{
|
||||
"sender": nickname,
|
||||
"time": msg_time,
|
||||
"content": text,
|
||||
"qq": sender.get("user_id", 0),
|
||||
}
|
||||
)
|
||||
|
||||
return interesting_messages
|
||||
@@ -183,7 +188,22 @@ class GoldenQuoteAnalyzer(BaseAnalyzer):
|
||||
return [], TokenUsage()
|
||||
|
||||
logger.info(f"开始从 {len(interesting_messages)} 条圣经消息中提取金句")
|
||||
return await self.analyze(interesting_messages, umo)
|
||||
logger.info(f"开始从 {len(interesting_messages)} 条圣经消息中提取金句")
|
||||
quotes, usage = await self.analyze(interesting_messages, umo)
|
||||
|
||||
# 回填QQ号
|
||||
for quote in quotes:
|
||||
for msg in interesting_messages:
|
||||
# 尝试匹配内容和发送者
|
||||
# 注意:LLM 可能会微调内容,这里使用包含匹配或精确匹配
|
||||
if (
|
||||
quote.content in msg["content"]
|
||||
or msg["content"] in quote.content
|
||||
) and quote.sender == msg["sender"]:
|
||||
quote.qq = msg.get("qq", 0)
|
||||
break
|
||||
|
||||
return quotes, usage
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"金句分析失败: {e}")
|
||||
|
||||
@@ -33,6 +33,7 @@ class GoldenQuote:
|
||||
content: str
|
||||
sender: str
|
||||
reason: str
|
||||
qq: int = 0
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -214,11 +214,15 @@ class ReportGenerator:
|
||||
max_golden_quotes = self.config_manager.get_max_golden_quotes()
|
||||
quotes_list = []
|
||||
for quote in stats.golden_quotes[:max_golden_quotes]:
|
||||
avatar_url = (
|
||||
await self._get_user_avatar(str(quote.qq)) if quote.qq else None
|
||||
)
|
||||
quotes_list.append(
|
||||
{
|
||||
"content": quote.content,
|
||||
"sender": quote.sender,
|
||||
"reason": quote.reason,
|
||||
"avatar_url": avatar_url,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -603,10 +603,110 @@
|
||||
.quote-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 85%;
|
||||
width: 100%;
|
||||
/* Occupy full width to allow internal flex to handle sizing */
|
||||
max-width: 90%;
|
||||
/* Limit max width */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.q-flex-container {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.q-user-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
width: 70px;
|
||||
/* Slightly narrower */
|
||||
}
|
||||
|
||||
.q-avatar-box {
|
||||
position: relative;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.q-avatar {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid #fff;
|
||||
background: #fff;
|
||||
object-fit: cover;
|
||||
/* Default base shadow */
|
||||
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Left/Odd: Blue Shadow */
|
||||
.quote-wrapper:nth-child(odd) .q-avatar {
|
||||
box-shadow: 0 0 0 2px var(--color-blue);
|
||||
}
|
||||
|
||||
/* Right/Even: Orange Shadow */
|
||||
.quote-wrapper:nth-child(even) .q-avatar {
|
||||
box-shadow: 0 0 0 2px var(--accent-orange);
|
||||
}
|
||||
|
||||
.q-content-col {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
align-items: flex-start;
|
||||
/* Default align left */
|
||||
}
|
||||
|
||||
.q-sender-name {
|
||||
font-family: var(--font-hand);
|
||||
font-size: 1.25rem;
|
||||
/* Larger size for cursive font */
|
||||
color: var(--ink-primary);
|
||||
margin-bottom: 2px;
|
||||
/* Reduce margin as underline takes space */
|
||||
margin-left: 10px;
|
||||
line-height: 1.2;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Underline Element */
|
||||
.q-sender-name::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background: var(--color-blue);
|
||||
opacity: 0.4;
|
||||
/* Marker pen feel */
|
||||
border-radius: 2px;
|
||||
margin-top: -6px;
|
||||
/* Overlap with text bottom */
|
||||
}
|
||||
|
||||
/* Right-aligned layout for even items */
|
||||
.quote-wrapper:nth-child(even) .q-flex-container {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(even) .q-content-col {
|
||||
align-items: flex-end;
|
||||
/* Align right */
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(even) .q-sender-name {
|
||||
margin-left: 0;
|
||||
margin-right: 15px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(even) .q-sender-name::after {
|
||||
background: var(--accent-orange);
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(odd) {
|
||||
align-self: flex-start;
|
||||
}
|
||||
@@ -619,62 +719,59 @@
|
||||
.q-bubble {
|
||||
background: #fff;
|
||||
border: 2px solid var(--ink-primary);
|
||||
padding: 20px 25px;
|
||||
padding: 15px 25px;
|
||||
border-radius: 20px;
|
||||
box-shadow: 5px 5px 0 var(--color-blue);
|
||||
box-shadow: 4px 4px 0 var(--color-blue);
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
width: fit-content;
|
||||
/* Dynamic width */
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(odd) .q-bubble {
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(even) .q-bubble {
|
||||
border-bottom-right-radius: 0;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 20px;
|
||||
/* Reset bottom right */
|
||||
background: var(--color-yellow);
|
||||
box-shadow: -5px 5px 0 var(--color-pink);
|
||||
box-shadow: -4px 4px 0 var(--color-pink);
|
||||
text-align: right;
|
||||
border-bottom-left-radius: 20px;
|
||||
}
|
||||
|
||||
.q-content {
|
||||
font-family: var(--font-title);
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.q-quote-mark {
|
||||
position: absolute;
|
||||
font-family: serif;
|
||||
font-size: 4rem;
|
||||
color: rgba(0, 0, 0, 0.05);
|
||||
top: -20px;
|
||||
left: -10px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.q-author {
|
||||
font-family: var(--font-hand);
|
||||
font-weight: bold;
|
||||
color: var(--ink-secondary);
|
||||
font-size: 0.95rem;
|
||||
display: none;
|
||||
/* Hide quote mark for cleaner chat look */
|
||||
}
|
||||
|
||||
.q-analysis-note {
|
||||
background: #fffde7;
|
||||
padding: 12px 15px;
|
||||
padding: 10px 15px;
|
||||
font-size: 0.9rem;
|
||||
color: #666;
|
||||
width: 95%;
|
||||
margin-top: -8px;
|
||||
width: fit-content;
|
||||
/* Fit content */
|
||||
max-width: 100%;
|
||||
margin-top: -5px;
|
||||
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #ddd;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-family: var(--font-body);
|
||||
line-height: 1.5;
|
||||
border-radius: 0 0 10px 10px;
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(odd) .q-analysis-note {
|
||||
|
||||
@@ -603,10 +603,110 @@
|
||||
.quote-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 85%;
|
||||
width: 100%;
|
||||
/* Occupy full width to allow internal flex to handle sizing */
|
||||
max-width: 90%;
|
||||
/* Limit max width */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.q-flex-container {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.q-user-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
width: 70px;
|
||||
/* Slightly narrower */
|
||||
}
|
||||
|
||||
.q-avatar-box {
|
||||
position: relative;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.q-avatar {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid #fff;
|
||||
background: #fff;
|
||||
object-fit: cover;
|
||||
/* Default base shadow */
|
||||
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Left/Odd: Blue Shadow */
|
||||
.quote-wrapper:nth-child(odd) .q-avatar {
|
||||
box-shadow: 0 0 0 2px var(--color-blue);
|
||||
}
|
||||
|
||||
/* Right/Even: Orange Shadow */
|
||||
.quote-wrapper:nth-child(even) .q-avatar {
|
||||
box-shadow: 0 0 0 2px var(--accent-orange);
|
||||
}
|
||||
|
||||
.q-content-col {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
align-items: flex-start;
|
||||
/* Default align left */
|
||||
}
|
||||
|
||||
.q-sender-name {
|
||||
font-family: 'Long Cang', cursive;
|
||||
font-size: 1.4rem;
|
||||
/* Larger size for cursive font */
|
||||
color: var(--ink-primary);
|
||||
margin-bottom: 2px;
|
||||
/* Reduce margin as underline takes space */
|
||||
margin-left: 10px;
|
||||
line-height: 1.2;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Underline Element */
|
||||
.q-sender-name::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background: var(--color-blue);
|
||||
opacity: 0.4;
|
||||
/* Marker pen feel */
|
||||
border-radius: 2px;
|
||||
margin-top: -6px;
|
||||
/* Overlap with text bottom */
|
||||
}
|
||||
|
||||
/* Right-aligned layout for even items */
|
||||
.quote-wrapper:nth-child(even) .q-flex-container {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(even) .q-content-col {
|
||||
align-items: flex-end;
|
||||
/* Align right */
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(even) .q-sender-name {
|
||||
margin-left: 0;
|
||||
margin-right: 15px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(even) .q-sender-name::after {
|
||||
background: var(--accent-orange);
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(odd) {
|
||||
align-self: flex-start;
|
||||
}
|
||||
@@ -619,62 +719,59 @@
|
||||
.q-bubble {
|
||||
background: #fff;
|
||||
border: 2px solid var(--ink-primary);
|
||||
padding: 20px 25px;
|
||||
padding: 15px 25px;
|
||||
border-radius: 20px;
|
||||
box-shadow: 5px 5px 0 var(--color-blue);
|
||||
box-shadow: 4px 4px 0 var(--color-blue);
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
width: fit-content;
|
||||
/* Dynamic width */
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(odd) .q-bubble {
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(even) .q-bubble {
|
||||
border-bottom-right-radius: 0;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 20px;
|
||||
/* Reset bottom right */
|
||||
background: var(--color-yellow);
|
||||
box-shadow: -5px 5px 0 var(--color-pink);
|
||||
box-shadow: -4px 4px 0 var(--color-pink);
|
||||
text-align: right;
|
||||
border-bottom-left-radius: 20px;
|
||||
}
|
||||
|
||||
.q-content {
|
||||
font-family: var(--font-title);
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.q-quote-mark {
|
||||
position: absolute;
|
||||
font-family: serif;
|
||||
font-size: 4rem;
|
||||
color: rgba(0, 0, 0, 0.05);
|
||||
top: -20px;
|
||||
left: -10px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.q-author {
|
||||
font-family: var(--font-hand);
|
||||
font-weight: bold;
|
||||
color: var(--ink-secondary);
|
||||
font-size: 0.95rem;
|
||||
display: none;
|
||||
/* Hide quote mark for cleaner chat look */
|
||||
}
|
||||
|
||||
.q-analysis-note {
|
||||
background: #fffde7;
|
||||
padding: 12px 15px;
|
||||
padding: 10px 15px;
|
||||
font-size: 0.9rem;
|
||||
color: #666;
|
||||
width: 95%;
|
||||
margin-top: -8px;
|
||||
width: fit-content;
|
||||
/* Fit content */
|
||||
max-width: 100%;
|
||||
margin-top: -5px;
|
||||
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #ddd;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-family: var(--font-body);
|
||||
line-height: 1.5;
|
||||
border-radius: 0 0 10px 10px;
|
||||
}
|
||||
|
||||
.quote-wrapper:nth-child(odd) .q-analysis-note {
|
||||
|
||||
@@ -8,14 +8,26 @@
|
||||
</div>
|
||||
{% for quote in quotes %}
|
||||
<div class="quote-wrapper">
|
||||
<div class="q-bubble">
|
||||
<div class="q-quote-mark">"</div>
|
||||
<div class="q-content">{{ quote.content }}</div>
|
||||
<div class="q-author">— {{ quote.sender }}</div>
|
||||
</div>
|
||||
<div class="q-analysis-note">
|
||||
<span class="note-label">🤣👉 AI 锐评:</span>
|
||||
{{ quote.reason }}
|
||||
<div class="q-flex-container">
|
||||
<div class="q-user-col">
|
||||
{% if quote.avatar_url %}
|
||||
<div class="q-avatar-box">
|
||||
<img src="{{ quote.avatar_url }}" class="q-avatar">
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="q-content-col">
|
||||
<div class="q-sender-name">{{ quote.sender }}</div>
|
||||
<div class="q-bubble">
|
||||
<div class="q-quote-mark">"</div>
|
||||
<div class="q-content">{{ quote.content }}</div>
|
||||
</div>
|
||||
<div class="q-analysis-note">
|
||||
<span class="note-label">🤣👉 AI 锐评:</span>
|
||||
{{ quote.reason }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
Reference in New Issue
Block a user