mirror of
https://github.com/ZSCNetSupportDept/WechatTicketSystem.git
synced 2025-10-30 01:46:18 +08:00
Compare commits
66 Commits
feature/ea
...
1.4-Conver
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
496827b152 | ||
|
|
ea9e78936d | ||
|
|
a804b79e6f | ||
|
|
78831e5c7a | ||
|
|
890c001832 | ||
|
|
9746f0d4b6 | ||
|
|
247da5ad83 | ||
|
|
ab590431af | ||
|
|
86c045aff2 | ||
|
|
461bdf2c27 | ||
|
|
83ef97609d | ||
|
|
4c837b36ae | ||
|
|
3e4ce1611d | ||
|
|
b28364f160 | ||
|
|
d45cbebd15 | ||
|
|
98a4e30c37 | ||
|
|
cb8757d8bf | ||
|
|
9e77961666 | ||
|
|
ebca69a1f3 | ||
|
|
78beb09ca6 | ||
|
|
caf83b3e70 | ||
|
|
cc3c9d30be | ||
|
|
710fa28ada | ||
|
|
633a3b184a | ||
|
|
9c2856e358 | ||
|
|
6483a39b63 | ||
|
|
ccdffd01d7 | ||
|
|
1e3a0754a4 | ||
|
|
1ce14b7d1a | ||
|
|
3e0c907655 | ||
|
|
a506a7742f | ||
|
|
df0034f2ea | ||
|
|
940bcaad8c | ||
|
|
4ddc2281b4 | ||
|
|
23f98e1951 | ||
|
|
25ae59c5e0 | ||
|
|
e929c69fdb | ||
|
|
d1956bae82 | ||
|
|
813a4a2b37 | ||
|
|
8f8e9cd620 | ||
|
|
a6cee3a0a6 | ||
|
|
f883c7dbf8 | ||
|
|
a7393ea772 | ||
|
|
29cbd4ae86 | ||
|
|
bad7bdbe45 | ||
|
|
0e14911650 | ||
|
|
37691b71c1 | ||
|
|
5d4a420a7b | ||
|
|
3c4b9bd80a | ||
|
|
183b3ec8d2 | ||
|
|
95278ccbb9 | ||
|
|
c973f0c63a | ||
|
|
66c04d42f1 | ||
|
|
b4065be9e1 | ||
|
|
288ac607c8 | ||
|
|
89f3c5cbca | ||
|
|
6a465ba1e5 | ||
|
|
05ea96bd9b | ||
|
|
d85408bcdd | ||
|
|
def90117e2 | ||
|
|
a3c36d265c | ||
|
|
5ef112711c | ||
|
|
b309876428 | ||
|
|
58381fa3e1 | ||
|
|
16135a8158 | ||
|
|
485e80ef5b |
2
pom.xml
2
pom.xml
@@ -4,7 +4,7 @@
|
|||||||
<name>WechatTicketSystem</name>
|
<name>WechatTicketSystem</name>
|
||||||
<groupId>love.sola.netsupport</groupId>
|
<groupId>love.sola.netsupport</groupId>
|
||||||
<artifactId>WechatTicketSystem</artifactId>
|
<artifactId>WechatTicketSystem</artifactId>
|
||||||
<version>1.1-SNAPSHOT</version>
|
<version>1.4-SNAPSHOT</version>
|
||||||
<packaging>war</packaging>
|
<packaging>war</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
66
src/main/java/love/sola/netsupport/api/CheckSession.java
Normal file
66
src/main/java/love/sola/netsupport/api/CheckSession.java
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package love.sola.netsupport.api;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import love.sola.netsupport.enums.Attribute;
|
||||||
|
import love.sola.netsupport.sql.SQLCore;
|
||||||
|
import love.sola.netsupport.util.ParseUtil;
|
||||||
|
import love.sola.netsupport.wechat.WechatSession;
|
||||||
|
import me.chanjar.weixin.common.session.WxSession;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/21.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
@WebServlet(name = "CheckSession", urlPatterns = "/api/checksession", loadOnStartup = 11)
|
||||||
|
public class CheckSession extends HttpServlet {
|
||||||
|
|
||||||
|
private Gson gson = SQLCore.gson;
|
||||||
|
|
||||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
doGet(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
request.setCharacterEncoding("utf-8");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
response.addHeader("Content-type", "application/json;charset=utf-8");
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
String json = gson.toJson(check(request));
|
||||||
|
out.println(ParseUtil.parseJsonP(request, json));
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response check(HttpServletRequest request) {
|
||||||
|
String t = request.getParameter("token");
|
||||||
|
if (t == null || t.isEmpty()) return new Response(Response.ResponseCode.UNAUTHORIZED);
|
||||||
|
WxSession s = WechatSession.get(t, false);
|
||||||
|
if (s == null) return new Response(Response.ResponseCode.UNAUTHORIZED);
|
||||||
|
String more = request.getParameter("more");
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put(Attribute.AUTHORIZED, s.getAttribute(Attribute.AUTHORIZED));
|
||||||
|
if (more != null){
|
||||||
|
switch (more) {
|
||||||
|
case "1":
|
||||||
|
result.put(Attribute.USER, s.getAttribute(Attribute.USER));
|
||||||
|
result.put(Attribute.OPERATOR, s.getAttribute(Attribute.OPERATOR));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Response(Response.ResponseCode.OK, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package love.sola.netsupport.api.admin;
|
package love.sola.netsupport.api;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import love.sola.netsupport.api.Response;
|
|
||||||
import love.sola.netsupport.enums.Access;
|
import love.sola.netsupport.enums.Access;
|
||||||
import love.sola.netsupport.enums.Attribute;
|
import love.sola.netsupport.enums.Attribute;
|
||||||
import love.sola.netsupport.pojo.Operator;
|
import love.sola.netsupport.pojo.Operator;
|
||||||
@@ -31,7 +30,7 @@ import java.io.PrintWriter;
|
|||||||
* ***********************************************
|
* ***********************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@WebServlet(name = "Login", urlPatterns = "/api/admin/login", loadOnStartup = 31)
|
@WebServlet(name = "Login", urlPatterns = "/api/admin/login", loadOnStartup = 12)
|
||||||
public class Login extends HttpServlet {
|
public class Login extends HttpServlet {
|
||||||
|
|
||||||
private Gson gson = SQLCore.gson;
|
private Gson gson = SQLCore.gson;
|
||||||
@@ -36,14 +36,12 @@ public class Response {
|
|||||||
PARAMETER_REQUIRED(-1),
|
PARAMETER_REQUIRED(-1),
|
||||||
ILLEGAL_PARAMETER(-2),
|
ILLEGAL_PARAMETER(-2),
|
||||||
REQUEST_FAILED(-3),
|
REQUEST_FAILED(-3),
|
||||||
AUTHORIZE_FAILED(-9),
|
LENGTH_LIMIT_EXCEEDED(-4),
|
||||||
USER_NOT_FOUND(-11),
|
USER_NOT_FOUND(-11),
|
||||||
TICKET_NOT_FOUND(-12),
|
TICKET_NOT_FOUND(-12),
|
||||||
OPERATOR_NOT_FOUND(-13),
|
OPERATOR_NOT_FOUND(-13),
|
||||||
UNAUTHORIZED(-20),
|
UNAUTHORIZED(-20),
|
||||||
REQUEST_EXPIRED(-21),
|
|
||||||
WRONG_PASSWORD(-22),
|
WRONG_PASSWORD(-22),
|
||||||
INCORRECT_WECHAT(-23),
|
|
||||||
PERMISSION_DENIED(-24),
|
PERMISSION_DENIED(-24),
|
||||||
INTERNAL_ERROR(-90),
|
INTERNAL_ERROR(-90),
|
||||||
DATABASE_ERROR(-91),
|
DATABASE_ERROR(-91),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package love.sola.netsupport.api.admin.root;
|
package love.sola.netsupport.api.manager;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import love.sola.netsupport.api.Response;
|
import love.sola.netsupport.api.Response;
|
||||||
@@ -28,7 +28,7 @@ import java.io.PrintWriter;
|
|||||||
* Don't modify this source without my agreement
|
* Don't modify this source without my agreement
|
||||||
* ***********************************************
|
* ***********************************************
|
||||||
*/
|
*/
|
||||||
@WebServlet(name = "GetUser",urlPatterns = "/api/admin/getuser",loadOnStartup = 42)
|
@WebServlet(name = "GetUser",urlPatterns = "/api/admin/getuser",loadOnStartup = 41)
|
||||||
public class GetUser extends HttpServlet {
|
public class GetUser extends HttpServlet {
|
||||||
|
|
||||||
private Gson gson = SQLCore.gson;
|
private Gson gson = SQLCore.gson;
|
||||||
@@ -59,7 +59,7 @@ public class GetUser extends HttpServlet {
|
|||||||
return new Response(Response.ResponseCode.UNAUTHORIZED);
|
return new Response(Response.ResponseCode.UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
Operator op = (Operator) session.getAttribute(Attribute.OPERATOR);
|
Operator op = (Operator) session.getAttribute(Attribute.OPERATOR);
|
||||||
if (op.getAccess() != Access.ROOT) {
|
if (op.getAccess() > Access.LEADER) {
|
||||||
return new Response(Response.ResponseCode.PERMISSION_DENIED);
|
return new Response(Response.ResponseCode.PERMISSION_DENIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package love.sola.netsupport.api.manager;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import love.sola.netsupport.api.Response;
|
||||||
|
import love.sola.netsupport.config.Settings;
|
||||||
|
import love.sola.netsupport.enums.Access;
|
||||||
|
import love.sola.netsupport.enums.Attribute;
|
||||||
|
import love.sola.netsupport.enums.Status;
|
||||||
|
import love.sola.netsupport.pojo.Operator;
|
||||||
|
import love.sola.netsupport.pojo.Ticket;
|
||||||
|
import love.sola.netsupport.pojo.User;
|
||||||
|
import love.sola.netsupport.sql.SQLCore;
|
||||||
|
import love.sola.netsupport.util.Checker;
|
||||||
|
import love.sola.netsupport.util.ParseUtil;
|
||||||
|
import love.sola.netsupport.wechat.Command;
|
||||||
|
import me.chanjar.weixin.common.session.WxSession;
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/22.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
@WebServlet(name = "TicketPush",urlPatterns = "/api/admin/ticketpush",loadOnStartup = 42)
|
||||||
|
public class TicketPush extends HttpServlet{
|
||||||
|
|
||||||
|
private Gson gson = SQLCore.gson;
|
||||||
|
|
||||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
doGet(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
request.setCharacterEncoding("utf-8");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
response.addHeader("Content-type", "application/json;charset=utf-8");
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
String json = gson.toJson(push(request));
|
||||||
|
out.println(ParseUtil.parseJsonP(request, json));
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response push(HttpServletRequest request) {
|
||||||
|
String uid = request.getParameter("uid");
|
||||||
|
String desc = request.getParameter("desc");
|
||||||
|
if (Checker.hasNull(uid, desc)) {
|
||||||
|
return new Response(Response.ResponseCode.PARAMETER_REQUIRED);
|
||||||
|
}
|
||||||
|
if (desc.length() > Settings.MAX_DESC_LENGTH) {
|
||||||
|
return new Response(Response.ResponseCode.LENGTH_LIMIT_EXCEEDED);
|
||||||
|
}
|
||||||
|
|
||||||
|
WxSession session = Checker.isAuthorized(request, Command.LOGIN);
|
||||||
|
if (session == null) {
|
||||||
|
return new Response(Response.ResponseCode.UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
Operator op = (Operator) session.getAttribute(Attribute.OPERATOR);
|
||||||
|
if (op.getAccess() > Access.LEADER) {
|
||||||
|
return new Response(Response.ResponseCode.PERMISSION_DENIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Session s = SQLCore.sf.openSession()) {
|
||||||
|
s.beginTransaction();
|
||||||
|
User u = s.get(User.class, Long.parseLong(uid));
|
||||||
|
if (u == null) {
|
||||||
|
return new Response(Response.ResponseCode.USER_NOT_FOUND);
|
||||||
|
}
|
||||||
|
Ticket t = new Ticket(null, u, desc, null, "Pushed By Admin", null, op, Status.UNCHECKED);
|
||||||
|
s.save(t);
|
||||||
|
s.getTransaction().commit();
|
||||||
|
return new Response(Response.ResponseCode.OK, t);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return new Response(Response.ResponseCode.ILLEGAL_PARAMETER);
|
||||||
|
} catch (HibernateException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new Response(Response.ResponseCode.DATABASE_ERROR, e.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new Response(Response.ResponseCode.INTERNAL_ERROR, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
package love.sola.netsupport.api.admin.root;
|
package love.sola.netsupport.api.root;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import love.sola.netsupport.enums.Access;
|
import love.sola.netsupport.enums.Access;
|
||||||
import love.sola.netsupport.enums.Attribute;
|
import love.sola.netsupport.enums.Attribute;
|
||||||
import love.sola.netsupport.pojo.Operator;
|
import love.sola.netsupport.pojo.Operator;
|
||||||
import love.sola.netsupport.sql.SQLCore;
|
|
||||||
import love.sola.netsupport.util.Checker;
|
import love.sola.netsupport.util.Checker;
|
||||||
import love.sola.netsupport.wechat.Command;
|
import love.sola.netsupport.wechat.Command;
|
||||||
import love.sola.netsupport.wechat.WechatSession;
|
import love.sola.netsupport.wechat.WechatSession;
|
||||||
@@ -27,25 +25,24 @@ import java.util.Enumeration;
|
|||||||
* ***********************************************
|
* ***********************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@WebServlet(name = "Dashboard", urlPatterns = "/api/admin/dashboard", loadOnStartup = 41)
|
@WebServlet(name = "Dashboard", urlPatterns = "/api/root/dashboard", loadOnStartup = 51)
|
||||||
public class DashBoard extends HttpServlet {
|
public class DashBoard extends HttpServlet {
|
||||||
|
|
||||||
private Gson gson = SQLCore.gson;
|
|
||||||
|
|
||||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
doGet(request, response);
|
doGet(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
request.setCharacterEncoding("utf-8");
|
request.setCharacterEncoding("utf-8");
|
||||||
response.setCharacterEncoding("utf-8");
|
response.setCharacterEncoding("utf-8");
|
||||||
response.addHeader("Content-type", "text/plain;charset=utf-8");
|
response.addHeader("Content-type", "text/plain;charset=utf-8");
|
||||||
PrintWriter out = response.getWriter();
|
PrintWriter out = response.getWriter();
|
||||||
print(request, out);
|
process(request, out);
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void print(HttpServletRequest request, PrintWriter out) {
|
private void process(HttpServletRequest request, PrintWriter out) {
|
||||||
WxSession session = Checker.isAuthorized(request, Command.LOGIN);
|
WxSession session = Checker.isAuthorized(request, Command.LOGIN);
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
out.println("Unauthorized");
|
out.println("Unauthorized");
|
||||||
59
src/main/java/love/sola/netsupport/api/root/FlushCache.java
Normal file
59
src/main/java/love/sola/netsupport/api/root/FlushCache.java
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package love.sola.netsupport.api.root;
|
||||||
|
|
||||||
|
import love.sola.netsupport.enums.Access;
|
||||||
|
import love.sola.netsupport.enums.Attribute;
|
||||||
|
import love.sola.netsupport.pojo.Operator;
|
||||||
|
import love.sola.netsupport.sql.TableUser;
|
||||||
|
import love.sola.netsupport.util.Checker;
|
||||||
|
import love.sola.netsupport.wechat.Command;
|
||||||
|
import me.chanjar.weixin.common.session.WxSession;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/15.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
@WebServlet(name = "FlushCache", urlPatterns = "/api/root/flushcache", loadOnStartup = 52)
|
||||||
|
public class FlushCache extends HttpServlet {
|
||||||
|
|
||||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
doGet(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
request.setCharacterEncoding("utf-8");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
response.addHeader("Content-type", "text/plain;charset=utf-8");
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
process(request, out);
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void process(HttpServletRequest request, PrintWriter out) {
|
||||||
|
WxSession session = Checker.isAuthorized(request, Command.LOGIN);
|
||||||
|
if (session == null) {
|
||||||
|
out.println("Unauthorized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operator op = (Operator) session.getAttribute(Attribute.OPERATOR);
|
||||||
|
if (op.getAccess() != Access.ROOT) {
|
||||||
|
out.println("Unauthorized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TableUser.flushCache();
|
||||||
|
out.println("Flushed wechat cache");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
80
src/main/java/love/sola/netsupport/api/root/SetPassword.java
Normal file
80
src/main/java/love/sola/netsupport/api/root/SetPassword.java
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package love.sola.netsupport.api.root;
|
||||||
|
|
||||||
|
import love.sola.netsupport.enums.Access;
|
||||||
|
import love.sola.netsupport.enums.Attribute;
|
||||||
|
import love.sola.netsupport.pojo.Operator;
|
||||||
|
import love.sola.netsupport.sql.SQLCore;
|
||||||
|
import love.sola.netsupport.util.Checker;
|
||||||
|
import love.sola.netsupport.util.Crypto;
|
||||||
|
import love.sola.netsupport.wechat.Command;
|
||||||
|
import me.chanjar.weixin.common.session.WxSession;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/20.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
@WebServlet(name = "SetPassword",urlPatterns = "/api/root/setpass",loadOnStartup = 53)
|
||||||
|
public class SetPassword extends HttpServlet{
|
||||||
|
|
||||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
doGet(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
request.setCharacterEncoding("utf-8");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
response.addHeader("Content-type", "text/plain;charset=utf-8");
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
process(request, out);
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void process(HttpServletRequest request, PrintWriter out) {
|
||||||
|
WxSession session = Checker.isAuthorized(request, Command.LOGIN);
|
||||||
|
if (session == null) {
|
||||||
|
out.println("Unauthorized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operator op = (Operator) session.getAttribute(Attribute.OPERATOR);
|
||||||
|
if (op.getAccess() != Access.ROOT) {
|
||||||
|
out.println("Unauthorized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String id = request.getParameter("id");
|
||||||
|
String pass = request.getParameter("pass");
|
||||||
|
if (pass == null || pass.length() < 8) {
|
||||||
|
out.println("Invalid pass");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try (Session s = SQLCore.sf.openSession()) {
|
||||||
|
s.beginTransaction();
|
||||||
|
op = s.get(Operator.class, Integer.parseInt(id));
|
||||||
|
if (op == null) {
|
||||||
|
out.println("Invalid user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
op.setPassword(Crypto.hash(pass));
|
||||||
|
s.update(op);
|
||||||
|
s.getTransaction().commit();
|
||||||
|
out.println("Operation success");
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
out.println("Invalid id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
98
src/main/java/love/sola/netsupport/api/stuff/TicketLog.java
Normal file
98
src/main/java/love/sola/netsupport/api/stuff/TicketLog.java
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package love.sola.netsupport.api.stuff;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import love.sola.netsupport.api.Response;
|
||||||
|
import love.sola.netsupport.pojo.Ticket;
|
||||||
|
import love.sola.netsupport.sql.SQLCore;
|
||||||
|
import love.sola.netsupport.sql.TableTicket;
|
||||||
|
import love.sola.netsupport.util.Checker;
|
||||||
|
import love.sola.netsupport.util.ParseUtil;
|
||||||
|
import love.sola.netsupport.wechat.Command;
|
||||||
|
import me.chanjar.weixin.common.session.WxSession;
|
||||||
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.envers.AuditReader;
|
||||||
|
import org.hibernate.envers.query.AuditEntity;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/18.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
@WebServlet(name = "TicketLog", urlPatterns = "/api/admin/ticketlog", loadOnStartup = 35)
|
||||||
|
public class TicketLog extends HttpServlet {
|
||||||
|
|
||||||
|
public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
|
||||||
|
private Gson gson = SQLCore.gson;
|
||||||
|
|
||||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
doGet(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
request.setCharacterEncoding("utf-8");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
response.addHeader("Content-type", "application/json;charset=utf-8");
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
String json = gson.toJson(query(request));
|
||||||
|
out.println(ParseUtil.parseJsonP(request, json));
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response query(HttpServletRequest request) {
|
||||||
|
WxSession session = Checker.isAuthorized(request, Command.LOGIN);
|
||||||
|
if (session == null) {
|
||||||
|
return new Response(Response.ResponseCode.UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
int first;
|
||||||
|
int limit;
|
||||||
|
Date start;
|
||||||
|
Date end;
|
||||||
|
try {
|
||||||
|
first = request.getParameter("first") == null ? 0 : Integer.parseInt(request.getParameter("first"));
|
||||||
|
limit = request.getParameter("limit") == null ? 20 : Integer.parseInt(request.getParameter("limit"));
|
||||||
|
start = request.getParameter("start") == null ? getToday() : dateFormat.parse(request.getParameter("start"));
|
||||||
|
end = request.getParameter("end") == null ? getToday() : dateFormat.parse(request.getParameter("end"));
|
||||||
|
end = DateUtils.addDays(end, 1);
|
||||||
|
} catch (ParseException | NumberFormatException e) {
|
||||||
|
return new Response(Response.ResponseCode.ILLEGAL_PARAMETER);
|
||||||
|
}
|
||||||
|
try (Session s = SQLCore.sf.openSession()) {
|
||||||
|
AuditReader reader = TableTicket.getAuditReader(s);
|
||||||
|
Object obj = reader.createQuery()
|
||||||
|
.forRevisionsOfEntity(Ticket.class, false, true)
|
||||||
|
.addOrder(AuditEntity.revisionNumber().desc())
|
||||||
|
.add(AuditEntity.revisionProperty("timestamp").between(start.getTime(), end.getTime()))
|
||||||
|
.setFirstResult(first)
|
||||||
|
.setMaxResults(limit)
|
||||||
|
.getResultList();
|
||||||
|
return new Response(Response.ResponseCode.OK, obj);
|
||||||
|
} catch (HibernateException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new Response(Response.ResponseCode.DATABASE_ERROR, e.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new Response(Response.ResponseCode.INTERNAL_ERROR, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Date getToday() {
|
||||||
|
return DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
package love.sola.netsupport.api.admin;
|
package love.sola.netsupport.api.stuff;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import love.sola.netsupport.api.Response;
|
import love.sola.netsupport.api.Response;
|
||||||
|
import love.sola.netsupport.enums.Access;
|
||||||
import love.sola.netsupport.enums.Attribute;
|
import love.sola.netsupport.enums.Attribute;
|
||||||
import love.sola.netsupport.pojo.Operator;
|
import love.sola.netsupport.pojo.Operator;
|
||||||
import love.sola.netsupport.pojo.Ticket;
|
import love.sola.netsupport.pojo.Ticket;
|
||||||
@@ -28,7 +29,7 @@ import java.util.List;
|
|||||||
* Don't modify this source without my agreement
|
* Don't modify this source without my agreement
|
||||||
* ***********************************************
|
* ***********************************************
|
||||||
*/
|
*/
|
||||||
@WebServlet(name = "TicketLookup", urlPatterns = "/api/admin/ticketlookup", loadOnStartup = 24)
|
@WebServlet(name = "TicketLookup", urlPatterns = "/api/admin/ticketlookup", loadOnStartup = 33)
|
||||||
public class TicketLookup extends HttpServlet {
|
public class TicketLookup extends HttpServlet {
|
||||||
|
|
||||||
private Gson gson = SQLCore.gson;
|
private Gson gson = SQLCore.gson;
|
||||||
@@ -60,6 +61,9 @@ public class TicketLookup extends HttpServlet {
|
|||||||
} else {
|
} else {
|
||||||
block = op.getBlock();
|
block = op.getBlock();
|
||||||
}
|
}
|
||||||
|
if (block == 0 && op.getAccess() > Access.LEADER) {
|
||||||
|
return new Response(Response.ResponseCode.PERMISSION_DENIED);
|
||||||
|
}
|
||||||
List<Ticket> list = TableTicket.unsolvedByBlock(block);
|
List<Ticket> list = TableTicket.unsolvedByBlock(block);
|
||||||
return new Response(Response.ResponseCode.OK, list);
|
return new Response(Response.ResponseCode.OK, list);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package love.sola.netsupport.api.stuff;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import love.sola.netsupport.api.Response;
|
||||||
|
import love.sola.netsupport.sql.SQLCore;
|
||||||
|
import love.sola.netsupport.sql.TableTicket;
|
||||||
|
import love.sola.netsupport.util.Checker;
|
||||||
|
import love.sola.netsupport.util.ParseUtil;
|
||||||
|
import love.sola.netsupport.wechat.Command;
|
||||||
|
import me.chanjar.weixin.common.session.WxSession;
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/18.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
@WebServlet(name = "TicketTrack", urlPatterns = "/api/admin/tickettrack", loadOnStartup = 34)
|
||||||
|
public class TicketTrack extends HttpServlet{
|
||||||
|
|
||||||
|
private Gson gson = SQLCore.gson;
|
||||||
|
|
||||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
doGet(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
request.setCharacterEncoding("utf-8");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
response.addHeader("Content-type", "application/json;charset=utf-8");
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
String json = gson.toJson(track(request));
|
||||||
|
out.println(ParseUtil.parseJsonP(request, json));
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response track(HttpServletRequest request) {
|
||||||
|
String tid = request.getParameter("id");
|
||||||
|
if (tid == null) {
|
||||||
|
return new Response(Response.ResponseCode.PARAMETER_REQUIRED);
|
||||||
|
}
|
||||||
|
WxSession session = Checker.isAuthorized(request, Command.LOGIN);
|
||||||
|
if (session == null) {
|
||||||
|
return new Response(Response.ResponseCode.UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return new Response(Response.ResponseCode.OK, TableTicket.track(Integer.parseInt(tid)));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return new Response(Response.ResponseCode.ILLEGAL_PARAMETER);
|
||||||
|
} catch (HibernateException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new Response(Response.ResponseCode.DATABASE_ERROR, e.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new Response(Response.ResponseCode.INTERNAL_ERROR, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package love.sola.netsupport.api.admin;
|
package love.sola.netsupport.api.stuff;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import love.sola.netsupport.api.Response;
|
import love.sola.netsupport.api.Response;
|
||||||
@@ -20,6 +20,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ***********************************************
|
* ***********************************************
|
||||||
@@ -64,6 +65,7 @@ public class TicketUpdate extends HttpServlet {
|
|||||||
t.setOperator(op);
|
t.setOperator(op);
|
||||||
t.setRemark(remark);
|
t.setRemark(remark);
|
||||||
t.setStatus(Integer.parseInt(status));
|
t.setStatus(Integer.parseInt(status));
|
||||||
|
t.setUpdateTime(new Date());
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
s.update(t);
|
s.update(t);
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package love.sola.netsupport.api;
|
package love.sola.netsupport.api.user;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import love.sola.netsupport.api.Response;
|
||||||
import love.sola.netsupport.enums.Attribute;
|
import love.sola.netsupport.enums.Attribute;
|
||||||
import love.sola.netsupport.enums.ISP;
|
import love.sola.netsupport.enums.ISP;
|
||||||
import love.sola.netsupport.pojo.User;
|
import love.sola.netsupport.pojo.User;
|
||||||
@@ -60,17 +61,18 @@ public class ProfileModify extends HttpServlet {
|
|||||||
int block = checkBlock(request.getParameter("block"));
|
int block = checkBlock(request.getParameter("block"));
|
||||||
int room = checkRoom(request.getParameter("room"), block);
|
int room = checkRoom(request.getParameter("room"), block);
|
||||||
long phone = checkPhoneNumber(request.getParameter("phone"));
|
long phone = checkPhoneNumber(request.getParameter("phone"));
|
||||||
if (netAccount != null) {
|
if (room == -1)
|
||||||
u.setIsp(isp);
|
return new Response(Response.ResponseCode.REQUEST_FAILED, "Invalid_Room");
|
||||||
u.setNetAccount(netAccount);
|
if (phone == -1)
|
||||||
}
|
return new Response(Response.ResponseCode.REQUEST_FAILED, "Invalid_Phone_Number");
|
||||||
if (room != -1) {
|
if (netAccount == null)
|
||||||
u.setBlock(block);
|
return new Response(Response.ResponseCode.REQUEST_FAILED, "Invalid_Account");
|
||||||
u.setRoom(room);
|
|
||||||
}
|
u.setIsp(isp);
|
||||||
if (phone != -1) {
|
u.setNetAccount(netAccount);
|
||||||
u.setPhone(phone);
|
u.setBlock(block);
|
||||||
}
|
u.setRoom(room);
|
||||||
|
u.setPhone(phone);
|
||||||
try {
|
try {
|
||||||
TableUser.update(u);
|
TableUser.update(u);
|
||||||
} catch (ConstraintViolationException e) {
|
} catch (ConstraintViolationException e) {
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package love.sola.netsupport.api;
|
package love.sola.netsupport.api.user;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import love.sola.netsupport.api.Response;
|
||||||
import love.sola.netsupport.enums.Attribute;
|
import love.sola.netsupport.enums.Attribute;
|
||||||
import love.sola.netsupport.enums.ISP;
|
import love.sola.netsupport.enums.ISP;
|
||||||
import love.sola.netsupport.pojo.User;
|
import love.sola.netsupport.pojo.User;
|
||||||
@@ -9,7 +10,10 @@ import love.sola.netsupport.sql.TableUser;
|
|||||||
import love.sola.netsupport.util.Checker;
|
import love.sola.netsupport.util.Checker;
|
||||||
import love.sola.netsupport.util.ParseUtil;
|
import love.sola.netsupport.util.ParseUtil;
|
||||||
import love.sola.netsupport.wechat.Command;
|
import love.sola.netsupport.wechat.Command;
|
||||||
|
import love.sola.netsupport.wechat.WxMpServlet;
|
||||||
|
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||||
import me.chanjar.weixin.common.session.WxSession;
|
import me.chanjar.weixin.common.session.WxSession;
|
||||||
|
import me.chanjar.weixin.mp.bean.WxMpCustomMessage;
|
||||||
import org.hibernate.exception.ConstraintViolationException;
|
import org.hibernate.exception.ConstraintViolationException;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
@@ -19,6 +23,10 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import static love.sola.netsupport.util.Checker.*;
|
import static love.sola.netsupport.util.Checker.*;
|
||||||
|
|
||||||
@@ -100,6 +108,8 @@ public class Register extends HttpServlet {
|
|||||||
String dupKey = e.getConstraintName();
|
String dupKey = e.getConstraintName();
|
||||||
return "Duplicated_" + dupKey.toUpperCase(); // PHONE ACCOUNT WECHAT
|
return "Duplicated_" + dupKey.toUpperCase(); // PHONE ACCOUNT WECHAT
|
||||||
}
|
}
|
||||||
|
// FIXME: 2015/12/30 Temporary converter
|
||||||
|
converterWithRetry(user);
|
||||||
return "Register_Success";
|
return "Register_Success";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,4 +119,45 @@ public class Register extends HttpServlet {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void converterWithRetry(User u) {
|
||||||
|
Throwable last = null;
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
try {
|
||||||
|
converter(u);
|
||||||
|
return;
|
||||||
|
} catch (WxErrorException | SQLException e) {
|
||||||
|
last = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last.printStackTrace();
|
||||||
|
try {
|
||||||
|
WxMpServlet.instance.wxMpService.customMessageSend(WxMpCustomMessage.TEXT().toUser(u.getWechatId()).content("数据转换失败").build());
|
||||||
|
} catch (WxErrorException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void converter(User u) throws WxErrorException, SQLException {
|
||||||
|
try (Connection conn = SQLCore.ds.getConnection()) {
|
||||||
|
PreparedStatement ps = conn.prepareStatement("SELECT wechat FROM `convert` WHERE id=?");
|
||||||
|
ps.setLong(1, u.getId());
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
WxMpServlet.instance.wxMpService
|
||||||
|
.userUpdateGroup(u.getWechatId(), 100L);
|
||||||
|
String old = rs.getString(1);
|
||||||
|
ps = conn.prepareStatement("UPDATE `operators` SET wechat=? WHERE wechat=?");
|
||||||
|
ps.setString(1, u.getWechatId());
|
||||||
|
ps.setString(2, old);
|
||||||
|
if (ps.executeUpdate() == 1) {
|
||||||
|
WxMpServlet.instance.wxMpService.customMessageSend(WxMpCustomMessage.TEXT().toUser(u.getWechatId()).content("数据转换成功").build());
|
||||||
|
} else {
|
||||||
|
WxMpServlet.instance.wxMpService.customMessageSend(WxMpCustomMessage.TEXT().toUser(u.getWechatId()).content("已进行过数据转换").build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException | WxErrorException e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package love.sola.netsupport.api;
|
package love.sola.netsupport.api.user;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import love.sola.netsupport.api.Response;
|
||||||
import love.sola.netsupport.enums.Attribute;
|
import love.sola.netsupport.enums.Attribute;
|
||||||
import love.sola.netsupport.pojo.Ticket;
|
import love.sola.netsupport.pojo.Ticket;
|
||||||
import love.sola.netsupport.pojo.User;
|
import love.sola.netsupport.pojo.User;
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package love.sola.netsupport.api;
|
package love.sola.netsupport.api.user;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import love.sola.netsupport.api.Response;
|
||||||
|
import love.sola.netsupport.config.Settings;
|
||||||
import love.sola.netsupport.enums.Attribute;
|
import love.sola.netsupport.enums.Attribute;
|
||||||
import love.sola.netsupport.pojo.Ticket;
|
import love.sola.netsupport.pojo.Ticket;
|
||||||
import love.sola.netsupport.pojo.User;
|
import love.sola.netsupport.pojo.User;
|
||||||
@@ -51,6 +53,9 @@ public class TicketSubmit extends HttpServlet {
|
|||||||
if (desc == null || desc.isEmpty()) {
|
if (desc == null || desc.isEmpty()) {
|
||||||
return new Response(Response.ResponseCode.PARAMETER_REQUIRED);
|
return new Response(Response.ResponseCode.PARAMETER_REQUIRED);
|
||||||
}
|
}
|
||||||
|
if (desc.length() > Settings.MAX_DESC_LENGTH) {
|
||||||
|
return new Response(Response.ResponseCode.LENGTH_LIMIT_EXCEEDED);
|
||||||
|
}
|
||||||
|
|
||||||
try (Session s = SQLCore.sf.openSession()) {
|
try (Session s = SQLCore.sf.openSession()) {
|
||||||
|
|
||||||
33
src/main/java/love/sola/netsupport/config/Cortana.java
Normal file
33
src/main/java/love/sola/netsupport/config/Cortana.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package love.sola.netsupport.config;
|
||||||
|
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/29.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
public class Cortana {
|
||||||
|
|
||||||
|
|
||||||
|
public static List<Compiled> entries;
|
||||||
|
|
||||||
|
public static void load() {
|
||||||
|
InputStream in = Lang.class.getClassLoader().getResourceAsStream("cortana.yml");
|
||||||
|
Map<String, Object> root = (Map<String, Object>) new Yaml().load(in);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Compiled {
|
||||||
|
Pattern[] patterns;
|
||||||
|
String[] replies;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,8 +19,8 @@ public class Lang {
|
|||||||
public static Map<String, MessageFormat> format_cache = new HashMap<>(32);
|
public static Map<String, MessageFormat> format_cache = new HashMap<>(32);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
//noinspection unchecked
|
|
||||||
InputStream in = Lang.class.getClassLoader().getResourceAsStream("lang.yml");
|
InputStream in = Lang.class.getClassLoader().getResourceAsStream("lang.yml");
|
||||||
|
//noinspection unchecked
|
||||||
messages = new Yaml().loadAs(in, Map.class);
|
messages = new Yaml().loadAs(in, Map.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import love.sola.netsupport.sql.TableConfig;
|
|||||||
@ToString
|
@ToString
|
||||||
public class Settings {
|
public class Settings {
|
||||||
|
|
||||||
|
public static final int MAX_DESC_LENGTH = 255;
|
||||||
|
|
||||||
public static Settings I;
|
public static Settings I;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -29,9 +31,8 @@ public class Settings {
|
|||||||
public int Check_Spam_Cache_Expire_Time;
|
public int Check_Spam_Cache_Expire_Time;
|
||||||
public int Check_Spam_Interval;
|
public int Check_Spam_Interval;
|
||||||
|
|
||||||
public int User_Caching_Time;
|
|
||||||
|
|
||||||
public int User_Session_Max_Inactive;
|
public int User_Session_Max_Inactive;
|
||||||
|
public int User_Wechat_Cache_Expire_Time;
|
||||||
|
|
||||||
//No arg constructor for Yaml.loadAs
|
//No arg constructor for Yaml.loadAs
|
||||||
public Settings() { I = this; }
|
public Settings() { I = this; }
|
||||||
|
|||||||
@@ -15,6 +15,14 @@ import static love.sola.netsupport.config.Lang.lang;
|
|||||||
public class Access {
|
public class Access {
|
||||||
|
|
||||||
public static final int ROOT = 0;
|
public static final int ROOT = 0;
|
||||||
|
public static final int MANAGER = 1;
|
||||||
|
public static final int CO_MANAGER = 2;
|
||||||
|
public static final int LEADER = 3;
|
||||||
|
public static final int CO_LEADER = 4;
|
||||||
|
public static final int ELITE = 5;
|
||||||
|
public static final int ELDER = 6;
|
||||||
|
public static final int MEMBER = 7;
|
||||||
|
public static final int PRE_MEMBER = 8;
|
||||||
public static final int NOLOGIN = 9;
|
public static final int NOLOGIN = 9;
|
||||||
|
|
||||||
public static final Map<Integer, String> inverseMap = new HashMap<>();
|
public static final Map<Integer, String> inverseMap = new HashMap<>();
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ public class Block {
|
|||||||
public static final int DM_13 = 31;
|
public static final int DM_13 = 31;
|
||||||
public static final int DM_14 = 32;
|
public static final int DM_14 = 32;
|
||||||
public static final int DM_15 = 33;
|
public static final int DM_15 = 33;
|
||||||
|
public static final int DM_20 = 34;
|
||||||
|
public static final int DM_21 = 35;
|
||||||
public static final int XH_A = 40;
|
public static final int XH_A = 40;
|
||||||
public static final int XH_B = 41;
|
public static final int XH_B = 41;
|
||||||
public static final int XH_C = 42;
|
public static final int XH_C = 42;
|
||||||
@@ -35,8 +37,6 @@ public class Block {
|
|||||||
public static final int FX_4 = 53;
|
public static final int FX_4 = 53;
|
||||||
public static final int FX_5 = 54;
|
public static final int FX_5 = 54;
|
||||||
public static final int FX_6 = 55;
|
public static final int FX_6 = 55;
|
||||||
public static final int DM_20 = 60;
|
|
||||||
public static final int DM_21 = 61;
|
|
||||||
|
|
||||||
public static final Map<Integer, String> inverseMap = new HashMap<>();
|
public static final Map<Integer, String> inverseMap = new HashMap<>();
|
||||||
|
|
||||||
@@ -67,8 +67,8 @@ public class Block {
|
|||||||
AVAILABLE[BM_7] = new int[]{100, 216, 317, 417, 517, 617, 717};
|
AVAILABLE[BM_7] = new int[]{100, 216, 317, 417, 517, 617, 717};
|
||||||
AVAILABLE[BM_8] = new int[]{100, 221, 321, 421, 521, 621, 721};
|
AVAILABLE[BM_8] = new int[]{100, 221, 321, 421, 521, 621, 721};
|
||||||
AVAILABLE[BM_9] = new int[]{100, 221, 321, 421, 521, 621};
|
AVAILABLE[BM_9] = new int[]{100, 221, 321, 421, 521, 621};
|
||||||
AVAILABLE[BM_10] = new int[]{111, 239, 339, 439, 558, 658, 758, 858};
|
AVAILABLE[BM_10] = new int[]{111, 239, 354, 454, 564, 664, 764, 864};
|
||||||
AVAILABLE[BM_11] = new int[]{100, 220, 320, 420, 520, 620, 720, 820};
|
AVAILABLE[BM_11] = new int[]{100, 213, 321, 421, 521, 621, 721, 821};
|
||||||
AVAILABLE[DM_12] = new int[]{119, 221, 321, 421, 521, 621, 720};
|
AVAILABLE[DM_12] = new int[]{119, 221, 321, 421, 521, 621, 720};
|
||||||
AVAILABLE[DM_13] = new int[]{120, 222, 322, 422, 522, 622, 722};
|
AVAILABLE[DM_13] = new int[]{120, 222, 322, 422, 522, 622, 722};
|
||||||
AVAILABLE[DM_14] = new int[]{100, 230, 330, 430, 530, 630, 730};
|
AVAILABLE[DM_14] = new int[]{100, 230, 330, 430, 530, 630, 730};
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ public class Status {
|
|||||||
public static final int UNCHECKED = 0;
|
public static final int UNCHECKED = 0;
|
||||||
public static final int ARRANGED = 1;
|
public static final int ARRANGED = 1;
|
||||||
public static final int PUTOFF = 2;
|
public static final int PUTOFF = 2;
|
||||||
|
public static final int REPORTED = 4;
|
||||||
|
public static final int ISP_HANDLED = 7;
|
||||||
public static final int SOLVED = 9;
|
public static final int SOLVED = 9;
|
||||||
|
|
||||||
public static final Map<Integer, String> inverseMap = new HashMap<>();
|
public static final Map<Integer, String> inverseMap = new HashMap<>();
|
||||||
|
|||||||
@@ -42,4 +42,10 @@ public class User {
|
|||||||
private Integer room;
|
private Integer room;
|
||||||
private Long phone;
|
private Long phone;
|
||||||
|
|
||||||
|
|
||||||
|
//System Accounts
|
||||||
|
public static User OFFICIAL_CHINA_UNICOM_XH;
|
||||||
|
public static User OFFICIAL_CHINA_MOBILE_XH;
|
||||||
|
public static User OFFICIAL_CHINA_MOBILE_FX;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,24 @@ package love.sola.netsupport.sql;
|
|||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
import com.google.gson.annotations.Expose;
|
import com.google.gson.annotations.Expose;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
import love.sola.netsupport.enums.ISP;
|
import love.sola.netsupport.enums.ISP;
|
||||||
|
import love.sola.netsupport.wechat.Command;
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
|
import org.hibernate.Session;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.boot.MetadataSources;
|
import org.hibernate.boot.MetadataSources;
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.envers.AuditReader;
|
||||||
|
import org.hibernate.envers.AuditReaderFactory;
|
||||||
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,6 +60,9 @@ public class SQLCore {
|
|||||||
.registerTypeAdapter(Date.class, (JsonSerializer<Date>) (src, typeOfSrc, context) -> new JsonPrimitive(src.getTime()))
|
.registerTypeAdapter(Date.class, (JsonSerializer<Date>) (src, typeOfSrc, context) -> new JsonPrimitive(src.getTime()))
|
||||||
.registerTypeAdapter(ISP.class, (JsonDeserializer<ISP>) (json, typeOfT, context) -> ISP.fromId(json.getAsJsonPrimitive().getAsInt()))
|
.registerTypeAdapter(ISP.class, (JsonDeserializer<ISP>) (json, typeOfT, context) -> ISP.fromId(json.getAsJsonPrimitive().getAsInt()))
|
||||||
.registerTypeAdapter(ISP.class, (JsonSerializer<ISP>) (src, typeOfSrc, context) -> new JsonPrimitive(src.id))
|
.registerTypeAdapter(ISP.class, (JsonSerializer<ISP>) (src, typeOfSrc, context) -> new JsonPrimitive(src.id))
|
||||||
|
.registerTypeAdapter(Command.class, (JsonDeserializer<Command>) (json, typeOfT, context) -> Command.fromId(json.getAsJsonPrimitive().getAsInt()))
|
||||||
|
.registerTypeAdapter(Command.class, (JsonSerializer<Command>) (src, typeOfSrc, context) -> new JsonPrimitive(src.id))
|
||||||
|
.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY)
|
||||||
.create();
|
.create();
|
||||||
public static SessionFactory sf;
|
public static SessionFactory sf;
|
||||||
public static ServiceRegistry sr;
|
public static ServiceRegistry sr;
|
||||||
@@ -63,10 +76,54 @@ public class SQLCore {
|
|||||||
sr = new StandardServiceRegistryBuilder().configure().build();
|
sr = new StandardServiceRegistryBuilder().configure().build();
|
||||||
sf = new MetadataSources(sr).buildMetadata().buildSessionFactory();
|
sf = new MetadataSources(sr).buildMetadata().buildSessionFactory();
|
||||||
|
|
||||||
|
TableUser.init();
|
||||||
TableOperator.init();
|
TableOperator.init();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static AuditReader getAuditReader(Session session) {
|
||||||
|
return AuditReaderFactory.get(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HibernateProxyTypeAdapter extends TypeAdapter<HibernateProxy> {
|
||||||
|
|
||||||
|
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||||
|
return (HibernateProxy.class.isAssignableFrom(type.getRawType()) ? (TypeAdapter<T>) new HibernateProxyTypeAdapter(gson) : null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final Gson context;
|
||||||
|
|
||||||
|
private HibernateProxyTypeAdapter(Gson context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HibernateProxy read(JsonReader in) throws IOException {
|
||||||
|
throw new UnsupportedOperationException("Not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Override
|
||||||
|
public void write(JsonWriter out, HibernateProxy value) throws IOException {
|
||||||
|
if (value == null) {
|
||||||
|
out.nullValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Retrieve the original (not proxy) class
|
||||||
|
Class<?> baseType = Hibernate.getClass(value);
|
||||||
|
// Get the TypeAdapter of the original class, to delegate the serialization
|
||||||
|
TypeAdapter delegate = context.getAdapter(TypeToken.get(baseType));
|
||||||
|
// Get a filled instance of the original class
|
||||||
|
Object unproxiedValue = ((HibernateProxy) value).getHibernateLazyInitializer()
|
||||||
|
.getImplementation();
|
||||||
|
// Serialize the value
|
||||||
|
delegate.write(out, unproxiedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import org.hibernate.Session;
|
|||||||
import org.hibernate.criterion.Order;
|
import org.hibernate.criterion.Order;
|
||||||
import org.hibernate.criterion.Projections;
|
import org.hibernate.criterion.Projections;
|
||||||
import org.hibernate.criterion.Restrictions;
|
import org.hibernate.criterion.Restrictions;
|
||||||
|
import org.hibernate.envers.AuditReader;
|
||||||
|
import org.hibernate.envers.query.AuditEntity;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -61,8 +63,10 @@ public class TableTicket extends SQLCore {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static List<Ticket> unsolvedByBlock(int b) {
|
public static List<Ticket> unsolvedByBlock(int b) {
|
||||||
|
if (b == 0) return unsolved();
|
||||||
try (Session s = SQLCore.sf.openSession()) {
|
try (Session s = SQLCore.sf.openSession()) {
|
||||||
return s.createCriteria(Ticket.class)
|
return s.createCriteria(Ticket.class)
|
||||||
|
.addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME))
|
||||||
.add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED))
|
.add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED))
|
||||||
.createCriteria(Ticket.PROPERTY_USER)
|
.createCriteria(Ticket.PROPERTY_USER)
|
||||||
.add(Restrictions.between(User.PROPERTY_BLOCK, b * 10, (b + 1) * 10 - 1))
|
.add(Restrictions.between(User.PROPERTY_BLOCK, b * 10, (b + 1) * 10 - 1))
|
||||||
@@ -70,4 +74,29 @@ public class TableTicket extends SQLCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static List<Ticket> unsolved() {
|
||||||
|
try (Session s = SQLCore.sf.openSession()) {
|
||||||
|
return s.createCriteria(Ticket.class)
|
||||||
|
.createAlias(Ticket.PROPERTY_USER, "u")
|
||||||
|
.addOrder(Order.asc("u." + User.PROPERTY_BLOCK))
|
||||||
|
.addOrder(Order.desc(Ticket.PROPERTY_SUBMIT_TIME))
|
||||||
|
.add(Restrictions.ne(Ticket.PROPERTY_STATUS, Status.SOLVED))
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static List<Object[]> track(int tid) {
|
||||||
|
try (Session s = SQLCore.sf.openSession()) {
|
||||||
|
AuditReader reader = getAuditReader(s);
|
||||||
|
return reader.createQuery()
|
||||||
|
.forRevisionsOfEntity(Ticket.class, false, true)
|
||||||
|
.addOrder(AuditEntity.revisionNumber().desc())
|
||||||
|
.add(AuditEntity.id().eq(tid))
|
||||||
|
.getResultList()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
package love.sola.netsupport.sql;
|
package love.sola.netsupport.sql;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import love.sola.netsupport.config.Settings;
|
||||||
import love.sola.netsupport.pojo.User;
|
import love.sola.netsupport.pojo.User;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.criterion.Restrictions;
|
import org.hibernate.criterion.Restrictions;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ***********************************************
|
* ***********************************************
|
||||||
* Created by Sola on 2015/11/10.
|
* Created by Sola on 2015/11/10.
|
||||||
@@ -28,26 +35,64 @@ public class TableUser extends SQLCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static User getByWechat(String wechat) {
|
|
||||||
try (Session s = sf.openSession()) {
|
|
||||||
return (User) s.createCriteria(User.class).add(Restrictions.eq(User.PROPERTY_WECHAT, wechat)).uniqueResult();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static User getByName(String name) {
|
public static User getByName(String name) {
|
||||||
try (Session s = sf.openSession()) {
|
try (Session s = sf.openSession()) {
|
||||||
return (User) s.createCriteria(User.class).add(Restrictions.eq(User.PROPERTY_NAME, name)).uniqueResult();
|
return (User) s.createCriteria(User.class).add(Restrictions.eq(User.PROPERTY_NAME, name)).uniqueResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static User getByWechat(String wechat) {
|
||||||
|
try {
|
||||||
|
User u = cache.get(wechat);
|
||||||
|
return u == NULL_USER ? null : u;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static int update(User user) {
|
public static int update(User user) {
|
||||||
try (Session s = sf.openSession()) {
|
try (Session s = sf.openSession()) {
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
s.update(user);
|
s.update(user);
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
|
cache.put(user.getWechatId(), user);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static void init() {
|
||||||
|
try (Session s = SQLCore.sf.openSession()) {
|
||||||
|
User.OFFICIAL_CHINA_UNICOM_XH = s.get(User.class, 100104L);
|
||||||
|
User.OFFICIAL_CHINA_MOBILE_XH = s.get(User.class, 100864L);
|
||||||
|
User.OFFICIAL_CHINA_MOBILE_FX = s.get(User.class, 100865L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LoadingCache<String, User> cache = CacheBuilder.newBuilder()
|
||||||
|
.concurrencyLevel(4)
|
||||||
|
.maximumSize(4096)
|
||||||
|
.expireAfterWrite(Settings.I.User_Wechat_Cache_Expire_Time, TimeUnit.SECONDS)
|
||||||
|
.build(new ValueLoader());
|
||||||
|
|
||||||
|
private static class ValueLoader extends CacheLoader<String, User> {
|
||||||
|
@Override
|
||||||
|
public User load(String key) throws Exception {
|
||||||
|
User u = TableUser.getByWechat0(key);
|
||||||
|
return u == null ? NULL_USER : u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final User NULL_USER = new User();
|
||||||
|
|
||||||
|
public static void flushCache() {
|
||||||
|
cache.invalidateAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static User getByWechat0(String wechat) {
|
||||||
|
try (Session s = sf.openSession()) {
|
||||||
|
return (User) s.createCriteria(User.class).add(Restrictions.eq(User.PROPERTY_WECHAT, wechat)).uniqueResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package love.sola.netsupport.wechat;
|
package love.sola.netsupport.wechat;
|
||||||
|
|
||||||
import love.sola.netsupport.wechat.handler.*;
|
import love.sola.netsupport.wechat.handler.*;
|
||||||
|
import love.sola.netsupport.wechat.handler.admin.LoginHandler;
|
||||||
|
import love.sola.netsupport.wechat.handler.admin.OperatorInfoHandler;
|
||||||
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -22,6 +24,7 @@ public enum Command {
|
|||||||
CANCEL(3, CancelHandler.class),
|
CANCEL(3, CancelHandler.class),
|
||||||
PROFILE(4, ProfileHandler.class),
|
PROFILE(4, ProfileHandler.class),
|
||||||
LOGIN(10, LoginHandler.class),
|
LOGIN(10, LoginHandler.class),
|
||||||
|
OPERATOR_INFO(11, OperatorInfoHandler.class),
|
||||||
;
|
;
|
||||||
|
|
||||||
private static final Map<Integer, Command> ID_MAP = new HashMap<>();
|
private static final Map<Integer, Command> ID_MAP = new HashMap<>();
|
||||||
@@ -34,13 +37,11 @@ public enum Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String name;
|
|
||||||
public final String regex;
|
public final String regex;
|
||||||
public final Class<? extends WxMpMessageHandler> handler;
|
public final Class<? extends WxMpMessageHandler> handler;
|
||||||
public final int id;
|
public final int id;
|
||||||
|
|
||||||
Command(int id, Class<? extends WxMpMessageHandler> handler) {
|
Command(int id, Class<? extends WxMpMessageHandler> handler) {
|
||||||
this.name = lang("CMD_" + name());
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.regex = lang("REGEX_" + name());
|
this.regex = lang("REGEX_" + name());
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
@@ -52,7 +53,7 @@ public enum Command {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package love.sola.netsupport.wechat;
|
package love.sola.netsupport.wechat;
|
||||||
|
|
||||||
import love.sola.netsupport.config.Settings;
|
import love.sola.netsupport.config.Settings;
|
||||||
import me.chanjar.weixin.common.session.InternalSession;
|
import me.chanjar.weixin.common.session.*;
|
||||||
import me.chanjar.weixin.common.session.StandardSessionManager;
|
|
||||||
import me.chanjar.weixin.common.session.WxSession;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -23,11 +21,15 @@ public class WechatSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static WxSession get(String id, boolean create) {
|
public static WxSession get(String id, boolean create) {
|
||||||
return manager.getSession(id, create);
|
WxSession session = manager.getSession(id, create);
|
||||||
|
if (session != null) {
|
||||||
|
((StandardSessionFacade) session).getInternalSession().endAccess();
|
||||||
|
}
|
||||||
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WxSession get(String id) {
|
public static WxSession get(String id) {
|
||||||
return manager.getSession(id);
|
return get(id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String genId() {
|
public static String genId() {
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package love.sola.netsupport.wechat;
|
|||||||
|
|
||||||
import love.sola.netsupport.config.Settings;
|
import love.sola.netsupport.config.Settings;
|
||||||
import love.sola.netsupport.wechat.handler.RegisterHandler;
|
import love.sola.netsupport.wechat.handler.RegisterHandler;
|
||||||
|
import love.sola.netsupport.wechat.handler.SubscribeHandler;
|
||||||
import love.sola.netsupport.wechat.matcher.CheckSpamMatcher;
|
import love.sola.netsupport.wechat.matcher.CheckSpamMatcher;
|
||||||
import love.sola.netsupport.wechat.matcher.RegisterMatcher;
|
import love.sola.netsupport.wechat.matcher.RegisterMatcher;
|
||||||
|
import me.chanjar.weixin.common.api.WxConsts;
|
||||||
import me.chanjar.weixin.common.util.StringUtils;
|
import me.chanjar.weixin.common.util.StringUtils;
|
||||||
import me.chanjar.weixin.mp.api.*;
|
import me.chanjar.weixin.mp.api.*;
|
||||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||||
@@ -24,12 +26,12 @@ import static love.sola.netsupport.config.Lang.lang;
|
|||||||
* Don't modify this source without my agreement
|
* Don't modify this source without my agreement
|
||||||
* ***********************************************
|
* ***********************************************
|
||||||
*/
|
*/
|
||||||
@WebServlet(name = "WxMpServlet", urlPatterns = "/wechattest", loadOnStartup = 99)
|
@WebServlet(name = "WxMpServlet", urlPatterns = "/wechat", loadOnStartup = 99)
|
||||||
public class WxMpServlet extends HttpServlet {
|
public class WxMpServlet extends HttpServlet {
|
||||||
|
|
||||||
public static WxMpServlet instance;
|
public static WxMpServlet instance;
|
||||||
protected WxMpInMemoryConfigStorage config;
|
protected WxMpInMemoryConfigStorage config;
|
||||||
protected WxMpService wxMpService;
|
public WxMpService wxMpService;
|
||||||
protected WxMpMessageRouter wxMpMessageRouter;
|
protected WxMpMessageRouter wxMpMessageRouter;
|
||||||
protected CheckSpamMatcher checkSpamMatcher;
|
protected CheckSpamMatcher checkSpamMatcher;
|
||||||
|
|
||||||
@@ -45,7 +47,7 @@ public class WxMpServlet extends HttpServlet {
|
|||||||
config.setAppId(Settings.I.Wechat_AppId);
|
config.setAppId(Settings.I.Wechat_AppId);
|
||||||
config.setSecret(Settings.I.Wechat_Secret);
|
config.setSecret(Settings.I.Wechat_Secret);
|
||||||
config.setToken(Settings.I.Wechat_Token);
|
config.setToken(Settings.I.Wechat_Token);
|
||||||
config.setAesKey(Settings.I.Wechat_Token);
|
config.setAesKey(Settings.I.Wechat_AesKey);
|
||||||
|
|
||||||
wxMpService = new WxMpServiceImpl();
|
wxMpService = new WxMpServiceImpl();
|
||||||
wxMpService.setWxMpConfigStorage(config);
|
wxMpService.setWxMpConfigStorage(config);
|
||||||
@@ -54,17 +56,12 @@ public class WxMpServlet extends HttpServlet {
|
|||||||
wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
|
wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
|
||||||
wxMpMessageRouter.rule()
|
wxMpMessageRouter.rule()
|
||||||
.async(false)
|
.async(false)
|
||||||
.msgType("event")
|
.msgType(WxConsts.XML_MSG_EVENT)
|
||||||
.event("subscribe")
|
.event(WxConsts.EVT_SUBSCRIBE)
|
||||||
.handler((wxMessage, context, wxMpService1, sessionManager)
|
.handler(new SubscribeHandler())
|
||||||
-> WxMpXmlOutMessage.TEXT()
|
|
||||||
.fromUser(wxMessage.getToUserName())
|
|
||||||
.toUser(wxMessage.getFromUserName())
|
|
||||||
.content(lang("Event_Subscribe")).build())
|
|
||||||
.end();
|
.end();
|
||||||
wxMpMessageRouter.rule()
|
wxMpMessageRouter.rule()
|
||||||
.async(false)
|
.async(false)
|
||||||
.msgType("text")
|
|
||||||
.matcher(new CheckSpamMatcher())
|
.matcher(new CheckSpamMatcher())
|
||||||
.handler((wxMessage, context, wxMpService1, sessionManager)
|
.handler((wxMessage, context, wxMpService1, sessionManager)
|
||||||
-> WxMpXmlOutMessage.TEXT()
|
-> WxMpXmlOutMessage.TEXT()
|
||||||
@@ -74,7 +71,6 @@ public class WxMpServlet extends HttpServlet {
|
|||||||
.end();
|
.end();
|
||||||
wxMpMessageRouter.rule()
|
wxMpMessageRouter.rule()
|
||||||
.async(false)
|
.async(false)
|
||||||
.msgType("text")
|
|
||||||
.matcher(new RegisterMatcher())
|
.matcher(new RegisterMatcher())
|
||||||
.handler(new RegisterHandler())
|
.handler(new RegisterHandler())
|
||||||
.end();
|
.end();
|
||||||
@@ -88,7 +84,8 @@ public class WxMpServlet extends HttpServlet {
|
|||||||
public static void registerCommands(WxMpMessageRouter router) throws IllegalAccessException, InstantiationException {
|
public static void registerCommands(WxMpMessageRouter router) throws IllegalAccessException, InstantiationException {
|
||||||
for (Command c : Command.values()) {
|
for (Command c : Command.values()) {
|
||||||
WxMpMessageHandler handler = c.handler.newInstance();
|
WxMpMessageHandler handler = c.handler.newInstance();
|
||||||
router.rule().async(false).msgType("text").rContent(c.regex).handler(handler).end();
|
router.rule().async(false).msgType(WxConsts.XML_MSG_TEXT).rContent(c.regex).handler(handler).end();
|
||||||
|
router.rule().async(false).msgType(WxConsts.XML_MSG_EVENT).event(WxConsts.EVT_CLICK).eventKey(c.name()).handler(handler).end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,19 +115,19 @@ public class WxMpServlet extends HttpServlet {
|
|||||||
|
|
||||||
String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) ? "raw" : request.getParameter("encrypt_type");
|
String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) ? "raw" : request.getParameter("encrypt_type");
|
||||||
|
|
||||||
if ("raw".equals(encryptType)) {
|
// if ("raw".equals(encryptType)) {
|
||||||
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream());
|
// WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream());
|
||||||
WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
|
// WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
|
||||||
if (outMessage == null) {
|
// if (outMessage == null) {
|
||||||
outMessage = WxMpXmlOutMessage.TEXT()
|
// outMessage = WxMpXmlOutMessage.TEXT()
|
||||||
.fromUser(inMessage.getToUserName())
|
// .fromUser(inMessage.getToUserName())
|
||||||
.toUser(inMessage.getFromUserName())
|
// .toUser(inMessage.getFromUserName())
|
||||||
.content(lang("Invalid_Operation"))
|
// .content(lang("Invalid_Operation"))
|
||||||
.build();
|
// .build();
|
||||||
}
|
// }
|
||||||
response.getWriter().write(outMessage.toXml());
|
// response.getWriter().write(outMessage.toXml());
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if ("aes".equals(encryptType)) {
|
if ("aes".equals(encryptType)) {
|
||||||
String msgSignature = request.getParameter("msg_signature");
|
String msgSignature = request.getParameter("msg_signature");
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package love.sola.netsupport.wechat.handler;
|
||||||
|
|
||||||
|
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||||
|
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
|
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||||
|
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/29.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
public class AutoReplyHandler implements WxMpMessageHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
|
||||||
|
//TODO auto reply
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ public class ProfileHandler implements WxMpMessageHandler {
|
|||||||
session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName());
|
session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName());
|
||||||
session.setAttribute(Attribute.USER, u);
|
session.setAttribute(Attribute.USER, u);
|
||||||
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
|
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
|
||||||
out.content(format("User_Profile_Link", id, u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone()));
|
out.content(format("Profile_Modify", format("User_Profile_Link", id, u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone())));
|
||||||
return out.build();
|
return out.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import me.chanjar.weixin.mp.bean.outxmlbuilder.TextBuilder;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static love.sola.netsupport.config.Lang.format;
|
import static love.sola.netsupport.config.Lang.format;
|
||||||
import static love.sola.netsupport.config.Lang.lang;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ***********************************************
|
* ***********************************************
|
||||||
@@ -33,14 +32,17 @@ public class RegisterHandler implements WxMpMessageHandler {
|
|||||||
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
|
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
|
||||||
String fromUser = wxMessage.getFromUserName();
|
String fromUser = wxMessage.getFromUserName();
|
||||||
User u = TableUser.getByWechat(fromUser);
|
User u = TableUser.getByWechat(fromUser);
|
||||||
|
String id = WechatSession.genId();
|
||||||
|
WxSession session = WechatSession.get(id, true);
|
||||||
if (u != null) {
|
if (u != null) {
|
||||||
out.content(lang("Already_Registered"));
|
session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE);
|
||||||
|
session.setAttribute(Attribute.WECHAT, fromUser);
|
||||||
|
session.setAttribute(Attribute.USER, u);
|
||||||
|
out.content(format("Already_Registered", format("User_Profile_Link", id, u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone())));
|
||||||
} else {
|
} else {
|
||||||
String id = WechatSession.genId();
|
|
||||||
WxSession session = WechatSession.get(id, true);
|
|
||||||
session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER);
|
session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER);
|
||||||
session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName());
|
session.setAttribute(Attribute.WECHAT, fromUser);
|
||||||
out.content(format("User_Register_Link", id));
|
out.content(format("User_Register", format("User_Register_Link", id)));
|
||||||
}
|
}
|
||||||
return out.build();
|
return out.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class SubmitHandler implements WxMpMessageHandler {
|
|||||||
}
|
}
|
||||||
String id = WechatSession.genId();
|
String id = WechatSession.genId();
|
||||||
WxSession session = WechatSession.get(id, true);
|
WxSession session = WechatSession.get(id, true);
|
||||||
session.setAttribute(Attribute.AUTHORIZED, Command.QUERY);
|
session.setAttribute(Attribute.AUTHORIZED, Command.SUBMIT);
|
||||||
session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName());
|
session.setAttribute(Attribute.WECHAT, wxMessage.getFromUserName());
|
||||||
session.setAttribute(Attribute.USER, u);
|
session.setAttribute(Attribute.USER, u);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package love.sola.netsupport.wechat.handler;
|
||||||
|
|
||||||
|
import love.sola.netsupport.api.user.Register;
|
||||||
|
import love.sola.netsupport.enums.Attribute;
|
||||||
|
import love.sola.netsupport.pojo.User;
|
||||||
|
import love.sola.netsupport.sql.TableUser;
|
||||||
|
import love.sola.netsupport.wechat.Command;
|
||||||
|
import love.sola.netsupport.wechat.WechatSession;
|
||||||
|
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||||
|
import me.chanjar.weixin.common.session.WxSession;
|
||||||
|
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
|
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||||
|
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||||
|
import me.chanjar.weixin.mp.bean.outxmlbuilder.TextBuilder;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static love.sola.netsupport.config.Lang.format;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/25.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
public class SubscribeHandler implements WxMpMessageHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
|
||||||
|
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
|
||||||
|
String fromUser = wxMessage.getFromUserName();
|
||||||
|
User u = TableUser.getByWechat(fromUser);
|
||||||
|
String id = WechatSession.genId();
|
||||||
|
WxSession session = WechatSession.get(id, true);
|
||||||
|
if (u != null) {
|
||||||
|
session.setAttribute(Attribute.AUTHORIZED, Command.PROFILE);
|
||||||
|
session.setAttribute(Attribute.WECHAT, fromUser);
|
||||||
|
session.setAttribute(Attribute.USER, u);
|
||||||
|
out.content(format("Event_Subscribe", format("Already_Registered", format("User_Profile_Link", id, u.getName(), u.getIsp().id, u.getNetAccount(), u.getBlock(), u.getRoom(), u.getPhone()))));
|
||||||
|
Register.converterWithRetry(u);
|
||||||
|
} else {
|
||||||
|
session.setAttribute(Attribute.AUTHORIZED, Command.REGISTER);
|
||||||
|
session.setAttribute(Attribute.WECHAT, fromUser);
|
||||||
|
out.content(format("Event_Subscribe", format("User_Register", format("User_Register_Link", id))));
|
||||||
|
}
|
||||||
|
return out.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package love.sola.netsupport.wechat.handler;
|
package love.sola.netsupport.wechat.handler.admin;
|
||||||
|
|
||||||
import love.sola.netsupport.enums.Access;
|
import love.sola.netsupport.enums.Access;
|
||||||
import love.sola.netsupport.enums.Attribute;
|
import love.sola.netsupport.enums.Attribute;
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package love.sola.netsupport.wechat.handler.admin;
|
||||||
|
|
||||||
|
import love.sola.netsupport.enums.Access;
|
||||||
|
import love.sola.netsupport.pojo.Operator;
|
||||||
|
import love.sola.netsupport.sql.TableOperator;
|
||||||
|
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||||
|
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
|
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||||
|
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||||
|
import me.chanjar.weixin.mp.bean.outxmlbuilder.TextBuilder;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static love.sola.netsupport.config.Lang.format;
|
||||||
|
import static love.sola.netsupport.config.Lang.lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/28.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
public class OperatorInfoHandler implements WxMpMessageHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
|
||||||
|
TextBuilder out = WxMpXmlOutMessage.TEXT().fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName());
|
||||||
|
try {
|
||||||
|
Operator op = TableOperator.get(wxMessage.getFromUserName());
|
||||||
|
if (op == null)
|
||||||
|
out.content(lang("Not_Operator"));
|
||||||
|
else if (op.getAccess() == Access.NOLOGIN) {
|
||||||
|
out.content(lang("No_Login"));
|
||||||
|
} else {
|
||||||
|
out.content(format("Operator_Info", op.getId(), op.getName(), op.getAccess(), op.getBlock(), op.getWeek()));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
out.content(lang("Login_Error"));
|
||||||
|
}
|
||||||
|
return out.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package love.sola.netsupport.wechat.handler.admin;
|
||||||
|
|
||||||
|
import love.sola.netsupport.sql.SQLCore;
|
||||||
|
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||||
|
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
|
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||||
|
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||||
|
import me.chanjar.weixin.mp.bean.outxmlbuilder.TextBuilder;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ***********************************************
|
||||||
|
* Created by Sola on 2015/12/26.
|
||||||
|
* Don't modify this source without my agreement
|
||||||
|
* ***********************************************
|
||||||
|
*/
|
||||||
|
public class SignHandler implements WxMpMessageHandler {
|
||||||
|
|
||||||
|
public static Pattern pat = Pattern.compile("(?i)^Auth (\\d{4})");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
|
||||||
|
String msg = wxMessage.getContent();
|
||||||
|
TextBuilder out = WxMpXmlOutMessage.TEXT().toUser(wxMessage.getFromUserName()).fromUser(wxMessage.getToUserName());
|
||||||
|
Matcher mat = pat.matcher(msg);
|
||||||
|
|
||||||
|
root:
|
||||||
|
if (mat.find()) {
|
||||||
|
int id = Integer.parseInt(mat.group(1));
|
||||||
|
try (Connection conn = SQLCore.ds.getConnection()) {
|
||||||
|
switch (checkID(conn, id)) {
|
||||||
|
case -1:
|
||||||
|
out.content("无效ID。");
|
||||||
|
break root;
|
||||||
|
case -2:
|
||||||
|
out.content("该ID已登记过。");
|
||||||
|
break root;
|
||||||
|
}
|
||||||
|
if (checkDuplicated(conn, wxMessage.getFromUserName())) {
|
||||||
|
out.content("你的微信已经登记过。");
|
||||||
|
break root;
|
||||||
|
}
|
||||||
|
PreparedStatement ps = conn.prepareStatement("UPDATE auth SET wechat=? WHERE id=?");
|
||||||
|
ps.setString(1, wxMessage.getFromUserName());
|
||||||
|
ps.setInt(2, id);
|
||||||
|
if (ps.executeUpdate() == 1) {
|
||||||
|
out.content("登记成功。");
|
||||||
|
} else {
|
||||||
|
out.content("登记失败,请联系管理员。");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
out.content("系统异常,请联系管理员。");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.content("无效ID。");
|
||||||
|
}
|
||||||
|
return out.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int checkID(Connection conn, int id) throws SQLException {
|
||||||
|
PreparedStatement ps = conn.prepareStatement("SELECT wechat FROM auth WHERE id=?");
|
||||||
|
ps.setInt(1, id);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
return rs.getString("wechat") != null ? -2 : 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkDuplicated(Connection conn, String wechat) throws SQLException {
|
||||||
|
PreparedStatement ps = conn.prepareStatement("SELECT wechat FROM auth WHERE wechat=?");
|
||||||
|
ps.setString(1, wechat);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
return rs.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -26,7 +26,6 @@ public class CheckSpamMatcher implements WxMpMessageMatcher {
|
|||||||
|
|
||||||
private LoadingCache<String, Long> cache = CacheBuilder.newBuilder()
|
private LoadingCache<String, Long> cache = CacheBuilder.newBuilder()
|
||||||
.concurrencyLevel(4)
|
.concurrencyLevel(4)
|
||||||
.weakKeys()
|
|
||||||
.maximumSize(4096)
|
.maximumSize(4096)
|
||||||
.expireAfterWrite(Settings.I.Check_Spam_Cache_Expire_Time, TimeUnit.SECONDS)
|
.expireAfterWrite(Settings.I.Check_Spam_Cache_Expire_Time, TimeUnit.SECONDS)
|
||||||
.build(new ValueLoader());
|
.build(new ValueLoader());
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
package love.sola.netsupport.wechat.matcher;
|
package love.sola.netsupport.wechat.matcher;
|
||||||
|
|
||||||
import love.sola.netsupport.pojo.User;
|
|
||||||
import love.sola.netsupport.sql.TableUser;
|
import love.sola.netsupport.sql.TableUser;
|
||||||
import me.chanjar.weixin.mp.api.WxMpMessageMatcher;
|
import me.chanjar.weixin.mp.api.WxMpMessageMatcher;
|
||||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ***********************************************
|
* ***********************************************
|
||||||
* Created by Sola on 2015/11/26.
|
* Created by Sola on 2015/11/26.
|
||||||
@@ -16,18 +12,9 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class RegisterMatcher implements WxMpMessageMatcher {
|
public class RegisterMatcher implements WxMpMessageMatcher {
|
||||||
|
|
||||||
public static Set<String> registered = new HashSet<>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean match(WxMpXmlMessage message) {
|
public boolean match(WxMpXmlMessage message) {
|
||||||
String fromUser = message.getFromUserName();
|
return TableUser.getByWechat(message.getFromUserName()) == null;
|
||||||
if (registered.contains(fromUser)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
User u = TableUser.getByWechat(fromUser);
|
|
||||||
if (u != null) registered.add(u.getWechatId());
|
|
||||||
return u == null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
0
src/main/resources/cortana.yml
Normal file
0
src/main/resources/cortana.yml
Normal file
@@ -6,46 +6,61 @@ Unknown_Encrypt_Type: 'Unknown encrypt-type.'
|
|||||||
#Command Regex
|
#Command Regex
|
||||||
REGEX_QUERY: '^(?i)(Query)|(查询)|(cx)$'
|
REGEX_QUERY: '^(?i)(Query)|(查询)|(cx)$'
|
||||||
REGEX_REGISTER: '^(?i)(Reg(ister)?)|(注册)|(绑定)|(zc)|(bd)$'
|
REGEX_REGISTER: '^(?i)(Reg(ister)?)|(注册)|(绑定)|(zc)|(bd)$'
|
||||||
REGEX_SUBMIT: '^(?i)(Submit)|(报修)|(bx)$'
|
REGEX_SUBMIT: '^(?i)(Submit)|(报修)|(保修)|(bx)$'
|
||||||
REGEX_CANCEL: '^(?i)(Cancel)|(取消)|(撤销)|(qx)|(cx)$'
|
REGEX_CANCEL: '^(?i)(Cancel)|(取消)|(撤销)|(qx)|(cx)$'
|
||||||
REGEX_LOGIN: '^(?i)Authme$'
|
REGEX_LOGIN: '^(?i)Authme$'
|
||||||
REGEX_PROFILE: '^(?i)(EditProfile)|(修改资料)|(xgzl)$'
|
REGEX_PROFILE: '^(?i)(EditProfile)|(修改资料)|(修改信息)|(xgzl)|(xgxx)$'
|
||||||
|
REGEX_OPERATOR_INFO: '^(?i)(OpInfo)|(网维资料)|(wwzl)$'
|
||||||
|
|
||||||
#Event
|
#Misc
|
||||||
Event_Subscribe: "欢迎使用电子科技大学中山学院网络维护科微信自助报修平台。\n如您在使用中遇到任何问题,请将投诉或建议邮件至loli@sola.love.\n\n请发送'绑定'进行微信绑定"
|
|
||||||
Invalid_Operation: 'Whoops,报修姬找不到你想要的东西啦 (╯‵□′)╯︵┻━┻。'
|
Invalid_Operation: 'Whoops,报修姬找不到你想要的东西啦 (╯‵□′)╯︵┻━┻。'
|
||||||
Message_Spam: '你的打字速度太快了,喝一杯82年的Java压压惊吧。'
|
Message_Spam: '你的打字速度太快了,喝一杯82年的Java压压惊吧。'
|
||||||
|
#Subscribe
|
||||||
|
Event_Subscribe: "欢迎使用电子科技大学中山学院网络维护科微信自助报修平台。\n\n{0}"
|
||||||
#Register
|
#Register
|
||||||
Already_Registered: "您已进行过微信绑定。如果需要更改个人信息,请发送 '修改资料' 。"
|
User_Register: "您尚未进行微信绑定。\n<a href=\"{0}\">>点击这里进行微信绑定操作<</a>"
|
||||||
|
Already_Registered: '您已进行过微信绑定。若是需要更改个人信息,请<a href="{0}"> >点击此处<</a>。'
|
||||||
#Query
|
#Query
|
||||||
Query_Title: '最近一次报修记录:'
|
Query_Title: '最近一次报修记录:'
|
||||||
More_Details: '查询更早的报修信息,请点击 >'
|
More_Details: '>>> 查询更早的报修信息,请点击 <<<'
|
||||||
No_Ticket_Available: '您尚未提交过任何报修。'
|
No_Ticket_Available: '您尚未提交过任何报修。'
|
||||||
#Submit
|
#Submit
|
||||||
Already_Opening_Ticket: "您上次提交的报修单仍在处理中. 若需要查询报修单状态,请发送 '查询' 。"
|
Already_Opening_Ticket: "您上次提交的报修单仍在处理中. 若需要查询报修单状态,请发送 '查询' 。"
|
||||||
Submit_Title: '在网维工作人员上门解决您的问题之前...'
|
Submit_Title: '在网维工作人员上门解决您的问题之前...'
|
||||||
Submit_Desc: "在网维工作人员上门解决您的问题之前,您可以尝试以下方法来更有效地解决您的问题:\n
|
Submit_Desc: |
|
||||||
重新插拔您电脑的网线以及墙上的端口。\n
|
在网维工作人员上门解决您的问题之前,您可以尝试以下方法来更有效地解决您的问题:
|
||||||
尝试卸载掉您的wifi共享软件并重启电脑。\n
|
- 重新插拔您电脑的网线以及墙上的端口。
|
||||||
请您检查一下您的账号是否余额充足。\n
|
- 尝试卸载掉您的wifi共享软件并重启电脑。
|
||||||
若您的电脑出现明显异常,请尝试使用他人的电脑能否正常登录,网维的工作成员主要负责网络的维护工作,可能无法解决您的个人电脑问题。\n
|
- 请您检查一下您的账号是否余额充足。
|
||||||
\n
|
- 若您的电脑出现明显异常,请尝试使用他人的电脑能否正常登录,网维的工作成员主要负责网络的维护工作,可能无法解决您的个人电脑问题。
|
||||||
若以上步骤对您没有帮助,请点此提交报修表单。"
|
|
||||||
|
若以上步骤对您没有帮助,请点此提交报修表单。
|
||||||
#Cancel
|
#Cancel
|
||||||
No_Open_Ticket_Available: '您当前没有未解决的报修表单。'
|
No_Open_Ticket_Available: '您当前没有未解决的报修表单。'
|
||||||
Cancel_Title: '报修已取消:'
|
Cancel_Title: '报修已取消:'
|
||||||
User_Cancel_Remark: '用户手动取消报修。'
|
User_Cancel_Remark: '用户手动取消报修。'
|
||||||
Cancel_Failed: '取消失败。'
|
Cancel_Failed: '取消失败。'
|
||||||
|
#Modify
|
||||||
|
Profile_Modify: '<a href="{0}">> 点此修改资料 <</a>'
|
||||||
#Login
|
#Login
|
||||||
Not_Operator: '嘟嘟嘟……'
|
Not_Operator: '嘟嘟嘟……'
|
||||||
No_Login: 'Permission Denied.'
|
No_Login: 'Permission Denied.'
|
||||||
Internal_Error: '啊哦,登录失败了哦。'
|
Internal_Error: '啊哦,登录失败了哦。'
|
||||||
|
#Operator_Info
|
||||||
|
Operator_Info: |
|
||||||
|
网维成员资料:
|
||||||
|
网维ID: {0,number,#}
|
||||||
|
姓名: {1}
|
||||||
|
岗位: {2,choice,0#'Administrator >ω<'|3#值班组长|6#正式成员|7#实习成员|}
|
||||||
|
值班片区: {3,choice,0#'全图 >ω<'|1#岐头片区|2#北门片区|3#东门片区|4#香灰片区|5#凤翔片区}
|
||||||
|
值班日: {4,choice,0#'2月30日 >ω<'|1#周一|2#周二|3#周三|4#周四|5#周五|6#周六|7#周日}
|
||||||
|
|
||||||
|
若以上信息有误,请及时联系@15-排污-沙子森。
|
||||||
#URL
|
#URL
|
||||||
User_Register_Link: '您尚未进行微信绑定, 请<a href="http://topaz.sinaapp.com/nm/v1/reg.html?token={0}">点击这里</a>进行微信绑定操作。'
|
User_Register_Link: 'http://topaz.sinaapp.com/nm/v1/reg.html?token={0}'
|
||||||
User_Query_Link: 'http://topaz.sinaapp.com/nm/v1/list.html?token={0}'
|
User_Query_Link: 'http://topaz.sinaapp.com/nm/v1/list.html?token={0}'
|
||||||
User_Submit_Link: 'http://topaz.sinaapp.com/nm/v1/rrepair.html?token={0}&name={1}&isp={2}&room={3}&block={4}&phone={5,number,#}'
|
User_Submit_Link: 'http://topaz.sinaapp.com/nm/v1/rrepair.html?token={0}&name={1}&isp={2}&room={3}&block={4}&phone={5,number,#}'
|
||||||
User_Profile_Link: 'http://topaz.sinaapp.com/nm/v1/profile.html?token={0}&name={1}&isp={2}&account={3}&block={4}&room={5}&phone={6,number,#}'
|
User_Profile_Link: 'http://topaz.sinaapp.com/nm/v1/modi.html?token={0}&name={1}&isp={2}&username={3}&block={4}&room={5}&phone={6,number,#}'
|
||||||
Result_Page: 'http://topaz.sinaapp.com/nm/v1/result.html'
|
Result_Page: 'http://topaz.sinaapp.com/nm/v1/result.html'
|
||||||
Operator_Home_Page: '<a href="http://topaz.sinaapp.com/nm/v1/man/home.html?token={0}">CLICK HERE</a>'
|
Operator_Home_Page: '<a href="http://topaz.sinaapp.com/nm/v1/man/home.html?token={0}">CLICK HERE</a>'
|
||||||
Operator_Login_Page: 'http://topaz.sinaapp.com/nm/v1/man/login.html?pkey={0}'
|
Operator_Login_Page: 'http://topaz.sinaapp.com/nm/v1/man/login.html?pkey={0}'
|
||||||
@@ -56,7 +71,7 @@ STATUS_UNCHECKED: '待处理'
|
|||||||
STATUS_SOLVED: '已解决'
|
STATUS_SOLVED: '已解决'
|
||||||
#Ticket
|
#Ticket
|
||||||
Ticket_Info_Id: '报修单号: '
|
Ticket_Info_Id: '报修单号: '
|
||||||
Ticket_Info_Desc: '报修描述: '
|
Ticket_Info_Desc: ''
|
||||||
Ticket_Info_Submit_Time: '提交时间: '
|
Ticket_Info_Submit_Time: '提交时间: '
|
||||||
Ticket_Info_Operator: '操作员: '
|
Ticket_Info_Operator: '操作员: '
|
||||||
Ticket_Info_Remark: '维修描述: '
|
Ticket_Info_Remark: '维修描述: '
|
||||||
|
|||||||
47
src/main/resources/menu-op.json
Normal file
47
src/main/resources/menu-op.json
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"button": [
|
||||||
|
{
|
||||||
|
"name": "我要",
|
||||||
|
"sub_button": [
|
||||||
|
{
|
||||||
|
"type": "click",
|
||||||
|
"name": "提交报修",
|
||||||
|
"key": "SUBMIT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "click",
|
||||||
|
"name": "查询报修",
|
||||||
|
"key": "QUERY"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "click",
|
||||||
|
"name": "撤销报修",
|
||||||
|
"key": "CANCEL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "click",
|
||||||
|
"name": "修改资料",
|
||||||
|
"key": "PROFILE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "OP",
|
||||||
|
"sub_button": [
|
||||||
|
{
|
||||||
|
"type": "click",
|
||||||
|
"name": "网维资料",
|
||||||
|
"key": "OPERATOR_INFO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "click",
|
||||||
|
"name": "后台登录",
|
||||||
|
"key": "LOGIN"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"matchrule": {
|
||||||
|
"group_id": "100",
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/main/resources/menu.json
Normal file
29
src/main/resources/menu.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"button": [
|
||||||
|
{
|
||||||
|
"name": "我要",
|
||||||
|
"sub_button": [
|
||||||
|
{
|
||||||
|
"type": "click",
|
||||||
|
"name": "提交报修",
|
||||||
|
"key": "SUBMIT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "click",
|
||||||
|
"name": "查询报修",
|
||||||
|
"key": "QUERY"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "click",
|
||||||
|
"name": "撤销报修",
|
||||||
|
"key": "CANCEL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "click",
|
||||||
|
"name": "修改资料",
|
||||||
|
"key": "PROFILE"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
package love.sola.netsupport.wechat;
|
package love.sola.netsupport.wechat;
|
||||||
|
|
||||||
import love.sola.netsupport.util.RSAUtil;
|
import love.sola.netsupport.util.RSAUtil;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mindrot.jbcrypt.BCrypt;
|
import org.mindrot.jbcrypt.BCrypt;
|
||||||
|
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ***********************************************
|
* ***********************************************
|
||||||
* Created by Sola on 2015/12/6.
|
* Created by Sola on 2015/12/6.
|
||||||
@@ -24,4 +30,16 @@ public class TestEncrypt {
|
|||||||
assert "Encrypt".equals(RSAUtil.decrypt(RSAUtil.encrypt("Encrypt")));
|
assert "Encrypt".equals(RSAUtil.decrypt(RSAUtil.encrypt("Encrypt")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
public void testRSASpecKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
|
System.out.println("RSAUtil.privateKey_s = " + RSAUtil.privateKey_s);
|
||||||
|
System.out.println("RSAUtil.publicKey_s = " + RSAUtil.publicKey_s);
|
||||||
|
// String pkey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCA0qyARvHSCIUQ6YM6K+e/QgiZ+dc/MpVz5DIFwQab5iiifruQiaoA74ilHOOiq5i0ToR1VxNhCUZcAy2saHNifoYKTauMOUSV6IoP4X5jp691PlI9yxNx328mSlPNM9+7BgOzrUP1pR71d+T4LDn0o4J6Ad82vVIe7yWszzF4qQIDAQAB";
|
||||||
|
String pkey = RSAUtil.publicKey_s;
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(pkey));
|
||||||
|
RSAUtil.publicKey = keyFactory.generatePublic(keySpec);
|
||||||
|
System.out.println("RSAUtil.encrypt(\"233\") = " + RSAUtil.encrypt("233"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,4 +40,9 @@ public class TestMessageFormat {
|
|||||||
assert "15838838438".equals(MessageFormat.format("{0,number,#}", 15838838438L));
|
assert "15838838438".equals(MessageFormat.format("{0,number,#}", 15838838438L));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOpInfo() {
|
||||||
|
assert !Lang.format("Operator_Info", 1541, "Sola", 0, 0, 4).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user