package pl.shockah.shocky;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.pircbotx.Channel;
import org.pircbotx.PircBotX;
import org.pircbotx.User;
import pl.shockah.shocky.interfaces.IAcceptURLs;
public class URLDispatcher {
private static final Pattern urlPattern = Pattern.compile("(([a-z]+)://)?([a-z0-9]+(\\.[a-z0-9-]+)+(:[0-9]+)?)(/[a-z0-9-._~:/?#\\[\\]@!$&'()*+,;=%]+)?",Pattern.CASE_INSENSITIVE);
private static final List<IAcceptURLs> handles = new ArrayList<IAcceptURLs>();
public static void findURLs(PircBotX bot, Channel channel, User sender, String message) {
StringTokenizer tokens = new StringTokenizer(message);
Map<IAcceptURLs, List<URL>> map = null;
int total = 0;
while (total < 8 && tokens.hasMoreTokens()) {
String token = tokens.nextToken();
char c1 = token.charAt(0), c2 = token.charAt(token.length()-1);
if ((c1=='('&&c2==')')||(c1=='['&&c2==']')||(c1=='{'&&c2=='}')||(c1=='<'&&c2=='>'))
token = token.substring(1, token.length()-1);
Matcher m = urlPattern.matcher(token);
if (!m.find())
continue;
String found = m.group();
String protocol = m.group(2);
if (protocol == null)
found = "http://"+found;
URL u;
try {u = new URL(found);}
catch (MalformedURLException e) {continue;}
synchronized (handles) {
for (int i = 0; i < handles.size(); ++i) {
IAcceptURLs h = handles.get(i);
if (!h.shouldAcceptURL(u))
continue;
if (map == null) {
if (!tokens.hasMoreTokens()) {
h.handleURL(bot, channel, sender, Collections.singletonList(u));
return;
}
map = new LinkedHashMap<IAcceptURLs, List<URL>>(2, 1.0f);
}
List<URL> list;
if (map.containsKey(h))
list = map.get(h);
else
map.put(h, list = new LinkedList<URL>());
if (!list.contains(u)) {
list.add(u);
++total;
}
}
}
}
if (map != null) {
for (Map.Entry<IAcceptURLs, List<URL>> entry : map.entrySet()) {
IAcceptURLs handler = entry.getKey();
List<URL> list = entry.getValue();
int a = 0, b = 0, c = list.size();
if (c <= 3) {
handler.handleURL(bot, channel, sender, list);
continue;
}
while (a < c) {
b += 3;
if (b > c)
b = c;
handler.handleURL(bot, channel, sender, list.subList(a, b));
a = b;
}
}
}
}
public static void addHandler(IAcceptURLs i) {
synchronized (handles) {
handles.add(i);
}
}
public static void removeHandler(IAcceptURLs i) {
synchronized (handles) {
handles.remove(i);
}
}
}