import React, { Component, PureComponent } from 'react'; import ReactDOM from 'react-dom'; import TimeAgo from 'react-timeago'; import chineseStrings from 'react-timeago/lib/language-strings/zh-CN'; import buildFormatter from 'react-timeago/lib/formatters/buildFormatter'; import copy from 'copy-to-clipboard'; import './global.css'; import './widgets.css'; import emailExample from '../images/email_example.jpg'; import { get_json, API_VERSION_PARAM } from './functions'; import { EMAIL } from '../UserAction'; function pad2(x) { return x < 10 ? '0' + x : '' + x; } export function format_time(time) { return `${time.getMonth() + 1}-${pad2( time.getDate(), )} ${time.getHours()}:${pad2(time.getMinutes())}:${pad2(time.getSeconds())}`; } const chinese_format = buildFormatter(chineseStrings); export function Time(props) { const time = new Date(props.stamp * 1000); return (   {!props.short ? format_time(time) : null} ); } export function TitleLine(props) { return (

{props.text}

); } export function GlobalTitle(props) { return (

{props.text}

); } async function sha256_hex(text, l = null) { let hash_buffer = await window.crypto.subtle.digest('SHA-256' , new TextEncoder().encode(text)); let hex_str = Array.from(new Uint8Array(hash_buffer)).map((b) => b.toString(16).padStart(2, '0')).join(''); return l ? hex_str.slice(0, l) : hex_str } class LoginPopupSelf extends Component { constructor(props) { super(props); this.state = { token_phrase: '', already_copy: false, }; } setThuhole(e) { e.preventDefault(); alert('T大树洞已经没有啦😭'); } copy_token_hash(event) { const { token_phrase } = this.state; if (!token_phrase) { alert('不可以为空'); return; } sha256_hex(token_phrase + 'hole' + new Date().toDateString(), 16) .then((token) => sha256_hex(token + 'hole', 16)) .then((token_hash) => copy('|' + token_hash + '|')); this.setState({already_copy: true}); } copy_token_phrase(event) { const { token_phrase } = this.state; if (!token_phrase) { alert('不可以为空'); return; } copy(token_phrase); } use_token(event) { const { token_phrase } = this.state; if (!token_phrase) { alert('不可以为空'); return; } sha256_hex(token_phrase + 'hole' + new Date().toDateString(), 16) .then((token) => { localStorage['TOKEN'] = 'sha256:' + token; window.location.reload(); }); } render() { const { token_phrase, already_copy } = this.state; return (

直接邮箱登陆

this.setState({token_phrase: event.target.value})} />

  1. this.setState({token_phrase: window.crypto.randomUUID(), already_copy: false})}> 生成 或粘贴用来生成token的ID。
  2. {!!token_phrase && (
  3. 点击此处 复制此ID用于在其他设备上登录,当日有效,注意妥善保管。
  4. )} {!!token_phrase && (
  5. 点击此处 复制用来发送邮件的内容
  6. )} {!!already_copy ? (
  7. 发送邮件到 {EMAIL}。 不同设备请勿重复发件。 后台每15分钟查收一次邮件,等待一段时间后 点击此处 使用此token登录。示例:
  8. ) : (
  9. ...
  10. )}

第三方认证登陆

 GitHub

 闭社

 T大树洞

前往Telegram群查询15分钟临时token
 清华大水群



提醒:

  • 新T树洞的匿名性来自隔离用户名与发布的内容,而非试图隔离用户名与真实身份。
  • 目前一个人可能有多个帐号。
); } } export class LoginPopup extends Component { constructor(props) { super(props); this.state = { popup_show: false, }; this.on_popup_bound = this.on_popup.bind(this); this.on_close_bound = this.on_close.bind(this); } on_popup() { this.setState({ popup_show: true, }); } on_close() { this.setState({ popup_show: false, }); } render() { return ( <> {this.props.children(this.on_popup_bound)} {this.state.popup_show && ( )} ); } }