239 lines
8.5 KiB
Java
239 lines
8.5 KiB
Java
/*
|
||
* DmitriyMX <dmitriymx@yandex.ru>
|
||
* 2017-01-04
|
||
*/
|
||
package kinosearch.webapp;
|
||
|
||
import com.google.gson.Gson;
|
||
import kinosearch.core.Kino;
|
||
import kinosearch.core.KinoPlay;
|
||
import kinosearch.core.Tools;
|
||
import kinosearch.core.warez.KinoWarez;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.context.ApplicationContext;
|
||
import org.springframework.stereotype.Controller;
|
||
import org.springframework.ui.ModelMap;
|
||
import org.springframework.web.bind.annotation.PathVariable;
|
||
import org.springframework.web.bind.annotation.RequestMapping;
|
||
import org.springframework.web.bind.annotation.RequestMethod;
|
||
import org.springframework.web.bind.annotation.RequestParam;
|
||
|
||
import javax.servlet.http.HttpServletRequest;
|
||
import javax.servlet.http.HttpServletResponse;
|
||
import java.io.BufferedInputStream;
|
||
import java.io.BufferedOutputStream;
|
||
import java.io.IOException;
|
||
import java.net.HttpURLConnection;
|
||
import java.net.MalformedURLException;
|
||
import java.net.URL;
|
||
import java.util.*;
|
||
import java.util.logging.Level;
|
||
import java.util.logging.Logger;
|
||
|
||
@Controller
|
||
public class WebAppController {
|
||
private final Logger logger = Logger.getLogger(WebAppController.class.getName());
|
||
@Autowired
|
||
private ApplicationContext coreContext;
|
||
|
||
private void setDefaultModel(ModelMap model) {
|
||
model.addAttribute("version", "2.0.10-SNAPSHOT");
|
||
model.addAttribute("rutext", "Поиск кино по пиратским кинотеатрам");
|
||
}
|
||
|
||
@RequestMapping(value = {"/", "/index.html"}, method = RequestMethod.GET)
|
||
public String index(ModelMap model) {
|
||
setDefaultModel(model);
|
||
return "index";
|
||
}
|
||
|
||
@RequestMapping(value = {"/", "/index.html"}, method = RequestMethod.GET, params = {"search"})
|
||
public String search(@RequestParam("search") String searchText, ModelMap model) {
|
||
if (searchText.trim().isEmpty()) {
|
||
return "redirect:/";
|
||
}
|
||
|
||
List<Kino> list = Collections.synchronizedList(new LinkedList<>());
|
||
Map<String, KinoWarez> kinoWarezMap = coreContext.getBeansOfType(KinoWarez.class);
|
||
|
||
ThreadGroup threadGroup = new ThreadGroup("");
|
||
for (KinoWarez kinoWarez : kinoWarezMap.values()) { //TODO надо ограничить количество одновременных потоков
|
||
new Thread(threadGroup, () -> {
|
||
List<Kino> outList = kinoWarez.search(searchText, false); //FIXME "strong" нужно учитывать
|
||
|
||
for (Kino kino : outList) {
|
||
kino.setName("[" + kinoWarez.getName() + "] " + kino.getName());
|
||
}
|
||
list.addAll(outList);
|
||
}).start();
|
||
}
|
||
|
||
// ждем максимум 15 секунд
|
||
//FIXME надо бы убивать потоки, которые не успели найти контент
|
||
for (int i = 0; i < 15 && threadGroup.activeCount() > 0; i++) {
|
||
Tools.SafeSleep(1000);
|
||
}
|
||
|
||
model.put("searchtext", searchText);
|
||
model.put("resultsearch", groupKino(list));
|
||
model.put("strong", false); //FIXME "strong" нужно учитывать
|
||
|
||
setDefaultModel(model);
|
||
return "index";
|
||
}
|
||
|
||
private List<Kino> groupKino(List<Kino> list) {
|
||
Map<String, KinoGroup> hashGroup = new HashMap<>();
|
||
List<Kino> grouppedList = new ArrayList<>();
|
||
|
||
//TODO: необходима оптимизация
|
||
Iterator<Kino> itr1 = list.iterator();
|
||
int skip = 1;
|
||
while (itr1.hasNext()) {
|
||
Kino kino1 = itr1.next();
|
||
String s1 = Tools.cleanString(kino1.getName().replaceAll("^\\[.+?\\] ",""));
|
||
|
||
if (hashGroup.containsKey(s1)) {
|
||
skip++;
|
||
continue;
|
||
}
|
||
|
||
KinoGroup group = new KinoGroup(s1, null, null);
|
||
|
||
Iterator<Kino> itr2 = list.iterator();
|
||
int val = 0;
|
||
while (itr2.hasNext()) {
|
||
if (val < skip) {
|
||
val++;
|
||
itr2.next();
|
||
continue;
|
||
}
|
||
|
||
Kino kino2 = itr2.next();
|
||
String s2 = Tools.cleanString(kino2.getName().replaceAll("^\\[.+?\\] ",""));
|
||
|
||
int res = s1.compareTo(s2);
|
||
if (res == 0) {
|
||
if (!group.contains(kino2)) {
|
||
group.add(kino2);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (group.getKinolist().size() > 0) {
|
||
group.add(kino1);
|
||
hashGroup.put(s1, group);
|
||
} else {
|
||
grouppedList.add(kino1);
|
||
}
|
||
|
||
skip++;
|
||
}
|
||
|
||
grouppedList.addAll(0, hashGroup.values());
|
||
return grouppedList;
|
||
}
|
||
|
||
@RequestMapping(value = "/player/{warez}/**", method = RequestMethod.GET)
|
||
public String player(@PathVariable() String warez, ModelMap model, HttpServletRequest request) throws MalformedURLException {
|
||
KinoWarez kinoWarez = coreContext.getBean(warez, KinoWarez.class);
|
||
if (kinoWarez == null) {
|
||
return "redirect:/";
|
||
}
|
||
|
||
//TODO а необходимость в URL точно оправдана?
|
||
URL requestUrl = new URL(request.getRequestURL().toString());
|
||
KinoPlay kinoPlay = kinoWarez.player(requestUrl.getPath().substring(("/player/"+warez).length()));
|
||
Gson gson = coreContext.getBean(Gson.class);
|
||
model.put("json", gson.toJson(kinoPlay));
|
||
|
||
setDefaultModel(model);
|
||
return "player";
|
||
}
|
||
|
||
@RequestMapping(value = "/proxy/{warez}/**", method = RequestMethod.GET)
|
||
public void proxy(@PathVariable String warez, HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||
//TODO а необходимость в URL точно оправдана?
|
||
URL requestUrl = new URL(request.getRequestURL().toString());
|
||
String path = requestUrl.getPath().substring(("/proxy/"+warez+"/").length());
|
||
|
||
URL url = new URL("http://" + path);
|
||
HttpURLConnection con =(HttpURLConnection) url.openConnection();
|
||
con.setRequestMethod("GET");
|
||
con.setDoOutput(true);
|
||
con.setDoInput(true);
|
||
con.setUseCaches(true);
|
||
|
||
for (Enumeration names = request.getHeaderNames(); names.hasMoreElements();) {
|
||
String headerName = names.nextElement().toString();
|
||
if (headerName.equalsIgnoreCase("referer")) continue;
|
||
con.setRequestProperty(headerName, request.getHeader(headerName));
|
||
}
|
||
|
||
boolean connected;
|
||
int _try = 0;
|
||
do {
|
||
try {
|
||
con.connect();
|
||
connected = true;
|
||
} catch (IOException e) {
|
||
con.disconnect();
|
||
connected = false;
|
||
_try++;
|
||
logger.log(Level.WARNING,String.format("Error connection to '%s': '%s'. Try again...", url.toString(), e.getMessage()));
|
||
}
|
||
} while (!connected && _try < 3);
|
||
|
||
if (!connected) {
|
||
response.sendError(524);
|
||
return;
|
||
}
|
||
|
||
int statusCode = con.getResponseCode();
|
||
response.setStatus(statusCode);
|
||
if (statusCode != 200 && statusCode != 206) {
|
||
con.disconnect();
|
||
return;
|
||
}
|
||
|
||
for (Map.Entry<String, List<String>> stringListEntry : con.getHeaderFields().entrySet()) {
|
||
Map.Entry mapEntry = stringListEntry;
|
||
if (mapEntry.getKey() != null) {
|
||
response.setHeader(mapEntry.getKey().toString(), ((List) mapEntry.getValue()).get(0).toString());
|
||
}
|
||
}
|
||
|
||
BufferedInputStream webToProxyBuf = new BufferedInputStream(con.getInputStream());
|
||
BufferedOutputStream proxyToClientBuf = new BufferedOutputStream(response.getOutputStream());
|
||
|
||
int oneByte;
|
||
try {
|
||
while ((oneByte = webToProxyBuf.read()) != -1) {
|
||
proxyToClientBuf.write(oneByte);
|
||
}
|
||
proxyToClientBuf.flush();
|
||
proxyToClientBuf.close();
|
||
} catch (Exception ignore) {
|
||
// ignore
|
||
}
|
||
|
||
webToProxyBuf.close();
|
||
con.disconnect();
|
||
}
|
||
|
||
@RequestMapping(value = {"/about", "/about.html"}, method = RequestMethod.GET)
|
||
public String about(ModelMap model) {
|
||
setDefaultModel(model);
|
||
return "about";
|
||
}
|
||
|
||
@RequestMapping(value = "/favicon.ico")
|
||
public void favicon(HttpServletResponse response) {
|
||
try {
|
||
response.sendError(404);
|
||
} catch (IOException e) {
|
||
logger.log(Level.WARNING, "favicon 404", e);
|
||
}
|
||
}
|
||
}
|