refactor: extract duplicated code into shared utility classes by devin-ai-integration[bot] · Pull Request #2 · oneky/NewBingGoGo-MagicURL-java · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 15 additions & 159 deletions src/main/java/cn/jja8/newbinggogo/NewBingGoGoServer.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package cn.jja8.newbinggogo;

import cn.jja8.newbinggogo.util.HttpProxyUtils;
import cn.jja8.newbinggogo.util.ResponseBuilder;
import fi.iki.elonen.NanoHTTPD;
import fi.iki.elonen.NanoWSD;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

Expand All @@ -36,54 +32,46 @@ public NewBingGoGoServer(int port) {
@Override
public Response serveHttp(IHTTPSession session) {
if(!isUser(session)){
return getReturnError("请求头无user-agent参数,拒绝请求!");
return ResponseBuilder.httpError("请求头无user-agent参数,拒绝请求!");
}
String ip = new Date()+":"+getIp(session);
String url = session.getUri();
if(url.equals("/turing/conversation/create")){//创建聊天
System.out.println(ip+":请求创建聊天");
return goUrl(session,"https://www.bing.com/turing/conversation/create");
return HttpProxyUtils.proxyGet(session,"https://www.bing.com/turing/conversation/create");
}
if(url.equals("/msrewards/api/v1/enroll")){//加入候补
System.out.println(ip+":请求加入候补");
return goUrl(session,"https://www.bing.com/msrewards/api/v1/enroll?"+session.getQueryParameterString());
return HttpProxyUtils.proxyGet(session,"https://www.bing.com/msrewards/api/v1/enroll?"+session.getQueryParameterString());
}
if(url.equals("/images/create")){
System.out.println(ip+":请求AI画图");
HashMap<String,String> he = new HashMap<>();
he.put("sec-fetch-site","same-origin");
he.put("referer","https://www.bing.com/search?q=bingAI");
Response re = goUrl(session,"https://www.bing.com/images/create?"+session.getQueryParameterString(),he);
re.setMimeType("text/html");
return re;
return HttpProxyUtils.proxyImageRequest(session,
"https://www.bing.com/images/create?"+session.getQueryParameterString(),
"https://www.bing.com/search?q=bingAI");
}
if(url.startsWith("/images/create/async/results")){
System.out.println(ip+":请求AI画图图片");
String gogoUrl = url.replace("/images/create/async/results","https://www.bing.com/images/create/async/results");
gogoUrl = gogoUrl+"?"+session.getQueryParameterString();
// /641f0e9c318346378e94e495ab61a703?q=a+dog&partner=sydney&showselective=1
HashMap<String,String> he = new HashMap<>();
he.put("sec-fetch-site","same-origin");
he.put("referer","https://www.bing.com/images/create?partner=sydney&showselective=1&sude=1&kseed=7000");
Response re = goUrl(session, gogoUrl,he);
re.setMimeType("text/html");
return re;
return HttpProxyUtils.proxyImageRequest(session, gogoUrl,
"https://www.bing.com/images/create?partner=sydney&showselective=1&sude=1&kseed=7000");
}
return getReturnError("由于NewBing策略更新,请更新NewBingGoGo到2023.4.3版本以上。");
return ResponseBuilder.httpError("由于NewBing策略更新,请更新NewBingGoGo到2023.4.3版本以上。");
}

@Override
protected WebSocket openWebSocket(IHTTPSession handshake) {
if(!isUser(handshake)){
return getReturnErrorWebSocket(handshake,"请求头无user-agent参数,拒绝请求!");
return createErrorWebSocket(handshake,"请求头无user-agent参数,拒绝请求!");
}
String ip = new Date()+":"+getIp(handshake);
String url = handshake.getUri();
if(url.equals("/sydney/ChatHub")){
System.out.println(ip+":创建魔法聊天连接");
return new NewBingGoGoServerWebSocket(handshake,scheduledExecutorService);
}
return getReturnErrorWebSocket(handshake,"请求接口错误!");
return createErrorWebSocket(handshake,"请求接口错误!");
}

public static boolean isUser(IHTTPSession session){
Expand All @@ -100,102 +88,11 @@ public static String getIp(IHTTPSession session){
return ip;
}

/*
* 转发请求
*/
public static NanoHTTPD.Response goUrl(NanoHTTPD.IHTTPSession session,String stringUrl){
return goUrl(session,stringUrl,new HashMap<>(1));
}


public static NanoHTTPD.Response goUrl(NanoHTTPD.IHTTPSession session,String stringUrl,Map<String,String> addHeaders){
URL url;
try {
url = new URL(stringUrl);
} catch (MalformedURLException e) {
return getReturnError(e);
}

HttpURLConnection urlConnection;
try{
urlConnection = (HttpURLConnection) url.openConnection();
} catch (IOException e) {
return getReturnError(e);
}
try {
urlConnection.setRequestMethod("GET");
} catch (ProtocolException e) {
return getReturnError(e);
}
urlConnection.setDoOutput(false);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(true);
urlConnection.setInstanceFollowRedirects(true);
urlConnection.setConnectTimeout(3000);

//拷贝头信息
Map<String,String> header = session.getHeaders();
String[] b = {"cookie","user-agent","accept","accept-language"};
for (String s : b) {
String v = header.get(s);
urlConnection.addRequestProperty(s,v);
}
//添加指定的头部信息
addHeaders.forEach(urlConnection::addRequestProperty);

//建立链接
try {
urlConnection.connect();
} catch (IOException e) {
return getReturnError(e);
}
int code;
try{
code = urlConnection.getResponseCode();
} catch (IOException e) {
return getReturnError(e);
}
//获取请求状态代码
if(code!=200){
urlConnection.disconnect();
return getReturnError("此魔法链接服务器请求被bing拒绝!请稍后再试。错误代码:"+code,null,false);
}

//将数据全部读取然后关闭流和链接
int len = urlConnection.getContentLength();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(Math.max(len, 0));
try(InputStream inputStream = urlConnection.getInputStream()){
for (int i = 0; i < len; i++) {
byteArrayOutputStream.write(inputStream.read());
}
}catch (FileNotFoundException e){
urlConnection.disconnect();
return getReturnError("此魔法链接服务器无法正常工作,请求被bing拒绝!",e,false);
}catch (IOException e) {
urlConnection.disconnect();
return getReturnError(e);
}
urlConnection.disconnect();

//创建用于输出的流
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
return NanoHTTPD.newFixedLengthResponse(
Response.Status.OK,
"application/json",
byteArrayInputStream,
len
);
}

public static WebSocket getReturnErrorWebSocket(IHTTPSession session,String error){
public static WebSocket createErrorWebSocket(IHTTPSession session, String error){
return new WebSocket(session) {
@Override
protected void onOpen(){
String errorMessage = "{\"type\": 2,\"result\":{\"value\":\"Error\",\"message\":\""+escapeJsonString(error)+"\"}}";
try{
this.send(errorMessage);
this.close(NanoWSD.WebSocketFrame.CloseCode.NormalClosure,"error",false);
} catch (IOException ignored) {}
ResponseBuilder.sendWebSocketErrorAndClose(this, error);
}
@Override
protected void onClose(WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) {}
Expand All @@ -208,45 +105,4 @@ protected void onException(IOException exception) {}
};
}

/**
* 获取返回的错误
* */
public static NanoHTTPD.Response getReturnError(Throwable error){
return getReturnError("服务器内部发生未知错误!",error,true);
}
public static NanoHTTPD.Response getReturnError(String error){
return getReturnError(error,null,true);
}
/**
* @param all 是否全部打印
* */
public static NanoHTTPD.Response getReturnError(String message,Throwable error,boolean all){
String r;
if (error==null){
r = "{\"result\":{\"value\":\"error\",\"message\":\""+escapeJsonString(message)+"\"}}";
}else if(all){
r = "{\"result\":{\"value\":\"error\",\"message\":\""+escapeJsonString(message+"详情:"+printErrorToString(error))+"\"}}";
}else {
r = "{\"result\":{\"value\":\"error\",\"message\":\""+escapeJsonString(message+"详情:"+error)+"\"}}";
}
return NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Response.Status.OK,"application/json",r);
}

/**
* 转义成json字符串
* */
public static String escapeJsonString(String input) {
return input
.replace("\\","\\\\")
.replace("\n","\\n")
.replace("\r","\\r")
.replace("\t","\\t")
.replace("\"","\\\"");
}
public static String printErrorToString(Throwable t) {
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw, true));
return sw.getBuffer().toString();
}

}
112 changes: 112 additions & 0 deletions src/main/java/cn/jja8/newbinggogo/util/HttpProxyUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package cn.jja8.newbinggogo.util;

import fi.iki.elonen.NanoHTTPD;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public class HttpProxyUtils {

private static final String[] FORWARDED_HEADERS = {"cookie", "user-agent", "accept", "accept-language"};

private HttpProxyUtils() {}

/**
* Proxy a GET request to the target URL, forwarding selected headers.
*/
public static NanoHTTPD.Response proxyGet(NanoHTTPD.IHTTPSession session, String stringUrl) {
return proxyGet(session, stringUrl, new HashMap<>(1));
}

/**
* Proxy a GET request to the target URL with additional headers.
*/
public static NanoHTTPD.Response proxyGet(NanoHTTPD.IHTTPSession session, String stringUrl, Map<String, String> addHeaders) {
URL url;
try {
url = new URL(stringUrl);
} catch (MalformedURLException e) {
return ResponseBuilder.httpError(e);
}

HttpURLConnection urlConnection;
try {
urlConnection = (HttpURLConnection) url.openConnection();
} catch (IOException e) {
return ResponseBuilder.httpError(e);
}
try {
urlConnection.setRequestMethod("GET");
} catch (ProtocolException e) {
return ResponseBuilder.httpError(e);
}
urlConnection.setDoOutput(false);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(true);
urlConnection.setInstanceFollowRedirects(true);
urlConnection.setConnectTimeout(3000);

Map<String, String> header = session.getHeaders();
for (String s : FORWARDED_HEADERS) {
String v = header.get(s);
urlConnection.addRequestProperty(s, v);
}
addHeaders.forEach(urlConnection::addRequestProperty);

try {
urlConnection.connect();
} catch (IOException e) {
return ResponseBuilder.httpError(e);
}
int code;
try {
code = urlConnection.getResponseCode();
} catch (IOException e) {
return ResponseBuilder.httpError(e);
}
if (code != 200) {
urlConnection.disconnect();
return ResponseBuilder.httpError("此魔法链接服务器请求被bing拒绝!请稍后再试。错误代码:" + code, null, false);
}

int len = urlConnection.getContentLength();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(Math.max(len, 0));
try (InputStream inputStream = urlConnection.getInputStream()) {
for (int i = 0; i < len; i++) {
byteArrayOutputStream.write(inputStream.read());
}
} catch (FileNotFoundException e) {
urlConnection.disconnect();
return ResponseBuilder.httpError("此魔法链接服务器无法正常工作,请求被bing拒绝!", e, false);
} catch (IOException e) {
urlConnection.disconnect();
return ResponseBuilder.httpError(e);
}
urlConnection.disconnect();

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
return NanoHTTPD.newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
"application/json",
byteArrayInputStream,
len
);
}

/**
* Proxy a request as an image-related HTML response with same-origin headers.
*/
public static NanoHTTPD.Response proxyImageRequest(NanoHTTPD.IHTTPSession session, String targetUrl, String referer) {
HashMap<String, String> headers = new HashMap<>();
headers.put("sec-fetch-site", "same-origin");
headers.put("referer", referer);
NanoHTTPD.Response response = proxyGet(session, targetUrl, headers);
response.setMimeType("text/html");
return response;
}
}
24 changes: 24 additions & 0 deletions src/main/java/cn/jja8/newbinggogo/util/JsonUtils.java
Loading