Explorar o código

更新UI和API频率限制

guowengui %!s(int64=8) %!d(string=hai) anos
pai
achega
550a1495bb

+ 3 - 3
app.js

@@ -12,10 +12,10 @@ var app = express();
 
 // view engine setup
 app.set('views', path.join(__dirname, 'views'));
-app.set('view engine', 'jade');
+app.set('view engine', 'pug');
 
 // uncomment after placing your favicon in /public
-//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
+app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
 app.use(logger('dev'));
 app.use(bodyParser.json());
 app.use(bodyParser.urlencoded({ extended: false }));
@@ -23,7 +23,7 @@ app.use(cookieParser());
 app.use(express.static(path.join(__dirname, 'public')));
 
 app.use('/', index);
-app.use('/api', apis); // 加在app.use部分
+app.use('/api', apis);
 
 // catch 404 and forward to error handler
 app.use(function(req, res, next) {

+ 7 - 3
config.js

@@ -7,8 +7,12 @@ module.exports = {
 	redis_host: '127.0.0.1',
 	redis_port: '6379',
 	redis_pwd: null, // 没有redis密码则写 null
-	// 列表Hash表名
+	// redis Hash列表名
 	field_lists: 'naives',
-	// 匹配GUID的正则表达式
-	regex_guid: /[?a-zA-Z0-9]{8}-[?a-zA-Z0-9]{4}-[?a-zA-Z0-9]{4}-[?a-zA-Z0-9]{4}-[?a-zA-Z0-9]{12}$/,
+	// 1小时内单个IP可获取最多临时链接数
+	rate_limit: 500,
+	// 是否显示首页中的作死文本 eg.「☭赵」
+	isZhao: true,
+	// 用于匹配GUID的正则
+	reg_guid: /[?a-zA-Z0-9]{8}-[?a-zA-Z0-9]{4}-[?a-zA-Z0-9]{4}-[?a-zA-Z0-9]{4}-[?a-zA-Z0-9]{12}$/,
 }

BIN=BIN
dump.rdb


+ 2 - 2
lib/tools.js

@@ -1,5 +1,5 @@
 var redis = require("redis");
-var guidtool = require('guid');
+var uuidv1 = require('uuid/v1');
 
 /**
  * Redis存档的Hash消息管理工具
@@ -45,7 +45,7 @@ module.exports = function(conf)
 	 * @return {[type]}            [description]
 	 */
 	this.getUniID = (callback) => {
-		var guid = guidtool.raw();
+		var guid = uuidv1();
 		this.exists(guid, (exists) => {
 			// 如果存在则递归重新获取,直到获取到不重复的GUID并返回
 			exists ? this.getUniID(callback) : callback(guid);

+ 8 - 5
package.json

@@ -1,6 +1,7 @@
 {
-  "name": "node-api",
-  "version": "0.0.0",
+  "name": "naiveboom",
+  "version": "1.1.2",
+  "license": "MIT License",
   "private": true,
   "scripts": {
     "start": "node ./bin/www"
@@ -10,10 +11,12 @@
     "cookie-parser": "~1.4.3",
     "debug": "~2.6.9",
     "express": "~4.15.5",
-    "guid": "^0.0.12",
-    "jade": "~1.11.0",
+    "express-rate-limit": "^2.11.0",
     "morgan": "~1.9.0",
+    "pug": "latest",
     "redis": "^2.8.0",
-    "serve-favicon": "~2.4.5"
+    "serve-favicon": "~2.4.5",
+    "util": "^0.10.3",
+    "uuid": "^3.2.1"
   }
 }

+ 29 - 1
public/javascripts/a.js

@@ -1,3 +1,21 @@
+modal = new Vue({
+	el: '#modal',
+	data: {
+		msg: '么有',
+		title: '提示'
+	},
+	methods: {
+		show: function(msg, title) {
+			if (title) {
+				this.title = title;
+			}
+			this.msg = msg;
+			$('#mmodal').modal();
+		}
+	}
+})
+
+
 app = new Vue({
 	el: '#app',
 	data: {
@@ -18,19 +36,29 @@ app = new Vue({
 	},
 	methods: {
 		getTempURL: function() {
+			$("#enurl").loading({
+				message: '加载中...',
+				onStop: function(loading) {
+				    loading.overlay.fadeOut(650)
+				  }
+			});
 			axios.post('/api/get-temp', {
 				text: app.text
 			}).then(function(response) {
+				$("#enurl").loading('stop');
 				var data = response.data;
 				if (data.status == 1) {
 					var newURL = window.location.protocol + "//" + window.location.host + window.location.pathname;
 					app.enurl = newURL + data.guid;
 				} else {
 					throw 'failure to get the tmp url!';
+					modal.show("操作失败!<br>", '错误')
 				}
 				console.log(response);
 			}).catch(function(error) {
-				console.warn(error);
+				console.warn(error.response);
+				$("#enurl").loading('stop');
+				modal.show("操作失败!<br>" + error.response.data.message, '错误')
 			})
 		}
 	}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 8 - 0
public/javascripts/jquery.loading.min.js


+ 12 - 20
public/javascripts/view.js

@@ -2,29 +2,21 @@
 app = new Vue({
 	el: '#app',
 	data: {
-		// 解析GUID需要的正则
-		guidregEx: /[?a-zA-Z0-9]{8}-[?a-zA-Z0-9]{4}-[?a-zA-Z0-9]{4}-[?a-zA-Z0-9]{4}-[?a-zA-Z0-9]{12}/,
 		status: -1,
 		text: null,
 	},
-	methods: {
-		getMsg: function() {
-			// 从URL获取GUID,然后透过POST获取消息
-			var guid = this.guidregEx.exec(window.location.href)[0];
-			axios.post('/api/get-msg', {
-				guid: guid
-			}).then(function (response) {
-				var data = response.data;
-				app.status = data.status;
-				app.text = data.text;
-				console.log(data);
-			}).catch(function (error) {
-				throw error;
-				alert('发生错误!')
-			});
-		}
-	},
 	mounted: function() {
-		this.getMsg();// 开始获取消息
+		// 从URL获取GUID,然后透过POST获取消息
+		var guid = reg_guid.exec(window.location.href)[0];
+		axios.post('/api/get-msg', {
+			guid: guid
+		}).then(function (response) {
+			var data = response.data;
+			app.status = data.status;
+			app.text = data.text;
+		}).catch(function (error) {
+			throw error;
+			alert('发生错误!')
+		});
 	}
 });

+ 1 - 0
public/stylesheets/jquery.loading.min.css

@@ -0,0 +1 @@
+.loading-overlay{display:table;opacity:.7}.loading-overlay-content{text-transform:uppercase;letter-spacing:.4em;font-size:1.15em;font-weight:700;text-align:center;display:table-cell;vertical-align:middle}.loading-overlay.loading-theme-light{background-color:#fff;color:#000}.loading-overlay.loading-theme-dark{background-color:#000;color:#fff}

+ 15 - 58
public/stylesheets/style.css

@@ -1,70 +1,27 @@
-body {
-  padding: 50px;
-  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
-}
+body {padding-top: 78px; font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; }
 
-a {
-  color: #00B7FF;
-}
+.getbtn {margin-top: 16px; margin-bottom: 10px; padding: 8px 35px; }
 
-#warning{
-	color: red;
-}
+pre {letter-spacing: 0.12em; white-space: pre-wrap; word-wrap: break-word; font-size: 1.05em; line-height: 1.6em; font-family: Georgia, Cambria, "Times New Roman", Times, serif;}
+footer a{ margin-right: 9px }
+footer { margin-bottom: 10px; }
+#zhao {color: red; }
 
-textarea { border: 2px dotted black;  }
+p.tips{ line-height: 1.8em; }
 
-button#dobtn { margin-top: 10px; padding: 5px 30px; cursor: pointer; border: 1px solid black;  transition: all .3s ease-in-out}
-button#dobtn:hover {background-color: black; color: white; transform: scale(.96); }
-button#dobtn:active { transform: scale(1.03); }
-#text_edit
-{
-	width: 70vw;
-}
+.maincontent{ min-height: 78vh }
 
-pre {
-white-space: pre-wrap;
-word-wrap: break-word;
+.fade-enter-active, .fade-leave-active {
+  transition: opacity .5s;
 }
-
-hr {
-	border:0; height:1px; background-color:#d4d4d4;
-	color:#d4d4d4	/* IE6 */
-}
-
-#zhao {
-	color: red;
+.fade-enter, .fade-leave-to
+  opacity: 0;
 }
 
 #enurl:hover { transform: scale(1.01); }
 
-#tg.show
-{
-	background: red;
-	width: 100vh;
-	opacity: 1;
-	color: yellow;
-	font-size: 10em;
-}
+#tg.show {background: red; width: 100vh; opacity: 1; color: yellow; font-size: 10em; }
 
-#tg
-{
-	top: 1vw;
-	left: 1vw;
-	width: 1px;
-	display: block;
-	position: absolute;
-	background: gray;
-	transition: all 2s ease-in;
-	opacity: 0;
-}
+#tg {top: 1vw; left: 1vw; width: 1px; display: block; position: absolute; background: gray; transition: all 2s ease-in; opacity: 0; }
 
-#enurl
-{
-	transition: all .3s ease-in-out;
-	margin: 3px 0;
-	display: inline-block;
-	color: white;
-	background-color: #66CCCC;
-	padding: 6px 12px;
-	border-radius: .5;
-}
+#enurl {transition: all .3s ease-in; margin: 3px 0; display: inline-block; color: #02B875; border: 1px solid; border-radius: .859em; padding: 8px 15px; margin-top: 9px; border-radius: .5; }

+ 12 - 3
routes/apis.js

@@ -1,13 +1,22 @@
+var util = require('util');
 var express = require('express');
 var router = express.Router();
 var conf = require('../config.js');
 var mtool = new (require('../lib/tools.js'))(conf);// 消息操作工具
+var RateLimit = require('express-rate-limit');
 
-/* GET home page. */
-router.post('/get-temp', function(req, res, next) {
+// 限制生成临时链接API的访问次数
+var apiLimiter = new RateLimit({
+    windowMs: 60 * 60 * 1000, // 1 hour
+    max: conf.rate_limit,    // 频次
+    delayMs: 0,               // disabled 延迟响应
+});
+
+/* 生成消息的GUID */
+router.post('/get-temp', apiLimiter, function(req, res, next) {
 	// 用户输出的内容
 	var text = req.body.text;
-
+	// 插入消息
 	mtool.insert(text, (status, guid) => {
 		rep = { status: status, guid: guid };
 		res.send(rep);

+ 3 - 3
routes/index.js

@@ -5,7 +5,7 @@ var mtool = new (require('../lib/tools.js'))(conf);// 消息操作工具
 
 /* GET home page. */
 router.get('/', function(req, res, next) {
-  res.render('index', { title: 'Naiveboom - 比较安全' });
+  res.render('index', { title: 'Naiveboom - 比较安全', isZhao: conf.isZhao});
 });
 
 /**
@@ -14,8 +14,8 @@ router.get('/', function(req, res, next) {
  * @param  {[type]} res) {	var        guid [description]
  * @return {[type]}      [description]
  */
-router.get(conf.regex_guid, function(req, res) {
-	res.render('look', {title: '查看内容 - naiveBoom!'});
+router.get(conf.reg_guid, function(req, res) {
+	res.render('look', {title: '查看内容 - naiveBoom!', reg_guid: conf.reg_guid});
 })
 
 module.exports = router;

+ 0 - 0
views/error.jade → views/error.pug


+ 0 - 32
views/index.jade

@@ -1,32 +0,0 @@
-extends layout
-block content
-
-    p 在下面的框框里输入一些内容,然后点一下「产生」按钮
-      | 你就会得到一个长的网址,将这个网址发给你的朋友,他只能看一次,内容就会 <b>永远消失</b>!
-
-      div#app
-        textarea(v-model='text' rows='10' id='text_edit')
-        br
-        button(v-on:click='getTempURL' id='dobtn') 去产生
-
-        br
-        span(v-show='enurl') 可以把这个网址分享给你的朋友: 
-        br
-        span(v-show='enurl' id='enurl') {{ enurl }}
-
-        hr
-        br
-
-        p Naiveboom - 让Naive的事情不再发生
-        | 这是一个简单的项目,可以一定程度保证你的安全。 <br>
-        | 举例:你有个链接或者一段文字需要发送给某人,但是是透过QQ、WeChat这类含
-        <span id='zhao' v-on:mouseenter='showtg=true'>赵☭</span>
-        | 量极高的服务去发送,这样会非常不安全,甚至会被查水表。<br>
-        | 现在可以透过这样的一个方案得以解决<br>
-        | 你将私密的链接或者文字粘贴到我们这个页面<br>
-        | 产生一个一次性链接<br>
-        | 阅后即焚<br>
-        | 嗯,这回你不会被查水表了(确信<br>
-
-        img(src='/images/zhao.png' id='tg', 'v-bind:class'='tgstyle')
-        script(src='/javascripts/a.js')

+ 59 - 0
views/index.pug

@@ -0,0 +1,59 @@
+extends layout
+block content
+
+    <div id='app'>
+        <div class="row">
+            <div class='col-md-10 col-xs-12 col-sm-12'>
+                <p> 在下面的框框里输入一些内容,然后点一下「去产生」按钮 
+                | <br>你就会得到一个长的网址,将这个网址发给你的朋友,他只能看一次
+                | 内容就会 <b>永远消失</b>! </p>
+                <textarea v-model='text' rows='6' class='form-control'></textarea>
+                <button v-on:click='getTempURL' class="btn btn-primary getbtn">去产生</button>
+                
+                <transition name="fade">
+                    <p v-if="enurl">
+                        |可以把这个网址分享给你的朋友:
+                        <span id='enurl'>{{ enurl }}</span>
+                    </p>
+                </transition>
+                hr
+                <p>
+                    | Naiveboom - 让Naive的事情不再发生
+                    | 这是一个简单的项目,可以一定程度保证你的安全。 <br>
+                    | 举例:你有个链接或者一段文字需要发送给某人,但是通过QQ、WeChat这类
+                    if (isZhao)
+                        | 含<span id='zhao' v-on:mouseenter='showtg=true'>赵☭</span>量极高
+                    else
+                        | 被中国严密监管
+                    | <br>的服务去发送,有的时候会非常不安全,甚至会被查水表。<br>
+                    | <br>现在可以透过这样的一个方案得以解决<br>
+                    | 你将私密的链接或者文字粘贴到我们这个页面<br>
+                    | 产生一个一次性链接<br>
+                    | 阅后即焚<br>
+                    | 嗯,这回你不会被查水表了(确信<br>
+                </p>
+                img(src='/images/zhao.png' id='tg', 'v-bind:class'='tgstyle')
+            </div>
+        </div>
+    </div>
+    //- modal
+    <div id='modal'>
+        <div id='mmodal' class="modal">
+          <div class="modal-dialog" role="document">
+            <div class="modal-content">
+              <div class="modal-header">
+                <h5 class="modal-title">{{ title }}</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                  <span aria-hidden="true">&times;</span>
+                </button>
+              </div>
+              <div class="modal-body" v-html='msg'>
+              </div>
+              <div class="modal-footer">
+                <button type="button" class="btn btn-primary" data-dismiss="modal">关闭</button>
+              </div>
+            </div>
+          </div>
+        </div>
+    </div>
+        script(src='/javascripts/a.js')

+ 0 - 18
views/layout.jade

@@ -1,18 +0,0 @@
-doctype html
-html
-  head
-    title= title
-    link(rel='stylesheet', href='/stylesheets/style.css')
-    meta(content='width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0' name='viewport')
-  body
-    h5= title
-    noscript
-      h3#warning !!!警告: 您禁用了JavaScript,请开启它。<br>如果您禁止使用JavaScript,将无法使用我们的服务!
-    script(src='/javascripts/vue.min.js')
-    script(src='/javascripts/axios.min.js')
-    block content
-    hr
-    footer
-         a(href='/') 首页
-         span &nbsp;&nbsp;
-         a(href='https://github.com/kchown/naiveboom' target='_blank') GitHub

+ 48 - 0
views/layout.pug

@@ -0,0 +1,48 @@
+doctype html
+html
+  head
+    title= title
+    link(rel='stylesheet', href='https://cdn.bootcss.com/bootswatch/4.0.0/litera/bootstrap.min.css')
+    script(src='https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js')
+    script(src='https://cdn.bootcss.com/bootstrap/4.0.0/js/bootstrap.min.js')
+    script(src='/javascripts/vue.min.js')
+    script(src='/javascripts/axios.min.js')
+    script(src='/javascripts/jquery.loading.min.js')
+
+    link(rel='stylesheet', href='/stylesheets/style.css')
+    link(rel='stylesheet', href='/stylesheets/jquery.loading.min.css')
+    meta(content='width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0' name='viewport')
+  body
+    <div class="navbar navbar-expand-lg fixed-top navbar-light bg-light" style="">
+          <div class="container">
+            <a href="/" class="navbar-brand">naiveBoom</a>
+            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation" style="">
+              <span class="navbar-toggler-icon"></span>
+            </button>
+            <div class="collapse navbar-collapse" id="navbarResponsive">
+              <ul class="navbar-nav">
+                <li class="nav-item">
+                  <a class="nav-link" target='_blank' href="https://github.com/kchown/naiveboom">GitHub</a>
+                </li>
+                <li class="nav-item">
+                  <a class="nav-link" target='_blank' href="https://kch.host">Blog</a>
+                </li>
+              </ul>
+            </div>
+          </div>
+    </div>
+    <div class="container maincontent">
+      <noscript>
+        <div class="alert alert-dismissible alert-danger">
+          <button type="button" class="close" data-dismiss="alert">&times;</button>
+          <strong>上帝啊!</strong> 您禁用了JavaScript,请开启它 <br> 如果您禁止使用JavaScript,将无法使用我们的服务!
+          <a href="http://www.chiefgroup.com.hk/temp/chiefeasy/how-to-enable-javascript.html" target='_blank' class="alert-link">查看如何开启Cookie</a>
+        </div>
+      </noscript>
+      block content
+    </div>
+    hr
+    footer
+      .container
+         a(href='/') 首页
+         a(href='https://github.com/kchown/naiveboom' target='_blank') GitHub

+ 0 - 18
views/look.jade

@@ -1,18 +0,0 @@
-extends layout
-block content
-	hr
-	#app
-		<div v-if='status==1'>
-		pre {{ text }}
-		</div>
-		<div v-else-if='status==0'>
-		h3 啊喔😯,你查看的内容已经不见了...
-		p 这是因为这个网址已经被看过一次了
-		| 被看过一次的内容就会自动消失
-		| 对,这就是人们常说的 <b>阅后即焚!</b>
-		a(href="/") 我也要生成一个!
-		</div>
-		<div v-else>
-		p#warning 正在获取...
-		</div>
-	script(src='/javascripts/view.js')

+ 20 - 0
views/look.pug

@@ -0,0 +1,20 @@
+extends layout
+block content
+	#app
+		<div v-if='status==1'>
+		pre {{ text }}
+		</div>
+		<div v-else-if='status==0'>
+		h6 啊喔😯,你查看的内容已经不见了...
+		p.tips 
+			| 这是因为这个网址已经被看过一次了,被看过一次的内容就会自动消失
+			| <br>对,这就是人们常说的 <b>阅后即焚!</b>
+		a(href="/") 我也要生成一个!
+		</div>
+		<div v-else>
+		p#warning 正在获取...
+		</div>
+	//- 输出用于匹配GUID的正则表达式
+	script.
+		reg_guid =  !{locals.reg_guid};
+	script(src='/javascripts/view.js')

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio