Browse Source

thuhole update

dev
thuhole 5 years ago
parent
commit
0166bd8947
  1. 8
      public/index.html
  2. BIN
      public/static/bg/cyberpunk.jpg
  3. BIN
      public/static/favicon/180.png
  4. BIN
      public/static/favicon/192.png
  5. BIN
      public/static/favicon/256.png
  6. BIN
      public/static/favicon/512.png
  7. 6
      public/static/manifest.json
  8. 50
      public/stats.js
  9. 4
      src/App.js
  10. 8
      src/Common.js
  11. 3
      src/Config.js
  12. 15
      src/Flows.js
  13. 4
      src/Message.js
  14. 10
      src/Title.js
  15. 378
      src/UserAction.js
  16. 4
      src/flows_api.js
  17. 2
      src/infrastructure
  18. 7
      src/text_splitter.js

8
public/index.html

@ -3,19 +3,19 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="%PUBLIC_URL%/static/favicon/256.png">
<link rel="icon" href="%PUBLIC_URL%/static/favicon/512.png">
<meta name="format-detection" content="telephone=no">
<link rel="stylesheet" href="%PUBLIC_URL%/static/fonts_7/icomoon.css" />
<meta name="mobile-web-app-capable" content="yes">
<link rel="shortcut icon" href="%PUBLIC_URL%/static/favicon/256.png">
<link rel="shortcut icon" href="%PUBLIC_URL%/static/favicon/512.png">
<link rel="manifest" href="%PUBLIC_URL%/static/manifest.json">
<meta name="theme-color" content="#333333"/>
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-icon" sizes="180x180" href="%PUBLIC_URL%/static/favicon/180.png" />
<link rel="apple-touch-icon" sizes="256x256" href="%PUBLIC_URL%/static/favicon/256.png" />
<link rel="apple-touch-icon" sizes="512x512" href="%PUBLIC_URL%/static/favicon/512.png" />
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="树洞">
<link rel="apple-touch-startup-image" href="%PUBLIC_URL%/static/splash/750x1334.png" media="(device-width: 375px) and (-webkit-device-pixel-ratio: 2)"/>
@ -23,7 +23,7 @@
<link rel="apple-touch-startup-image" href="%PUBLIC_URL%/static/splash/1668x2388.png" media="(device-width: 834px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"/>
<link rel="apple-touch-startup-image" href="%PUBLIC_URL%/static/splash/2388x1668.png" media="(device-width: 834px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"/>
<title>P大树洞</title>
<title>T大树洞</title>
</head>
<body>
<div id="root"></div>

BIN
public/static/bg/cyberpunk.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

BIN
public/static/favicon/180.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 15 KiB

BIN
public/static/favicon/192.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/static/favicon/256.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

BIN
public/static/favicon/512.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

6
public/static/manifest.json

@ -1,10 +1,10 @@
{
"short_name": "树洞",
"name": "P大树洞",
"name": "T大树洞",
"icons": [
{
"src": "favicon/256.png",
"sizes": "256x256",
"src": "favicon/512.png",
"sizes": "512x512",
"type": "image/png"
},
{

50
public/stats.js

@ -1,25 +1,25 @@
var _czc=_czc||[];
_czc.push(["_setAccount","1274501752"]);
_czc.push(["_setCustomVar","has_token",localStorage['TOKEN']?'yes':'no',1]);
_czc.push(["_setCustomVar","standalone",((window.matchMedia('(display-mode: standalone)').matches) || (window.navigator.standalone))?'yes':'no',1]);
_czc.push(["_setCustomVar","build_info","%REACT_APP_BUILD_INFO%"||'---']);
var cr_version=/Chrome\/(\d+)/.exec(navigator.userAgent);
_czc.push(["_setCustomVar","cr_version_test",cr_version?cr_version[1]:'[null]',2]);
/*
// track config
try {
var config=JSON.parse(localStorage['hole_config']||'{}');
for(var key in config)
if(config.hasOwnProperty(key))
_czc.push(["_trackEvent",'config',key,encodeURIComponent(JSON.stringify(config[key])),0,'']);
//_czc.push(["_setCustomVar","config_"+key,encodeURIComponent(JSON.stringify(config[key])),0]);
} catch(e) {
console.trace(e);
}
*/
var cnzz_s_tag = document.createElement('script');
cnzz_s_tag.type = 'text/javascript';
cnzz_s_tag.async = true;
cnzz_s_tag.charset = "utf-8";
cnzz_s_tag.src = "https://w.cnzz.com/c.php?id=1274501752&async=1";
document.head.appendChild(cnzz_s_tag);
// var _czc=_czc||[];
// _czc.push(["_setAccount","1274501752"]);
// _czc.push(["_setCustomVar","has_token",localStorage['TOKEN']?'yes':'no',1]);
// _czc.push(["_setCustomVar","standalone",((window.matchMedia('(display-mode: standalone)').matches) || (window.navigator.standalone))?'yes':'no',1]);
// _czc.push(["_setCustomVar","build_info","%REACT_APP_BUILD_INFO%"||'---']);
// var cr_version=/Chrome\/(\d+)/.exec(navigator.userAgent);
// _czc.push(["_setCustomVar","cr_version_test",cr_version?cr_version[1]:'[null]',2]);
// /*
// // track config
// try {
// var config=JSON.parse(localStorage['hole_config']||'{}');
// for(var key in config)
// if(config.hasOwnProperty(key))
// _czc.push(["_trackEvent",'config',key,encodeURIComponent(JSON.stringify(config[key])),0,'']);
// //_czc.push(["_setCustomVar","config_"+key,encodeURIComponent(JSON.stringify(config[key])),0]);
// } catch(e) {
// console.trace(e);
// }
// */
// var cnzz_s_tag = document.createElement('script');
// cnzz_s_tag.type = 'text/javascript';
// cnzz_s_tag.async = true;
// cnzz_s_tag.charset = "utf-8";
// cnzz_s_tag.src = "https://w.cnzz.com/c.php?id=1274501752&async=1";
// document.head.appendChild(cnzz_s_tag);

4
src/App.js

@ -106,14 +106,14 @@ class App extends Component {
<LoginPopup token_callback={token.set_value}>{(do_popup)=>(
<a onClick={do_popup}>
<span className="icon icon-login" />
&nbsp;登录到 PKU Helper
&nbsp;登录到 T大树洞
</a>
)}</LoginPopup>
</p>
</div>
</div>
}
{this.inpku_flag||token.value ?
{this.inpku_flag||token.value||true ?
<Flow key={this.state.flow_render_key} show_sidebar={this.show_sidebar_bound}
mode={this.state.mode} search_text={this.state.search_text} token={token.value}
/> :

8
src/Common.js

@ -1,12 +1,12 @@
import React, {Component, PureComponent} from 'react';
import {format_time,Time,TitleLine} from './infrastructure/widgets';
import {PKUHELPER_ROOT} from './flows_api';
import {THUHOLE_API_ROOT} from './flows_api';
import './Common.css';
export {format_time,Time,TitleLine};
export const API_BASE=PKUHELPER_ROOT+'services/pkuhole';
export const API_BASE=THUHOLE_API_ROOT+'services/thuhole';
// https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
function escape_regex(string) {
@ -37,9 +37,9 @@ export class HighlightedText extends PureComponent {
let [rule,p]=part;
return (
<span key={idx}>{
rule==='url_pid' ? <span className="url-pid-link" title={p}>/hole/##</span> :
rule==='url_pid' ? <span className="url-pid-link" title={p}>/##</span> :
rule==='url' ? <a href={normalize_url(p)} target="_blank" rel="noopener">{p}</a> :
rule==='pid' ? <a href={'##'+p} onClick={(e)=>{e.preventDefault(); this.props.show_pid(p);}}>{p}</a> :
rule==='pid' ? <a href={'#'+p} onClick={(e)=>{e.preventDefault(); this.props.show_pid(p.substring(1));}}>{p}</a> :
rule==='nickname' ? <ColoredSpan colors={this.props.color_picker.get(p)}>{p}</ColoredSpan> :
rule==='search' ? <span className="search-query-highlight">{p}</span> :
p

3
src/Config.js

@ -7,6 +7,7 @@ const BUILTIN_IMGS={
'static/bg/eriri.jpg': '平成著名画师',
'static/bg/yurucamp.jpg': '露营天下第一',
'static/bg/minecraft.jpg': '麦恩·库拉夫特',
'static/bg/cyberpunk.jpg': '赛博城市',
'static/bg/sif.jpg': '梦开始的地方',
};
@ -238,7 +239,7 @@ export class ConfigUI extends PureComponent {
<hr />
<p>
新功能建议或问题反馈请在&nbsp;
<a href="https://github.com/pkuhelper-web/webhole/issues" target="_blank">GitHub <span className="icon icon-github" /></a>
<a href="https://github.com/thuhole/webhole/issues" target="_blank">GitHub <span className="icon icon-github" /></a>
&nbsp;提出
</p>
</div>

15
src/Flows.js

@ -8,14 +8,15 @@ import LazyLoad from './react-lazyload/src';
import {AudioWidget} from './AudioWidget';
import {TokenCtx, ReplyForm} from './UserAction';
import {API, PKUHELPER_ROOT} from './flows_api';
import {API, THUHOLE_API_ROOT} from './flows_api';
const IMAGE_BASE=PKUHELPER_ROOT+'services/pkuhole/images/';
const AUDIO_BASE=PKUHELPER_ROOT+'services/pkuhole/audios/';
const IMAGE_BASE=THUHOLE_API_ROOT+'services/thuhole/images/';
const AUDIO_BASE=THUHOLE_API_ROOT+'services/thuhole/audios/';
const CLICKABLE_TAGS={a: true, audio: true};
const PREVIEW_REPLY_COUNT=10;
const QUOTE_BLACKLIST=['23333','233333','66666','666666','10086','10000','100000','99999','999999','55555','555555'];
// const QUOTE_BLACKLIST=['23333','233333','66666','666666','10086','10000','100000','99999','999999','55555','555555'];
const QUOTE_BLACKLIST=[];
window.LATEST_POST_ID=parseInt(localStorage['_LATEST_POST_ID'],10)||0;
@ -521,7 +522,8 @@ class FlowItemRow extends PureComponent {
let quote_id=null;
if(!this.props.is_quote)
for(let [mode,content] of parts)
for(let [mode,content] of parts) {
content = content.length > 0 ? content.substring(1) : content
if(mode==='pid' && QUOTE_BLACKLIST.indexOf(content)===-1 && parseInt(content)<parseInt(this.state.info.pid))
if(quote_id===null)
quote_id=parseInt(content);
@ -529,6 +531,7 @@ class FlowItemRow extends PureComponent {
quote_id=null;
break;
}
}
let res=(
<div className={'flow-item-row flow-item-row-with-prompt'+(this.props.is_quote ? ' flow-item-row-quote' : '')} onClick={(event)=>{
@ -809,7 +812,7 @@ export class Flow extends PureComponent {
<TitleLine text={
this.state.loading_status==='loading' ?
<span><span className="icon icon-loading" />&nbsp;Loading...</span> :
xmcp'
thuhole'
} />
</div>
);

4
src/Message.js

@ -1,5 +1,5 @@
import React, {Component, PureComponent} from 'react';
import {PKUHELPER_ROOT, get_json, API_VERSION_PARAM} from './flows_api';
import {THUHOLE_API_ROOT, get_json, API_VERSION_PARAM} from './flows_api';
import {Time} from './Common';
export class MessageViewer extends PureComponent {
@ -20,7 +20,7 @@ export class MessageViewer extends PureComponent {
this.setState({
loading_status: 'loading',
},()=>{
fetch(PKUHELPER_ROOT+'api_xmcp/hole/system_msg?user_token='+encodeURIComponent(this.props.token)+API_VERSION_PARAM())
fetch(THUHOLE_API_ROOT+'api_xmcp/hole/system_msg?user_token='+encodeURIComponent(this.props.token)+API_VERSION_PARAM())
.then(get_json)
.then((json)=>{
if(json.error)

10
src/Title.js

@ -1,5 +1,5 @@
import React, {Component, PureComponent} from 'react';
import {AppSwitcher} from './infrastructure/widgets';
// import {AppSwitcher} from './infrastructure/widgets';
import {InfoSidebar, PostForm} from './UserAction';
import {TokenCtx} from './UserAction';
@ -94,7 +94,7 @@ class ControlBar extends PureComponent {
/>
<a className="no-underline control-btn" onClick={()=>{
this.props.show_sidebar(
'P大树洞',
'T大树洞',
<InfoSidebar show_sidebar={this.props.show_sidebar} />
)
}}>
@ -124,15 +124,15 @@ class ControlBar extends PureComponent {
export function Title(props) {
return (
<div className="title-bar">
<AppSwitcher appid="hole" />
{/* <AppSwitcher appid="hole" /> */}
<div className="aux-margin">
<div className="title">
<p className="centered-line">
<span onClick={()=>props.show_sidebar(
'P大树洞',
'T大树洞',
<InfoSidebar show_sidebar={props.show_sidebar} />
)}>
P大树洞
T大树洞
</span>
</p>
</div>

378
src/UserAction.js

@ -6,7 +6,7 @@ import {ConfigUI} from './Config';
import fixOrientation from 'fix-orientation';
import copy from 'copy-to-clipboard';
import {cache} from './cache';
import {API_VERSION_PARAM, PKUHELPER_ROOT, API, get_json, token_param} from './flows_api';
import {API_VERSION_PARAM, THUHOLE_API_ROOT, API, get_json, token_param} from './flows_api';
import './UserAction.css';
@ -20,179 +20,179 @@ export const TokenCtx=React.createContext({
set_value: ()=>{},
});
class LifeInfoBox extends Component {
constructor(props) {
super(props);
if(!window._life_info_cache)
window._life_info_cache={};
this.CACHE_TIMEOUT_S=15;
this.state={
today_info: this.cache_get('today_info'),
card_balance: this.cache_get('card_balance'),
net_balance: this.cache_get('net_balance'),
mail_count: this.cache_get('mail_count'),
};
this.INTERNAL_NETWORK_FAILURE='_network_failure';
this.API_NAME={
today_info: 'hole/today_info',
card_balance: 'isop/card_balance',
net_balance: 'isop/net_balance',
mail_count: 'isop/mail_count',
};
}
cache_get(key) {
let cache_item=window._life_info_cache[key];
if(!cache_item || (+new Date())-cache_item[0]>1000*this.CACHE_TIMEOUT_S)
return null;
else
return cache_item[1];
}
cache_set(key,value) {
if(!window._life_info_cache[key] || window._life_info_cache[key][1]!==value)
window._life_info_cache[key]=[+new Date(),value];
}
load(state_key) {
this.setState({
[state_key]: null,
},()=>{
fetch(
PKUHELPER_ROOT+'api_xmcp/'+this.API_NAME[state_key]
+'?user_token='+encodeURIComponent(this.props.token)
+API_VERSION_PARAM()
)
.then(get_json)
.then((json)=>{
//console.log(json);
this.setState({
[state_key]: json,
});
})
.catch((e)=>{
this.setState({
[state_key]: {
errMsg: '网络错误 '+e,
errCode: this.INTERNAL_NETWORK_FAILURE,
success: false,
}
});
})
});
}
componentDidMount() {
['today_info','card_balance','net_balance','mail_count'].forEach((k)=>{
if(!this.state[k])
this.load(k);
});
}
reload_all() {
['today_info','card_balance','net_balance','mail_count'].forEach((k)=>{
this.load(k);
});
}
render_line(state_key,title,value_fn,action,url_fn,do_login) {
let s=this.state[state_key];
if(!s)
return (
<tr>
<td>{title}</td>
<td>加载中</td>
<td />
</tr>
);
else if(!s.success) {
let type='加载失败';
if(s.errCode===this.INTERNAL_NETWORK_FAILURE)
type='网络错误';
else if(['E01','E02','E03'].indexOf(s.errCode)!==-1)
type='授权失效';
let details=JSON.stringify(s);
if(s.errMsg)
details=s.errMsg;
else if(s.error)
details=s.error;
return (
<tr>
<td>{title}</td>
<td className="life-info-error">
<a onClick={()=>alert(details)}>{type}</a>
</td>
<td>
{type==='授权失效' ?
<a onClick={do_login}>
<span className="icon icon-forward" />&nbsp;重新登录
</a> :
<a onClick={()=>this.load(state_key)}>
<span className="icon icon-forward" />&nbsp;重试
</a>
}
</td>
</tr>
)
}
else {
this.cache_set(state_key,s);
return (
<tr>
<td>{title}</td>
<td>{value_fn(s)}</td>
<td>
<a href={url_fn(s)} target="_blank">
<span className="icon icon-forward" />&nbsp;{action}
</a>
</td>
</tr>
);
}
}
render() {
return (
<LoginPopup token_callback={(t)=>{
this.props.set_token(t);
this.reload_all();
}}>{(do_login)=>(
<div className="box">
<table className="life-info-table">
<tbody>
{this.render_line(
'today_info',
'今日',(s)=>s.info,
'校历',(s)=>s.schedule_url,
do_login,
)}
{this.render_line(
'card_balance',
'校园卡',(s)=>`余额¥${s.balance.toFixed(2)}`,
'充值',()=>'https://virtualprod.alipay.com/educate/educatePcRecharge.htm?schoolCode=PKU&schoolName=',
do_login,
)}
{this.render_line(
'net_balance',
'网费',(s)=>`余额¥${s.balance.toFixed(2)}`,
'充值',()=>'https://its.pku.edu.cn/epay.jsp',
do_login,
)}
{this.render_line(
'mail_count',
'邮件',(s)=>`未读 ${s.count}`,
'查看',()=>'https://mail.pku.edu.cn/',
do_login,
)}
</tbody>
</table>
</div>
)}</LoginPopup>
)
}
}
// class LifeInfoBox extends Component {
// constructor(props) {
// super(props);
// if(!window._life_info_cache)
// window._life_info_cache={};
// this.CACHE_TIMEOUT_S=15;
// this.state={
// today_info: this.cache_get('today_info'),
// card_balance: this.cache_get('card_balance'),
// net_balance: this.cache_get('net_balance'),
// mail_count: this.cache_get('mail_count'),
// };
// this.INTERNAL_NETWORK_FAILURE='_network_failure';
// this.API_NAME={
// today_info: 'hole/today_info',
// card_balance: 'isop/card_balance',
// net_balance: 'isop/net_balance',
// mail_count: 'isop/mail_count',
// };
// }
//
// cache_get(key) {
// let cache_item=window._life_info_cache[key];
// if(!cache_item || (+new Date())-cache_item[0]>1000*this.CACHE_TIMEOUT_S)
// return null;
// else
// return cache_item[1];
// }
// cache_set(key,value) {
// if(!window._life_info_cache[key] || window._life_info_cache[key][1]!==value)
// window._life_info_cache[key]=[+new Date(),value];
// }
//
// load(state_key) {
// this.setState({
// [state_key]: null,
// },()=>{
// fetch(
// PKUHELPER_ROOT+'api_xmcp/'+this.API_NAME[state_key]
// +'?user_token='+encodeURIComponent(this.props.token)
// +API_VERSION_PARAM()
// )
// .then(get_json)
// .then((json)=>{
// //console.log(json);
// this.setState({
// [state_key]: json,
// });
// })
// .catch((e)=>{
// this.setState({
// [state_key]: {
// errMsg: '网络错误 '+e,
// errCode: this.INTERNAL_NETWORK_FAILURE,
// success: false,
// }
// });
// })
// });
// }
//
// componentDidMount() {
// ['today_info','card_balance','net_balance','mail_count'].forEach((k)=>{
// if(!this.state[k])
// this.load(k);
// });
// }
//
// reload_all() {
// ['today_info','card_balance','net_balance','mail_count'].forEach((k)=>{
// this.load(k);
// });
// }
//
// render_line(state_key,title,value_fn,action,url_fn,do_login) {
// let s=this.state[state_key];
// if(!s)
// return (
// <tr>
// <td>{title}</td>
// <td>加载中……</td>
// <td />
// </tr>
// );
// else if(!s.success) {
// let type='加载失败';
// if(s.errCode===this.INTERNAL_NETWORK_FAILURE)
// type='网络错误';
// else if(['E01','E02','E03'].indexOf(s.errCode)!==-1)
// type='授权失效';
//
// let details=JSON.stringify(s);
// if(s.errMsg)
// details=s.errMsg;
// else if(s.error)
// details=s.error;
//
// return (
// <tr>
// <td>{title}</td>
// <td className="life-info-error">
// <a onClick={()=>alert(details)}>{type}</a>
// </td>
// <td>
// {type==='授权失效' ?
// <a onClick={do_login}>
// <span className="icon icon-forward" />&nbsp;重新登录
// </a> :
// <a onClick={()=>this.load(state_key)}>
// <span className="icon icon-forward" />&nbsp;重试
// </a>
// }
// </td>
// </tr>
// )
// }
// else {
// this.cache_set(state_key,s);
//
// return (
// <tr>
// <td>{title}</td>
// <td>{value_fn(s)}</td>
// <td>
// <a href={url_fn(s)} target="_blank">
// <span className="icon icon-forward" />&nbsp;{action}
// </a>
// </td>
// </tr>
// );
// }
// }
//
// render() {
// return (
// <LoginPopup token_callback={(t)=>{
// this.props.set_token(t);
// this.reload_all();
// }}>{(do_login)=>(
// <div className="box">
// <table className="life-info-table">
// <tbody>
// {this.render_line(
// 'today_info',
// '今日',(s)=>s.info,
// '校历',(s)=>s.schedule_url,
// do_login,
// )}
// {this.render_line(
// 'card_balance',
// '校园卡',(s)=>`余额¥${s.balance.toFixed(2)}`,
// '充值',()=>'https://virtualprod.alipay.com/educate/educatePcRecharge.htm?schoolCode=PKU&schoolName=',
// do_login,
// )}
// {this.render_line(
// 'net_balance',
// '网费',(s)=>`余额¥${s.balance.toFixed(2)}`,
// '充值',()=>'https://its.pku.edu.cn/epay.jsp',
// do_login,
// )}
// {this.render_line(
// 'mail_count',
// '邮件',(s)=>`未读 ${s.count} 封`,
// '查看',()=>'https://mail.pku.edu.cn/',
// do_login,
// )}
// </tbody>
// </table>
// </div>
// )}</LoginPopup>
// )
// }
// }
export function InfoSidebar(props) {
return (
@ -207,23 +207,25 @@ export function InfoSidebar(props) {
<span className="icon icon-settings" /><label>网页版树洞设置</label>
</a>
&nbsp;&nbsp;
<a href="http://pkuhelper.pku.edu.cn/treehole_rules.html" target="_blank">
<span className="icon icon-textfile" /><label>树洞规范</label>
</a>
&nbsp;&nbsp;
<a href="https://github.com/pkuhelper-web/webhole/issues" target="_blank">
{/*<a href="http://pkuhelper.pku.edu.cn/treehole_rules.html" target="_blank">*/}
{/* <span className="icon icon-textfile" /><label>树洞规范</label>*/}
{/*</a>*/}
{/*&nbsp;&nbsp;*/}
<a href="https://github.com/thuhole/webhole/issues" target="_blank">
<span className="icon icon-github" /><label>意见反馈</label>
</a>
</div>
<div className="box help-desc-box">
<p>
PKUHelper 网页版树洞 by @xmcp
T大树洞 网页版 by @thuhole
基于&nbsp;
<a href="https://www.gnu.org/licenses/gpl-3.0.zh-cn.html" target="_blank">GPLv3</a>
&nbsp;协议在 <a href="https://github.com/pkuhelper-web/webhole" target="_blank">GitHub</a>
&nbsp;协议在 <a href="https://github.com/thuhole/webhole" target="_blank">GitHub</a>
</p>
<p>
PKUHelper 网页版的诞生离不开&nbsp;
T大树洞 网页版的诞生离不开&nbsp;
<a href="https://github.com/pkuhelper-web/webhole" target="_blank" rel="noopener">P大树洞</a>
<a href="https://reactjs.org/" target="_blank" rel="noopener">React</a>
<a href="https://icomoon.io/#icons" target="_blank" rel="noopener">IcoMoon</a>
@ -280,7 +282,7 @@ class ResetUsertokenWidget extends Component {
this.setState({
loading_status: 'loading',
},()=>{
fetch(PKUHELPER_ROOT+'api_xmcp/hole/reset_usertoken', {
fetch(THUHOLE_API_ROOT+'api_xmcp/hole/reset_usertoken', {
method: 'post',
headers: {
'Content-Type': 'application/json',
@ -329,9 +331,9 @@ export class LoginForm extends Component {
return (
<TokenCtx.Consumer>{(token)=>
<div>
{!!token.value &&
<LifeInfoBox token={token.value} set_token={token.set_value} />
}
{/*{!!token.value &&*/}
{/* <LifeInfoBox token={token.value} set_token={token.set_value} />*/}
{/*}*/}
<div className="login-form box">
{token.value ?
<div>
@ -354,7 +356,7 @@ export class LoginForm extends Component {
</p>
<p>
<a onClick={this.copy_token.bind(this,token.value)}>复制 User Token</a><br />
User Token 用于迁移登录状态切勿告知他人若怀疑被盗号请尽快 <ResetUsertokenWidget token={token.value} />
User Token 用于迁移登录状态切勿告知他人{/*,若怀疑被盗号请尽快 <ResetUsertokenWidget token={token.value} />*/}
</p>
</div> :
<LoginPopup token_callback={token.set_value}>{(do_popup)=>(
@ -366,7 +368,7 @@ export class LoginForm extends Component {
</button>
</p>
<p><small>
PKU Helper 面向北京大学学生通过 ISOP北京大学数据共享开放服务平台验证您的身份并提供服务
T大树洞 面向清华大学学生通过清华邮箱验证您的身份并提供服务
</small></p>
</div>
)}</LoginPopup>

4
src/flows_api.js

@ -1,9 +1,9 @@
import {get_json, API_VERSION_PARAM} from './infrastructure/functions';
import {PKUHELPER_ROOT} from './infrastructure/const';
import {THUHOLE_API_ROOT} from './infrastructure/const';
import {API_BASE} from './Common';
import {cache} from './cache';
export {PKUHELPER_ROOT, API_VERSION_PARAM};
export {THUHOLE_API_ROOT, API_VERSION_PARAM};
export function token_param(token) {
return API_VERSION_PARAM()+(token ? ('&user_token='+token) : '');

2
src/infrastructure

@ -1 +1 @@
Subproject commit 9901aa83dfa8ee01da9e9480cc9524b18e29c40c
Subproject commit e24cf980948f63cc1535a6d2eb69319c5b3b055e

7
src/text_splitter.js

@ -1,6 +1,9 @@
// regexp should match the WHOLE segmented part
export const PID_RE=/(^|[^\d\u20e3\ufe0e\ufe0f])([2-9]\d{4,5}|1\d{4,6})(?![\d\u20e3\ufe0e\ufe0f])/g;
export const URL_PID_RE=/((?:https?:\/\/)?pkuhelper\.pku\.edu\.cn\/hole\/?#(?:#|%23)([2-9]\d{4,5}|1\d{4,6}))(?!\d|\u20e3|\ufe0e|\ufe0f)/g;
// export const PID_RE=/(^|[^\d\u20e3\ufe0e\ufe0f])([2-9]\d{4,5}|1\d{4,6})(?![\d\u20e3\ufe0e\ufe0f])/g;
export const PID_RE=/(^|[^\d\u20e3\ufe0e\ufe0f])(#\d{1,7})(?![\d\u20e3\ufe0e\ufe0f])/g;
// TODO: fix this re
// export const URL_PID_RE=/((?:https?:\/\/)?thuhole\.tech\/?#(?:#|%23)([2-9]\d{4,5}|1\d{4,6}))(?!\d|\u20e3|\ufe0e|\ufe0f)/g;
export const URL_PID_RE=/((?:https?:\/\/)?thuhole\.tech\/?#(?:#|%23)(\d{1,7}))(?!\d|\u20e3|\ufe0e|\ufe0f)/g;
export const NICKNAME_RE=/(^|[^A-Za-z])((?:(?:Angry|Baby|Crazy|Diligent|Excited|Fat|Greedy|Hungry|Interesting|Jolly|Kind|Little|Magic|Naïve|Old|Powerful|Quiet|Rich|Superman|THU|Undefined|Valuable|Wifeless|Xiangbuchulai|Young|Zombie)\s)?(?:Alice|Bob|Carol|Dave|Eve|Francis|Grace|Hans|Isabella|Jason|Kate|Louis|Margaret|Nathan|Olivia|Paul|Queen|Richard|Susan|Thomas|Uma|Vivian|Winnie|Xander|Yasmine|Zach)|You Win(?: \d+)?|洞主)(?![A-Za-z])/gi;
export const URL_RE=/(^|[^.@a-zA-Z0-9_])((?:https?:\/\/)?(?:(?:[\w-]+\.)+[a-zA-Z]{2,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?::\d{1,5})?(?:\/[\w~!@#$%^&*()\-_=+[\]{};:,./?|]*)?)(?![a-zA-Z0-9])/gi;

Loading…
Cancel
Save