mirror of
https://github.com/xfgryujk/blivechat.git
synced 2025-02-11 04:10:48 +08:00
前端配置放在URL参数
This commit is contained in:
parent
8d4e8e6f35
commit
cae06858fc
@ -23,7 +23,7 @@
|
|||||||
```
|
```
|
||||||
3. 用浏览器打开[http://localhost:12450](http://localhost:12450),输入房间ID,保存配置,复制房间URL
|
3. 用浏览器打开[http://localhost:12450](http://localhost:12450),输入房间ID,保存配置,复制房间URL
|
||||||
4. 用样式生成器生成样式,复制CSS
|
4. 用样式生成器生成样式,复制CSS
|
||||||
5. 在OBS中添加浏览器源,输入URL和自定义CSS,或者可以在首页的样式设置里输入CSS
|
5. 在OBS中添加浏览器源,输入URL和自定义CSS
|
||||||
|
|
||||||
### 公共服务器
|
### 公共服务器
|
||||||
请优先在本地使用,使用公共服务器会有更大的弹幕延迟,而且服务器故障时可能出现直播事故
|
请优先在本地使用,使用公共服务器会有更大的弹幕延迟,而且服务器故障时可能出现直播事故
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import axios from 'axios'
|
|
||||||
|
|
||||||
import {mergeConfig} from '@/utils'
|
import {mergeConfig} from '@/utils'
|
||||||
|
|
||||||
export const DEFAULT_CONFIG = {
|
export const DEFAULT_CONFIG = {
|
||||||
@ -15,9 +13,7 @@ export const DEFAULT_CONFIG = {
|
|||||||
blockNotMobileVerified: true,
|
blockNotMobileVerified: true,
|
||||||
blockKeywords: '',
|
blockKeywords: '',
|
||||||
blockUsers: '',
|
blockUsers: '',
|
||||||
blockMedalLevel: 0,
|
blockMedalLevel: 0
|
||||||
|
|
||||||
css: ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setLocalConfig (config) {
|
export function setLocalConfig (config) {
|
||||||
@ -31,27 +27,3 @@ export function getLocalConfig () {
|
|||||||
}
|
}
|
||||||
return mergeConfig(JSON.parse(window.localStorage.config), DEFAULT_CONFIG)
|
return mergeConfig(JSON.parse(window.localStorage.config), DEFAULT_CONFIG)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createRemoteConfig (config) {
|
|
||||||
config = mergeConfig(config, DEFAULT_CONFIG)
|
|
||||||
return (await axios.post('/config', config)).data
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function setRemoteConfig (id, config) {
|
|
||||||
config = mergeConfig(config, DEFAULT_CONFIG)
|
|
||||||
return (await axios.put(`/config/${id}`, config)).data
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getRemoteConfig (id) {
|
|
||||||
let config = (await axios.get(`/config/${id}`)).data
|
|
||||||
return mergeConfig(config, DEFAULT_CONFIG)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
DEFAULT_CONFIG,
|
|
||||||
setLocalConfig,
|
|
||||||
getLocalConfig,
|
|
||||||
createRemoteConfig,
|
|
||||||
setRemoteConfig,
|
|
||||||
getRemoteConfig
|
|
||||||
}
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ImgShadow from './ImgShadow.vue'
|
import ImgShadow from './ImgShadow.vue'
|
||||||
import utils from '@/utils'
|
import * as utils from '@/utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'LegacyPaidMessage',
|
name: 'LegacyPaidMessage',
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ImgShadow from './ImgShadow.vue'
|
import ImgShadow from './ImgShadow.vue'
|
||||||
import * as constants from './constants'
|
import * as constants from './constants'
|
||||||
import utils from '@/utils'
|
import * as utils from '@/utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PaidMessage',
|
name: 'PaidMessage',
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
import ImgShadow from './ImgShadow.vue'
|
import ImgShadow from './ImgShadow.vue'
|
||||||
import AuthorBadge from './AuthorBadge.vue'
|
import AuthorBadge from './AuthorBadge.vue'
|
||||||
import * as constants from './constants'
|
import * as constants from './constants'
|
||||||
import utils from '@/utils'
|
import * as utils from '@/utils'
|
||||||
|
|
||||||
// HSL
|
// HSL
|
||||||
const REPEATED_MARK_COLOR_START = [210, 100.0, 62.5]
|
const REPEATED_MARK_COLOR_START = [210, 100.0, 62.5]
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import config from '@/api/config'
|
import * as config from '@/api/config'
|
||||||
import Ticker from './Ticker.vue'
|
import Ticker from './Ticker.vue'
|
||||||
import TextMessage from './TextMessage.vue'
|
import TextMessage from './TextMessage.vue'
|
||||||
import LegacyPaidMessage from './LegacyPaidMessage.vue'
|
import LegacyPaidMessage from './LegacyPaidMessage.vue'
|
||||||
|
@ -28,17 +28,12 @@ export default {
|
|||||||
blockUsers: 'Block users',
|
blockUsers: 'Block users',
|
||||||
blockMedalLevel: 'Block medal level lower than',
|
blockMedalLevel: 'Block medal level lower than',
|
||||||
|
|
||||||
style: 'Style',
|
|
||||||
|
|
||||||
roomUrl: 'Room URL',
|
roomUrl: 'Room URL',
|
||||||
copy: 'Copy',
|
copy: 'Copy',
|
||||||
saveConfig: 'Save config',
|
|
||||||
enterRoom: 'Enter room',
|
enterRoom: 'Enter room',
|
||||||
exportConfig: 'Export config',
|
exportConfig: 'Export config',
|
||||||
importConfig: 'Import config',
|
importConfig: 'Import config',
|
||||||
|
|
||||||
failedToSave: 'Failed to save: ',
|
|
||||||
successfullySaved: 'Successfully saved',
|
|
||||||
failedToParseConfig: 'Failed to parse config: '
|
failedToParseConfig: 'Failed to parse config: '
|
||||||
},
|
},
|
||||||
stylegen: {
|
stylegen: {
|
||||||
|
@ -28,17 +28,12 @@ export default {
|
|||||||
blockUsers: 'ブロックユーザー',
|
blockUsers: 'ブロックユーザー',
|
||||||
blockMedalLevel: 'ブロック勲章等級がx未満',
|
blockMedalLevel: 'ブロック勲章等級がx未満',
|
||||||
|
|
||||||
style: 'スタイル',
|
|
||||||
|
|
||||||
roomUrl: 'ルームのURL',
|
roomUrl: 'ルームのURL',
|
||||||
copy: 'コピー',
|
copy: 'コピー',
|
||||||
saveConfig: 'コンフィグを保存する',
|
|
||||||
enterRoom: 'ルームに入る',
|
enterRoom: 'ルームに入る',
|
||||||
exportConfig: 'コンフィグの導出',
|
exportConfig: 'コンフィグの導出',
|
||||||
importConfig: 'コンフィグの導入',
|
importConfig: 'コンフィグの導入',
|
||||||
|
|
||||||
failedToSave: '保存に失敗しました:',
|
|
||||||
successfullySaved: '保存に成功しました',
|
|
||||||
failedToParseConfig: 'コンフィグ解析に失敗しました'
|
failedToParseConfig: 'コンフィグ解析に失敗しました'
|
||||||
},
|
},
|
||||||
stylegen: {
|
stylegen: {
|
||||||
|
@ -28,17 +28,12 @@ export default {
|
|||||||
blockUsers: '屏蔽用户',
|
blockUsers: '屏蔽用户',
|
||||||
blockMedalLevel: '屏蔽当前直播间勋章等级低于',
|
blockMedalLevel: '屏蔽当前直播间勋章等级低于',
|
||||||
|
|
||||||
style: '样式',
|
|
||||||
|
|
||||||
roomUrl: '房间URL',
|
roomUrl: '房间URL',
|
||||||
copy: '复制',
|
copy: '复制',
|
||||||
saveConfig: '保存配置',
|
|
||||||
enterRoom: '进入房间',
|
enterRoom: '进入房间',
|
||||||
exportConfig: '导出配置',
|
exportConfig: '导出配置',
|
||||||
importConfig: '导入配置',
|
importConfig: '导入配置',
|
||||||
|
|
||||||
failedToSave: '保存失败:',
|
|
||||||
successfullySaved: '保存成功',
|
|
||||||
failedToParseConfig: '配置解析失败:'
|
failedToParseConfig: '配置解析失败:'
|
||||||
},
|
},
|
||||||
stylegen: {
|
stylegen: {
|
||||||
|
@ -6,6 +6,21 @@ export function mergeConfig (config, defaultConfig) {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toBool (val) {
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
return val !== 'false' && val !== ''
|
||||||
|
}
|
||||||
|
return !!val
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toInt (val, _default) {
|
||||||
|
let res = parseInt(val)
|
||||||
|
if (isNaN(res)) {
|
||||||
|
res = _default
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
export function formatCurrency (price) {
|
export function formatCurrency (price) {
|
||||||
return new Intl.NumberFormat('zh-CN', {
|
return new Intl.NumberFormat('zh-CN', {
|
||||||
minimumFractionDigits: price < 100 ? 2 : 0
|
minimumFractionDigits: price < 100 ? 2 : 0
|
||||||
@ -17,9 +32,3 @@ export function getTimeTextMinSec (date) {
|
|||||||
let sec = ('00' + date.getSeconds()).slice(-2)
|
let sec = ('00' + date.getSeconds()).slice(-2)
|
||||||
return `${min}:${sec}`
|
return `${min}:${sec}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
|
||||||
mergeConfig,
|
|
||||||
formatCurrency,
|
|
||||||
getTimeTextMinSec
|
|
||||||
}
|
|
||||||
|
@ -50,21 +50,14 @@
|
|||||||
<el-slider v-model="form.blockMedalLevel" show-input :min="0" :max="20"></el-slider>
|
<el-slider v-model="form.blockMedalLevel" show-input :min="0" :max="20"></el-slider>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane :label="$t('home.style')">
|
|
||||||
<el-form-item label="CSS">
|
|
||||||
<el-input v-model="form.css" type="textarea" :rows="20"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
<el-divider></el-divider>
|
<el-divider></el-divider>
|
||||||
<el-form-item :label="$t('home.roomUrl')" v-show="roomUrl">
|
<el-form-item :label="$t('home.roomUrl')">
|
||||||
<el-input ref="roomUrlInput" readonly :value="roomUrl" style="width: calc(100% - 6em); margin-right: 1em;"></el-input>
|
<el-input ref="roomUrlInput" readonly :value="roomUrl" style="width: calc(100% - 8em); margin-right: 1em;"></el-input>
|
||||||
<el-button type="primary" @click="copyUrl">{{$t('home.copy')}}</el-button>
|
<el-button type="primary" @click="copyUrl">{{$t('home.copy')}}</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="saveConfig">{{$t('home.saveConfig')}}</el-button>
|
|
||||||
<el-button type="primary" :disabled="!roomUrl" @click="enterRoom">{{$t('home.enterRoom')}}</el-button>
|
<el-button type="primary" :disabled="!roomUrl" @click="enterRoom">{{$t('home.enterRoom')}}</el-button>
|
||||||
<el-button type="primary" @click="exportConfig">{{$t('home.exportConfig')}}</el-button>
|
<el-button type="primary" @click="exportConfig">{{$t('home.exportConfig')}}</el-button>
|
||||||
<el-button type="primary" @click="importConfig">{{$t('home.importConfig')}}</el-button>
|
<el-button type="primary" @click="importConfig">{{$t('home.importConfig')}}</el-button>
|
||||||
@ -73,10 +66,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import _ from 'lodash'
|
||||||
import download from 'downloadjs'
|
import download from 'downloadjs'
|
||||||
|
|
||||||
import {mergeConfig} from '@/utils'
|
import {mergeConfig} from '@/utils'
|
||||||
import config from '@/api/config'
|
import * as config from '@/api/config'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Home',
|
name: 'Home',
|
||||||
@ -85,40 +79,27 @@ export default {
|
|||||||
form: {
|
form: {
|
||||||
roomId: parseInt(window.localStorage.roomId || '1'),
|
roomId: parseInt(window.localStorage.roomId || '1'),
|
||||||
...config.getLocalConfig()
|
...config.getLocalConfig()
|
||||||
},
|
}
|
||||||
roomUrl: ''
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
roomUrl() {
|
||||||
|
if (this.form.roomId === '') {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
let query = {...this.form}
|
||||||
|
delete query.roomId
|
||||||
|
let resolved = this.$router.resolve({name: 'room', params: {roomId: this.form.roomId}, query})
|
||||||
|
return `${window.location.protocol}//${window.location.host}${resolved.href}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
roomUrl: _.debounce(function() {
|
||||||
|
window.localStorage.roomId = this.form.roomId
|
||||||
|
config.setLocalConfig(this.form)
|
||||||
|
}, 500)
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
saveConfig() {
|
|
||||||
this.$refs.form.validate(async valid => {
|
|
||||||
if (!valid) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
window.localStorage.roomId = this.form.roomId
|
|
||||||
config.setLocalConfig(this.form)
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (window.localStorage.configId) {
|
|
||||||
try {
|
|
||||||
await config.setRemoteConfig(window.localStorage.configId, this.form)
|
|
||||||
} catch (e) { // 404
|
|
||||||
window.localStorage.configId = (await config.createRemoteConfig(this.form)).id
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
window.localStorage.configId = (await config.createRemoteConfig(this.form)).id
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
this.$message.error(this.$t('home.failedToSave') + e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$message({message: this.$t('home.successfullySaved'), type: 'success'})
|
|
||||||
|
|
||||||
let resolved = this.$router.resolve({name: 'room', params: {roomId: this.form.roomId},
|
|
||||||
query: {config_id: window.localStorage.configId}})
|
|
||||||
this.roomUrl = `${window.location.protocol}//${window.location.host}${resolved.href}`
|
|
||||||
})
|
|
||||||
},
|
|
||||||
enterRoom() {
|
enterRoom() {
|
||||||
window.open(this.roomUrl, `room ${this.form.roomId}`, 'menubar=0,location=0,scrollbars=0,toolbar=0,width=600,height=600')
|
window.open(this.roomUrl, `room ${this.form.roomId}`, 'menubar=0,location=0,scrollbars=0,toolbar=0,width=600,height=600')
|
||||||
},
|
},
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<chat-renderer ref="renderer" :css="config.css" :maxNumber="config.maxNumber"></chat-renderer>
|
<chat-renderer ref="renderer" :maxNumber="config.maxNumber"></chat-renderer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import config from '@/api/config'
|
import {mergeConfig, toBool, toInt} from '@/utils'
|
||||||
|
import * as config from '@/api/config'
|
||||||
import ChatRenderer from '@/components/ChatRenderer'
|
import ChatRenderer from '@/components/ChatRenderer'
|
||||||
import * as constants from '@/components/ChatRenderer/constants'
|
import * as constants from '@/components/ChatRenderer/constants'
|
||||||
|
|
||||||
@ -42,21 +43,35 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.wsConnect()
|
this.wsConnect()
|
||||||
if (this.$route.query.config_id) {
|
this.updateConfig()
|
||||||
this.updateConfig(this.$route.query.config_id)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.isDestroying = true
|
this.isDestroying = true
|
||||||
this.websocket.close()
|
this.websocket.close()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async updateConfig(configId) {
|
updateConfig() {
|
||||||
try {
|
let cfg = {}
|
||||||
this.config = await config.getRemoteConfig(configId)
|
// 留空的使用默认值
|
||||||
} catch (e) {
|
for (let i in this.$route.query) {
|
||||||
this.$message.error('获取配置失败:' + e)
|
if (this.$route.query[i] !== '') {
|
||||||
|
cfg[i] = this.$route.query[i]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
cfg = mergeConfig(cfg, config.DEFAULT_CONFIG)
|
||||||
|
|
||||||
|
cfg.minGiftPrice = toInt(cfg.minGiftPrice, config.DEFAULT_CONFIG.minGiftPrice)
|
||||||
|
cfg.mergeSimilarDanmaku = toBool(cfg.mergeSimilarDanmaku)
|
||||||
|
cfg.showDanmaku = toBool(cfg.showDanmaku)
|
||||||
|
cfg.showGift = toBool(cfg.showGift)
|
||||||
|
cfg.maxNumber = toInt(cfg.maxNumber, config.DEFAULT_CONFIG.maxNumber)
|
||||||
|
cfg.blockGiftDanmaku = toBool(cfg.blockGiftDanmaku)
|
||||||
|
cfg.blockLevel = toInt(cfg.blockLevel, config.DEFAULT_CONFIG.blockLevel)
|
||||||
|
cfg.blockNewbie = toBool(cfg.blockNewbie)
|
||||||
|
cfg.blockNotMobileVerified = toBool(cfg.blockNotMobileVerified)
|
||||||
|
cfg.blockMedalLevel = toInt(cfg.blockMedalLevel, config.DEFAULT_CONFIG.blockMedalLevel)
|
||||||
|
|
||||||
|
this.config = cfg
|
||||||
},
|
},
|
||||||
wsConnect() {
|
wsConnect() {
|
||||||
const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws'
|
const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws'
|
||||||
@ -138,7 +153,7 @@ export default {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
case COMMAND_ADD_MEMBER:
|
case COMMAND_ADD_MEMBER:
|
||||||
if (!this.config.showGift || !this.filterSuperChatMessage(data)) {
|
if (!this.config.showGift || !this.filterNewMemberMessage(data)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
message = {
|
message = {
|
||||||
@ -152,7 +167,7 @@ export default {
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
case COMMAND_ADD_SUPER_CHAT:
|
case COMMAND_ADD_SUPER_CHAT:
|
||||||
if (!this.config.showGift) {
|
if (!this.config.showGift || !this.filterSuperChatMessage(data)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (data.price < this.config.minGiftPrice) { // 丢人
|
if (data.price < this.config.minGiftPrice) { // 丢人
|
||||||
@ -199,6 +214,9 @@ export default {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return this.filterNewMemberMessage(data)
|
||||||
|
},
|
||||||
|
filterNewMemberMessage(data) {
|
||||||
for (let user of this.blockUsers) {
|
for (let user of this.blockUsers) {
|
||||||
if (data.authorName === user) {
|
if (data.authorName === user) {
|
||||||
return false
|
return false
|
||||||
|
File diff suppressed because one or more lines are too long
@ -200,8 +200,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
import stylegen from './stylegen'
|
import * as stylegen from './stylegen'
|
||||||
import fonts from './fonts'
|
import * as fonts from './fonts'
|
||||||
import ChatRenderer from '@/components/ChatRenderer'
|
import ChatRenderer from '@/components/ChatRenderer'
|
||||||
import * as constants from '@/components/ChatRenderer/constants'
|
import * as constants from '@/components/ChatRenderer/constants'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {mergeConfig} from '@/utils'
|
import {mergeConfig} from '@/utils'
|
||||||
import fonts from './fonts'
|
import * as fonts from './fonts'
|
||||||
|
|
||||||
export const DEFAULT_CONFIG = {
|
export const DEFAULT_CONFIG = {
|
||||||
showOutlines: true,
|
showOutlines: true,
|
||||||
@ -404,10 +404,3 @@ yt-live-chat-legacy-paid-message-renderer {
|
|||||||
animation-fill-mode: both;
|
animation-fill-mode: both;
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
|
||||||
DEFAULT_CONFIG,
|
|
||||||
setLocalConfig,
|
|
||||||
getLocalConfig,
|
|
||||||
getStyle
|
|
||||||
}
|
|
||||||
|
3
main.py
3
main.py
@ -11,7 +11,6 @@ import tornado.web
|
|||||||
|
|
||||||
import update
|
import update
|
||||||
import views.chat
|
import views.chat
|
||||||
import views.config
|
|
||||||
import views.main
|
import views.main
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -38,8 +37,6 @@ def main():
|
|||||||
app = tornado.web.Application(
|
app = tornado.web.Application(
|
||||||
[
|
[
|
||||||
(r'/chat', views.chat.ChatHandler),
|
(r'/chat', views.chat.ChatHandler),
|
||||||
(r'/config', views.config.ConfigsHandler),
|
|
||||||
(r'/config/(.+)', views.config.ConfigHandler),
|
|
||||||
|
|
||||||
(r'/((css|fonts|img|js|static)/.*)', tornado.web.StaticFileHandler, {'path': WEB_ROOT}),
|
(r'/((css|fonts|img|js|static)/.*)', tornado.web.StaticFileHandler, {'path': WEB_ROOT}),
|
||||||
(r'/(favicon\.ico)', tornado.web.StaticFileHandler, {'path': WEB_ROOT}),
|
(r'/(favicon\.ico)', tornado.web.StaticFileHandler, {'path': WEB_ROOT}),
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import json
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
import views.base
|
|
||||||
from typing import *
|
|
||||||
|
|
||||||
MAX_CONFIG_SIZE = 100 * 1024
|
|
||||||
|
|
||||||
configs: Dict[str, dict] = {}
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyAbstractClass
|
|
||||||
class ConfigsHandler(views.base.ApiHandler):
|
|
||||||
async def post(self):
|
|
||||||
if not isinstance(self.json_args, dict):
|
|
||||||
self.set_status(400)
|
|
||||||
return
|
|
||||||
|
|
||||||
config = self.json_args
|
|
||||||
config_id = str(uuid.uuid4())
|
|
||||||
config['id'] = config_id
|
|
||||||
config_str = json.dumps(config)
|
|
||||||
if len(config_str) > MAX_CONFIG_SIZE:
|
|
||||||
self.set_status(413)
|
|
||||||
return
|
|
||||||
|
|
||||||
configs[config_id] = config
|
|
||||||
self.write(config_str)
|
|
||||||
self.set_status(201)
|
|
||||||
self.set_header('Content-Type', 'application/json; charset=UTF-8')
|
|
||||||
|
|
||||||
if len(configs) > 10000:
|
|
||||||
for _, key in zip(range(100), configs):
|
|
||||||
del configs[key]
|
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyAbstractClass
|
|
||||||
class ConfigHandler(views.base.ApiHandler):
|
|
||||||
async def put(self, config_id):
|
|
||||||
if config_id not in configs:
|
|
||||||
self.set_status(404)
|
|
||||||
return
|
|
||||||
if not isinstance(self.json_args, dict):
|
|
||||||
self.set_status(400)
|
|
||||||
return
|
|
||||||
|
|
||||||
config = self.json_args
|
|
||||||
config['id'] = config_id
|
|
||||||
config_str = json.dumps(config)
|
|
||||||
if len(config_str) > MAX_CONFIG_SIZE:
|
|
||||||
self.set_status(413)
|
|
||||||
return
|
|
||||||
|
|
||||||
configs[config_id] = config
|
|
||||||
self.write(config_str)
|
|
||||||
self.set_header('Content-Type', 'application/json; charset=UTF-8')
|
|
||||||
|
|
||||||
async def get(self, config_id):
|
|
||||||
config = configs.get(config_id, None)
|
|
||||||
if config is None:
|
|
||||||
self.set_status(404)
|
|
||||||
return
|
|
||||||
self.write(config)
|
|
Loading…
Reference in New Issue
Block a user