添加勋章

pull/3/head
John Smith 5 years ago
parent fe598369b7
commit ef4c0daede

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

@ -0,0 +1,121 @@
<template>
<yt-live-chat-author-badge-renderer :type="authorTypeText" v-if="isAdmin || privilegeType > 0">
<el-tooltip :content="readableAuthorTypeText" placement="top">
<div id="image" class="style-scope yt-live-chat-author-badge-renderer">
<yt-icon v-if="isAdmin" class="style-scope yt-live-chat-author-badge-renderer">
<svg viewBox="0 0 16 16" class="style-scope yt-icon" preserveAspectRatio="xMidYMid meet" focusable="false"
style="pointer-events: none; display: block; width: 100%; height: 100%;"
>
<g class="style-scope yt-icon">
<path class="style-scope yt-icon"
d="M9.64589146,7.05569719 C9.83346524,6.562372 9.93617022,6.02722257 9.93617022,5.46808511 C9.93617022,3.00042984 7.93574038,1 5.46808511,1 C4.90894765,1 4.37379823,1.10270499 3.88047304,1.29027875 L6.95744681,4.36725249 L4.36725255,6.95744681 L1.29027875,3.88047305 C1.10270498,4.37379824 1,4.90894766 1,5.46808511 C1,7.93574038 3.00042984,9.93617022 5.46808511,9.93617022 C6.02722256,9.93617022 6.56237198,9.83346524 7.05569716,9.64589147 L12.4098057,15 L15,12.4098057 L9.64589146,7.05569719 Z"
></path>
</g>
</svg>
</yt-icon>
<img v-else :src="`/static/img/icons/guard-level-${privilegeType}.png`"
class="style-scope yt-live-chat-author-badge-renderer" :alt="readableAuthorTypeText">
</div>
</el-tooltip>
</yt-live-chat-author-badge-renderer>
</template>
<script>
import * as constants from './constants'
export default {
name: 'AuthorBadge',
props: {
isAdmin: Boolean,
privilegeType: Number
},
computed: {
authorTypeText() {
if (this.isAdmin) {
return 'moderator'
}
return this.privilegeType > 0 ? 'member' : ''
},
readableAuthorTypeText() {
if (this.isAdmin) {
return '管理员'
}
return constants.GUARD_LEVEL_TO_TEXT[this.privilegeType]
}
}
}
</script>
<!-- yt-live-chat-author-badge-renderer -->
<style>
canvas.yt-live-chat-author-badge-renderer, caption.yt-live-chat-author-badge-renderer, center.yt-live-chat-author-badge-renderer, cite.yt-live-chat-author-badge-renderer, code.yt-live-chat-author-badge-renderer, dd.yt-live-chat-author-badge-renderer, del.yt-live-chat-author-badge-renderer, dfn.yt-live-chat-author-badge-renderer, div.yt-live-chat-author-badge-renderer, dl.yt-live-chat-author-badge-renderer, dt.yt-live-chat-author-badge-renderer, em.yt-live-chat-author-badge-renderer, embed.yt-live-chat-author-badge-renderer, fieldset.yt-live-chat-author-badge-renderer, font.yt-live-chat-author-badge-renderer, form.yt-live-chat-author-badge-renderer, h1.yt-live-chat-author-badge-renderer, h2.yt-live-chat-author-badge-renderer, h3.yt-live-chat-author-badge-renderer, h4.yt-live-chat-author-badge-renderer, h5.yt-live-chat-author-badge-renderer, h6.yt-live-chat-author-badge-renderer, hr.yt-live-chat-author-badge-renderer, i.yt-live-chat-author-badge-renderer, iframe.yt-live-chat-author-badge-renderer, img.yt-live-chat-author-badge-renderer, ins.yt-live-chat-author-badge-renderer, kbd.yt-live-chat-author-badge-renderer, label.yt-live-chat-author-badge-renderer, legend.yt-live-chat-author-badge-renderer, li.yt-live-chat-author-badge-renderer, menu.yt-live-chat-author-badge-renderer, object.yt-live-chat-author-badge-renderer, ol.yt-live-chat-author-badge-renderer, p.yt-live-chat-author-badge-renderer, pre.yt-live-chat-author-badge-renderer, q.yt-live-chat-author-badge-renderer, s.yt-live-chat-author-badge-renderer, samp.yt-live-chat-author-badge-renderer, small.yt-live-chat-author-badge-renderer, span.yt-live-chat-author-badge-renderer, strike.yt-live-chat-author-badge-renderer, strong.yt-live-chat-author-badge-renderer, sub.yt-live-chat-author-badge-renderer, sup.yt-live-chat-author-badge-renderer, table.yt-live-chat-author-badge-renderer, tbody.yt-live-chat-author-badge-renderer, td.yt-live-chat-author-badge-renderer, tfoot.yt-live-chat-author-badge-renderer, th.yt-live-chat-author-badge-renderer, thead.yt-live-chat-author-badge-renderer, tr.yt-live-chat-author-badge-renderer, tt.yt-live-chat-author-badge-renderer, u.yt-live-chat-author-badge-renderer, ul.yt-live-chat-author-badge-renderer, var.yt-live-chat-author-badge-renderer {
margin: 0;
padding: 0;
border: 0;
background: transparent;
}
.yt-live-chat-author-badge-renderer[hidden] {
display: none !important;
}
yt-live-chat-author-badge-renderer {
display: inline-block;
}
yt-live-chat-author-badge-renderer[type='moderator'] {
color: var(--yt-live-chat-moderator-color, #5e84f1);
}
yt-live-chat-author-badge-renderer[type='owner'] {
color: var(--yt-live-chat-owner-color, #ffd600);
}
yt-live-chat-author-badge-renderer[type='member'] {
color: var(--yt-live-chat-sponsor-color, #107516);
}
yt-live-chat-author-badge-renderer[type='verified'] {
color: #999;
}
img.yt-live-chat-author-badge-renderer, yt-icon.yt-live-chat-author-badge-renderer {
display: block;
width: 16px;
height: 16px;
}
</style>
<!-- yt-icon -->
<style>
canvas.yt-icon, caption.yt-icon, center.yt-icon, cite.yt-icon, code.yt-icon, dd.yt-icon, del.yt-icon, dfn.yt-icon, div.yt-icon, dl.yt-icon, dt.yt-icon, em.yt-icon, embed.yt-icon, fieldset.yt-icon, font.yt-icon, form.yt-icon, h1.yt-icon, h2.yt-icon, h3.yt-icon, h4.yt-icon, h5.yt-icon, h6.yt-icon, hr.yt-icon, i.yt-icon, iframe.yt-icon, img.yt-icon, ins.yt-icon, kbd.yt-icon, label.yt-icon, legend.yt-icon, li.yt-icon, menu.yt-icon, object.yt-icon, ol.yt-icon, p.yt-icon, pre.yt-icon, q.yt-icon, s.yt-icon, samp.yt-icon, small.yt-icon, span.yt-icon, strike.yt-icon, strong.yt-icon, sub.yt-icon, sup.yt-icon, table.yt-icon, tbody.yt-icon, td.yt-icon, tfoot.yt-icon, th.yt-icon, thead.yt-icon, tr.yt-icon, tt.yt-icon, u.yt-icon, ul.yt-icon, var.yt-icon {
margin: 0;
padding: 0;
border: 0;
background: transparent;
}
.yt-icon[hidden] {
display: none !important;
}
yt-icon, .yt-icon-container.yt-icon {
display: inline-flex;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
position: relative;
vertical-align: middle;
fill: currentcolor;
stroke: none;
width: var(--iron-icon-width, 24px);
height: var(--iron-icon-height, 24px);
}
yt-icon.external-container {
display: none !important;
}
</style>

@ -0,0 +1,88 @@
<template>
<yt-img-shadow class="no-transition" :height="height" :width="width" style="background-color: transparent;" loaded>
<img id="img" class="style-scope yt-img-shadow" alt="" :height="height" :width="width" :src="imgUrl">
</yt-img-shadow>
</template>
<script>
export default {
name: 'ImgShadow',
props: {
imgUrl: String,
height: String,
width: String
}
}
</script>
<!-- yt-img-shadow -->
<style>
canvas.yt-img-shadow, caption.yt-img-shadow, center.yt-img-shadow, cite.yt-img-shadow, code.yt-img-shadow, dd.yt-img-shadow, del.yt-img-shadow, dfn.yt-img-shadow, div.yt-img-shadow, dl.yt-img-shadow, dt.yt-img-shadow, em.yt-img-shadow, embed.yt-img-shadow, fieldset.yt-img-shadow, font.yt-img-shadow, form.yt-img-shadow, h1.yt-img-shadow, h2.yt-img-shadow, h3.yt-img-shadow, h4.yt-img-shadow, h5.yt-img-shadow, h6.yt-img-shadow, hr.yt-img-shadow, i.yt-img-shadow, iframe.yt-img-shadow, img.yt-img-shadow, ins.yt-img-shadow, kbd.yt-img-shadow, label.yt-img-shadow, legend.yt-img-shadow, li.yt-img-shadow, menu.yt-img-shadow, object.yt-img-shadow, ol.yt-img-shadow, p.yt-img-shadow, pre.yt-img-shadow, q.yt-img-shadow, s.yt-img-shadow, samp.yt-img-shadow, small.yt-img-shadow, span.yt-img-shadow, strike.yt-img-shadow, strong.yt-img-shadow, sub.yt-img-shadow, sup.yt-img-shadow, table.yt-img-shadow, tbody.yt-img-shadow, td.yt-img-shadow, tfoot.yt-img-shadow, th.yt-img-shadow, thead.yt-img-shadow, tr.yt-img-shadow, tt.yt-img-shadow, u.yt-img-shadow, ul.yt-img-shadow, var.yt-img-shadow {
margin: 0;
padding: 0;
border: 0;
background: transparent;
}
.yt-img-shadow[hidden] {
display: none !important;
}
yt-img-shadow {
display: inline-block;
opacity: 0;
transition: opacity 0.2s;
-ms-flex: none;
-webkit-flex: none;
flex: none;
}
yt-img-shadow.no-transition {
opacity: 1;
transition: none;
}
yt-img-shadow.with-placeholder {
background-color: transparent;
min-height: unset;
min-width: unset;
}
yt-img-shadow[loaded] {
opacity: 1;
}
yt-img-shadow.empty img.yt-img-shadow {
visibility: hidden;
}
yt-img-shadow[object-fit="FILL"] img.yt-img-shadow, yt-img-shadow[fit] img.yt-img-shadow {
width: 100%;
height: 100%;
}
yt-img-shadow[object-fit="COVER"] img.yt-img-shadow {
width: 100%;
height: 100%;
object-fit: cover;
}
yt-img-shadow[object-fit="CONTAIN"] img.yt-img-shadow {
width: 100%;
height: 100%;
object-fit: contain;
}
yt-img-shadow[object-position="LEFT"] img.yt-img-shadow {
object-position: left;
}
img.yt-img-shadow {
display: block;
margin-left: auto;
margin-right: auto;
max-height: none;
max-width: 100%;
border-radius: none;
}
</style>

@ -1,11 +1,9 @@
<template>
<yt-live-chat-legacy-paid-message-renderer class="style-scope yt-live-chat-item-list-renderer">
<div id="card" class="style-scope yt-live-chat-legacy-paid-message-renderer">
<yt-img-shadow id="author-photo" class="style-scope yt-live-chat-legacy-paid-message-renderer no-transition"
height="40" width="40" style="background-color: transparent;" loaded
>
<img id="img" class="style-scope yt-img-shadow" alt="" height="40" width="40" :src="avatarUrl">
</yt-img-shadow>
<img-shadow id="author-photo" height="40" width="40" class="style-scope yt-live-chat-legacy-paid-message-renderer"
:imgUrl="avatarUrl"
></img-shadow>
<div id="content" class="style-scope yt-live-chat-legacy-paid-message-renderer">
<div id="content-primary-column" class="style-scope yt-live-chat-legacy-paid-message-renderer">
<div id="author-name" class="style-scope yt-live-chat-legacy-paid-message-renderer">{{authorName}}</div>
@ -22,8 +20,13 @@
</template>
<script>
import ImgShadow from './ImgShadow.vue'
export default {
name: 'LegacyPaidMessage',
components: {
ImgShadow
},
props: {
avatarUrl: String,
authorName: String,

@ -10,11 +10,9 @@
>
<div id="card" class="style-scope yt-live-chat-paid-message-renderer">
<div id="header" class="style-scope yt-live-chat-paid-message-renderer">
<yt-img-shadow id="author-photo" class="style-scope yt-live-chat-legacy-paid-message-renderer no-transition"
height="40" width="40" style="background-color: transparent;" loaded
>
<img id="img" class="style-scope yt-img-shadow" alt="" height="40" width="40" :src="avatarUrl">
</yt-img-shadow>
<img-shadow id="author-photo" height="40" width="40" class="style-scope yt-live-chat-paid-message-renderer"
:imgUrl="avatarUrl"
></img-shadow>
<div id="header-content" class="style-scope yt-live-chat-paid-message-renderer">
<div id="header-content-primary-column" class="style-scope yt-live-chat-paid-message-renderer">
<div id="author-name" class="style-scope yt-live-chat-paid-message-renderer">{{authorName}}</div>
@ -33,6 +31,8 @@
</template>
<script>
import ImgShadow from './ImgShadow.vue'
const COLORS = [
{ // $100
price: 1245, // >= 1245
@ -95,6 +95,9 @@ const COLORS = [
export default {
name: 'PaidMessage',
components: {
ImgShadow
},
props: {
avatarUrl: String,
authorName: String,

@ -1,18 +1,21 @@
<template>
<yt-live-chat-text-message-renderer :author-type="authorTypeText">
<yt-img-shadow id="author-photo" class="no-transition style-scope yt-live-chat-text-message-renderer" height="24"
width="24" style="background-color: transparent;" loaded
>
<img id="img" class="style-scope yt-img-shadow" alt="" height="24" width="24" :src="avatarUrl">
</yt-img-shadow>
<img-shadow id="author-photo" height="24" width="24" class="style-scope yt-live-chat-text-message-renderer"
:imgUrl="avatarUrl"
></img-shadow>
<div id="content" class="style-scope yt-live-chat-text-message-renderer">
<span id="timestamp" class="style-scope yt-live-chat-text-message-renderer">{{time}}</span>
<yt-live-chat-author-chip class="style-scope yt-live-chat-text-message-renderer">
<span id="author-name" dir="auto" class="style-scope yt-live-chat-author-chip" :type="authorTypeText">
{{authorName}}
<!-- 这里是已验证勋章 -->
<span id="chip-badges" class="style-scope yt-live-chat-author-chip"></span>
</span>
<span id="chat-badges" class="style-scope yt-live-chat-author-chip"></span>
<span id="chat-badges" class="style-scope yt-live-chat-author-chip">
<author-badge class="style-scope yt-live-chat-author-chip"
:isAdmin="authorType === 2" :privilegeType="privilegeType"
></author-badge>
</span>
</yt-live-chat-author-chip>
<span id="message" class="style-scope yt-live-chat-text-message-renderer">{{content}}</span>
<el-badge :value="repeated" :max="99" v-show="repeated > 1" class="style-scope yt-live-chat-text-message-renderer"
@ -23,28 +26,31 @@
</template>
<script>
const AUTHOR_TYPE_TO_TEXT = [
'',
'member', //
'moderator', //
'owner' //
]
import ImgShadow from './ImgShadow.vue'
import AuthorBadge from './AuthorBadge.vue'
import * as constants from './constants'
const REPEATED_MARK_COLOR_START = [64, 158, 255]
const REPEATED_MARK_COLOR_END = [245, 108, 108]
export default {
name: 'TextMessage',
components: {
ImgShadow,
AuthorBadge
},
props: {
avatarUrl: String,
time: String,
authorName: String,
authorType: Number,
content: String,
privilegeType: Number,
repeated: Number
},
computed: {
authorTypeText() {
return AUTHOR_TYPE_TO_TEXT[this.authorType]
return constants.AUTHOR_TYPE_TO_TEXT[this.authorType]
},
repeatedMarkColor() {
let color
@ -313,78 +319,6 @@ yt-live-chat-text-message-renderer[is-dimmed]::before {
}
</style>
<!-- yt-img-shadow -->
<style>
canvas.yt-img-shadow, caption.yt-img-shadow, center.yt-img-shadow, cite.yt-img-shadow, code.yt-img-shadow, dd.yt-img-shadow, del.yt-img-shadow, dfn.yt-img-shadow, div.yt-img-shadow, dl.yt-img-shadow, dt.yt-img-shadow, em.yt-img-shadow, embed.yt-img-shadow, fieldset.yt-img-shadow, font.yt-img-shadow, form.yt-img-shadow, h1.yt-img-shadow, h2.yt-img-shadow, h3.yt-img-shadow, h4.yt-img-shadow, h5.yt-img-shadow, h6.yt-img-shadow, hr.yt-img-shadow, i.yt-img-shadow, iframe.yt-img-shadow, img.yt-img-shadow, ins.yt-img-shadow, kbd.yt-img-shadow, label.yt-img-shadow, legend.yt-img-shadow, li.yt-img-shadow, menu.yt-img-shadow, object.yt-img-shadow, ol.yt-img-shadow, p.yt-img-shadow, pre.yt-img-shadow, q.yt-img-shadow, s.yt-img-shadow, samp.yt-img-shadow, small.yt-img-shadow, span.yt-img-shadow, strike.yt-img-shadow, strong.yt-img-shadow, sub.yt-img-shadow, sup.yt-img-shadow, table.yt-img-shadow, tbody.yt-img-shadow, td.yt-img-shadow, tfoot.yt-img-shadow, th.yt-img-shadow, thead.yt-img-shadow, tr.yt-img-shadow, tt.yt-img-shadow, u.yt-img-shadow, ul.yt-img-shadow, var.yt-img-shadow {
margin: 0;
padding: 0;
border: 0;
background: transparent;
}
.yt-img-shadow[hidden] {
display: none !important;
}
yt-img-shadow {
display: inline-block;
opacity: 0;
transition: opacity 0.2s;
-ms-flex: none;
-webkit-flex: none;
flex: none;
}
yt-img-shadow.no-transition {
opacity: 1;
transition: none;
}
yt-img-shadow.with-placeholder {
background-color: transparent;
min-height: unset;
min-width: unset;
}
yt-img-shadow[loaded] {
opacity: 1;
}
yt-img-shadow.empty img.yt-img-shadow {
visibility: hidden;
}
yt-img-shadow[object-fit="FILL"] img.yt-img-shadow, yt-img-shadow[fit] img.yt-img-shadow {
width: 100%;
height: 100%;
}
yt-img-shadow[object-fit="COVER"] img.yt-img-shadow {
width: 100%;
height: 100%;
object-fit: cover;
}
yt-img-shadow[object-fit="CONTAIN"] img.yt-img-shadow {
width: 100%;
height: 100%;
object-fit: contain;
}
yt-img-shadow[object-position="LEFT"] img.yt-img-shadow {
object-position: left;
}
img.yt-img-shadow {
display: block;
margin-left: auto;
margin-right: auto;
max-height: none;
max-width: 100%;
border-radius: none;
}
</style>
<!-- yt-live-chat-author-chip -->
<style>
canvas.yt-live-chat-author-chip, caption.yt-live-chat-author-chip, center.yt-live-chat-author-chip, cite.yt-live-chat-author-chip, code.yt-live-chat-author-chip, dd.yt-live-chat-author-chip, del.yt-live-chat-author-chip, dfn.yt-live-chat-author-chip, div.yt-live-chat-author-chip, dl.yt-live-chat-author-chip, dt.yt-live-chat-author-chip, em.yt-live-chat-author-chip, embed.yt-live-chat-author-chip, fieldset.yt-live-chat-author-chip, font.yt-live-chat-author-chip, form.yt-live-chat-author-chip, h1.yt-live-chat-author-chip, h2.yt-live-chat-author-chip, h3.yt-live-chat-author-chip, h4.yt-live-chat-author-chip, h5.yt-live-chat-author-chip, h6.yt-live-chat-author-chip, hr.yt-live-chat-author-chip, i.yt-live-chat-author-chip, iframe.yt-live-chat-author-chip, img.yt-live-chat-author-chip, ins.yt-live-chat-author-chip, kbd.yt-live-chat-author-chip, label.yt-live-chat-author-chip, legend.yt-live-chat-author-chip, li.yt-live-chat-author-chip, menu.yt-live-chat-author-chip, object.yt-live-chat-author-chip, ol.yt-live-chat-author-chip, p.yt-live-chat-author-chip, pre.yt-live-chat-author-chip, q.yt-live-chat-author-chip, s.yt-live-chat-author-chip, samp.yt-live-chat-author-chip, small.yt-live-chat-author-chip, span.yt-live-chat-author-chip, strike.yt-live-chat-author-chip, strong.yt-live-chat-author-chip, sub.yt-live-chat-author-chip, sup.yt-live-chat-author-chip, table.yt-live-chat-author-chip, tbody.yt-live-chat-author-chip, td.yt-live-chat-author-chip, tfoot.yt-live-chat-author-chip, th.yt-live-chat-author-chip, thead.yt-live-chat-author-chip, tr.yt-live-chat-author-chip, tt.yt-live-chat-author-chip, u.yt-live-chat-author-chip, ul.yt-live-chat-author-chip, var.yt-live-chat-author-chip {

@ -0,0 +1,17 @@
export const AUTHRO_TYPE_MEMBER = 1
export const AUTHRO_TYPE_ADMIN = 2
export const AUTHRO_TYPE_OWNER = 3
export const AUTHOR_TYPE_TO_TEXT = [
'',
'member', // 舰队
'moderator', // 房管
'owner' // 主播
]
export const GUARD_LEVEL_TO_TEXT = [
'',
'总督',
'提督',
'舰长'
]

@ -22,7 +22,8 @@
<text-message :key="message.id" v-if="message.type == 0"
class="style-scope yt-live-chat-item-list-renderer"
:avatarUrl="message.avatarUrl" :time="message.time" :authorName="message.authorName"
:authorType="message.authorType" :content="message.content" :repeated="message.repeated"
:authorType="message.authorType" :content="message.content" :privilegeType="message.privilegeType"
:repeated="message.repeated"
></text-message>
<legacy-paid-message :key="message.id" v-else-if="message.type == 1"
class="style-scope yt-live-chat-item-list-renderer"

@ -10,7 +10,7 @@
<el-form-item label="房间ID" required prop="roomId">
<el-input v-model.number="form.roomId" type="number" min="1"></el-input>
</el-form-item>
<el-form-item label="最低显示礼物价格" prop="minGiftPrice">
<el-form-item label="最低显示礼物价格(元)" prop="minGiftPrice">
<el-input v-model.number="form.minGiftPrice" type="number" min="0"></el-input>
</el-form-item>
<el-form-item label="合并相似弹幕" prop="mergeSimilarDanmaku">

@ -9,7 +9,7 @@ import ChatRenderer from '@/components/ChatRenderer'
const COMMAND_JOIN_ROOM = 0
const COMMAND_ADD_TEXT = 1
const COMMAND_ADD_GIFT = 2
const COMMAND_ADD_VIP = 3
const COMMAND_ADD_MEMBER = 3
export default {
name: 'Room',
@ -74,6 +74,7 @@ export default {
authorName: data.authorName,
authorType: data.authorType,
content: data.content,
privilegeType: data.privilegeType,
repeated: 1
}
break
@ -92,7 +93,7 @@ export default {
}
break
}
case COMMAND_ADD_VIP:
case COMMAND_ADD_MEMBER:
message = {
id: this.nextId++,
type: 1, // LegacyPaidMessage

@ -179,7 +179,7 @@
<h3>结果</h3>
<el-form-item label="CSS">
<el-input v-model="result" ref="result" type="textarea" :rows="10"></el-input>
<el-input v-model="result" ref="result" type="textarea" :rows="20"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="copyResult"></el-button>
@ -203,6 +203,7 @@ import _ from 'lodash'
import stylegen from './stylegen'
import fonts from './fonts'
import ChatRenderer from '@/components/ChatRenderer'
import * as constants from '@/components/ChatRenderer/constants'
let time = new Date()
let textMessageTemplate = {
@ -213,6 +214,7 @@ let textMessageTemplate = {
authorName: '',
authorType: 0,
content: '',
privilegeType: 0,
repeated: 1
}
let legacyPaidMessageTemplate = {
@ -245,14 +247,15 @@ const EXAMPLE_MESSAGES = [
...textMessageTemplate,
id: nextId++,
authorName: 'member舰长',
authorType: 1,
authorType: constants.AUTHRO_TYPE_MEMBER,
content: '草',
privilegeType: 3,
repeated: 3
}, {
...textMessageTemplate,
id: nextId++,
authorName: 'admin房管',
authorType: 2,
authorType: constants.AUTHRO_TYPE_ADMIN,
content: 'kksk'
}, {
...legacyPaidMessageTemplate,
@ -269,7 +272,7 @@ const EXAMPLE_MESSAGES = [
...textMessageTemplate,
id: nextId++,
authorName: 'streamer主播',
authorType: 3,
authorType: constants.AUTHRO_TYPE_OWNER,
content: '感谢石油佬送的小电视'
}, {
...paidMessageTemplate,
@ -325,11 +328,11 @@ export default {
}
},
watch: {
computedResult: _.debounce(function (val) {
computedResult: _.debounce(function(val) {
this.result = val
stylegen.setLocalConfig(this.form)
}, 500),
result (val) {
result(val) {
this.exampleCss = val.replace(/^body\b/gm, '#fakebody')
}
}

@ -155,7 +155,7 @@ yt-live-chat-legacy-paid-message-renderer #author-photo img {
}
/* Hide badges. */
yt-live-chat-text-message-renderer #author-badges {
yt-live-chat-text-message-renderer #chat-badges {
${config.showBadges ? '' : 'display: none !important;'}
vertical-align: text-top !important;
}

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import argparse
import webbrowser
import logging
import os
@ -46,6 +47,8 @@ def main():
)
app.listen(args.port, args.host)
logger.info('服务器启动:%s:%d', args.host, args.port)
url = 'http://localhost' if args.port == 80 else f'http://localhost:{args.port}'
webbrowser.open(url)
tornado.ioloop.IOLoop.current().start()

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import asyncio
import datetime
import enum
import json
import logging
@ -19,20 +20,31 @@ class Command(enum.IntEnum):
JOIN_ROOM = 0
ADD_TEXT = 1
ADD_GIFT = 2
ADD_VIP = 3
ADD_MEMBER = 3
_http_session = aiohttp.ClientSession()
_avatar_url_cache: Dict[int, str] = {}
_last_avatar_failed_time = None
async def get_avatar_url(user_id):
if user_id in _avatar_url_cache:
return _avatar_url_cache[user_id]
global _last_avatar_failed_time
if _last_avatar_failed_time is not None:
if (datetime.datetime.now() - _last_avatar_failed_time).seconds < 5 * 60:
# 5分钟以内被ban
return 'https://static.hdslb.com/images/member/noface.gif'
else:
_last_avatar_failed_time = None
async with _http_session.get('https://api.bilibili.com/x/space/acc/info',
params={'mid': user_id}) as r:
if r.status != 200: # 可能会被B站ban
logger.error('获取头像失败status=%d %s uid=%d', r.status, r.reason, user_id)
logger.warning('获取头像失败status=%d %s uid=%d', r.status, r.reason, user_id)
_last_avatar_failed_time = datetime.datetime.now()
return 'https://static.hdslb.com/images/member/noface.gif'
data = await r.json()
url = data['data']['face']
@ -40,7 +52,7 @@ async def get_avatar_url(user_id):
url += '@48w_48h'
_avatar_url_cache[user_id] = url
if len(_avatar_url_cache) > 10000:
if len(_avatar_url_cache) > 50000:
for _, key in zip(range(100), _avatar_url_cache):
del _avatar_url_cache[key]
@ -96,7 +108,7 @@ class Room(blivedm.BLiveClient):
})
async def _on_buy_guard(self, message: blivedm.GuardBuyMessage):
self.send_message(Command.ADD_VIP, {
self.send_message(Command.ADD_MEMBER, {
'avatarUrl': await get_avatar_url(message.uid),
'timestamp': message.start_time,
'authorName': message.username
@ -160,7 +172,7 @@ class RoomManager:
text_data['authorType'] = 3
text_data['content'] = "I can eat glass, it doesn't hurt me."
room.send_message(Command.ADD_TEXT, text_data)
room.send_message(Command.ADD_VIP, vip_data)
room.send_message(Command.ADD_MEMBER, vip_data)
room.send_message(Command.ADD_GIFT, gift_data)
gift_data['giftName'] = '节奏风暴'
gift_data['totalCoin'] = 100000

Loading…
Cancel
Save