252 lines
6.6 KiB
Java
252 lines
6.6 KiB
Java
package com.fpghoti.biscuit.captcha;
|
|
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
|
|
import com.fpghoti.biscuit.Main;
|
|
import com.fpghoti.biscuit.PluginCore;
|
|
import com.fpghoti.biscuit.guild.BiscuitGuild;
|
|
import com.fpghoti.biscuit.logging.BColor;
|
|
import com.fpghoti.biscuit.rest.MessageText;
|
|
import com.fpghoti.biscuit.user.CaptchaUser;
|
|
import com.fpghoti.biscuit.user.PreUser;
|
|
import com.github.cage.Cage;
|
|
|
|
import net.dv8tion.jda.api.entities.Guild;
|
|
import net.dv8tion.jda.api.entities.Member;
|
|
import net.dv8tion.jda.api.entities.Role;
|
|
import net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel;
|
|
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
|
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
|
import net.dv8tion.jda.api.utils.FileUpload;
|
|
import net.dv8tion.jda.api.entities.User;
|
|
|
|
public class Captcha {
|
|
|
|
public static Captcha getUpdatedCaptcha(User user, MessageChannel channel, String response) {
|
|
CaptchaUser c = CaptchaUser.getCaptchaUser(user);
|
|
if(c.getCaptcha() == null) {
|
|
Captcha captcha = new Captcha(user, channel, response);
|
|
c.setCaptcha(captcha);
|
|
return captcha;
|
|
}else {
|
|
Captcha captcha = c.getCaptcha();
|
|
captcha.setChannel(channel);
|
|
captcha.setResponse(response);
|
|
c.setCaptcha(captcha);
|
|
return captcha;
|
|
}
|
|
}
|
|
|
|
private CaptchaUser captchaUser;
|
|
private MessageChannel channel;
|
|
private User user;
|
|
private String response;
|
|
private String token;
|
|
|
|
private Captcha(User user, MessageChannel channel, String response) {
|
|
this.captchaUser = CaptchaUser.getCaptchaUser(user);
|
|
this.channel = channel;
|
|
this.user = user;
|
|
this.response = response;
|
|
this.token = null;
|
|
}
|
|
|
|
private void setChannel(MessageChannel channel) {
|
|
this.channel = channel;
|
|
}
|
|
|
|
private void setResponse(String response) {
|
|
this.response = response;
|
|
}
|
|
|
|
public User getUser() {
|
|
return user;
|
|
}
|
|
|
|
public CaptchaUser getCaptchaUser() {
|
|
return captchaUser;
|
|
}
|
|
|
|
public MessageChannel getChannel() {
|
|
return channel;
|
|
}
|
|
|
|
public String getToken() {
|
|
return this.token;
|
|
}
|
|
|
|
public void genToken() {
|
|
Cage cage = Main.getCage();
|
|
token = cage.getTokenGenerator().next();
|
|
}
|
|
|
|
public void handleResponse() {
|
|
if(captchaUser.isEmpty() && !captchaUser.inTestMode()) {
|
|
return;
|
|
}
|
|
|
|
String captchaString = leeway(response);
|
|
|
|
if(token != null && !captchaString.equalsIgnoreCase(token)) {
|
|
respond("Sorry! That's not quite right! Please try again.");
|
|
return;
|
|
}
|
|
|
|
if(token == null) {
|
|
|
|
log("Generating captcha challenge for user " + user.getName() + " " + user.getAsMention() + "...");
|
|
|
|
genToken();
|
|
generateImage();
|
|
File captcha = getImageFile();
|
|
FileUpload capUpload = FileUpload.fromData(captcha);
|
|
|
|
respond("Respond with the exact text in this image.");
|
|
//channel.sendFile(captcha).submit();
|
|
channel.sendFiles(capUpload);
|
|
}else {
|
|
boolean disable = false;
|
|
if(captchaUser.inTestMode()) {
|
|
disable = true;
|
|
}else {
|
|
doCaptchaReward();
|
|
}
|
|
respond("Well done, " + user.getAsMention() + "!");
|
|
if(disable) {
|
|
captchaUser.disableTestMode();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void generateImage() {
|
|
Cage cage = Main.getCage();
|
|
OutputStream os;
|
|
|
|
try {
|
|
if(!Main.isPlugin) {
|
|
//If Biscuit is running standalone output to this directory
|
|
os = new FileOutputStream("captcha/" + user.getId() + ".jpg", false);
|
|
}else {
|
|
//If Biscuit is running as a Spigot plugin output to this directory
|
|
File c = new File(PluginCore.plugin.getDataFolder(), "captcha/" + user.getId() + ".jpg");
|
|
os = new FileOutputStream(c, false);
|
|
}
|
|
} catch (FileNotFoundException e) {
|
|
Main.getMainBiscuit().error("Cannot retrieve captcha image directory.");
|
|
e.printStackTrace();
|
|
return;
|
|
}
|
|
|
|
//Draw captcha image
|
|
try {
|
|
cage.draw(token, os);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
return;
|
|
} finally {
|
|
try {
|
|
os.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public File getImageFile() {
|
|
if(!Main.isPlugin) {
|
|
return new File("captcha/" + user.getId() + ".jpg");
|
|
}else {
|
|
return new File(PluginCore.plugin.getDataFolder(), "captcha/" + user.getId() + ".jpg");
|
|
}
|
|
}
|
|
|
|
public void doCaptchaReward() {
|
|
for(PreUser p : captchaUser) {
|
|
//mark the PreUser as "done"
|
|
p.setDone();
|
|
|
|
BiscuitGuild biscuit = p.getBiscuitGuild();
|
|
|
|
if(biscuit == null) {
|
|
Main.getMainBiscuit().error("CAPTCHA ERROR: Null Biscuit");
|
|
return;
|
|
}
|
|
|
|
Guild g = biscuit.getGuild();
|
|
|
|
if(g == null) {
|
|
biscuit.error("CAPTCHA ERROR: Null Guild");
|
|
return;
|
|
}
|
|
|
|
Role newrole = biscuit.getCaptchaRewardRole();
|
|
Role defaultrole = biscuit.getDefaultRole();
|
|
|
|
if(newrole == null) {
|
|
biscuit.error("Cannot find captcha reward role!");
|
|
return;
|
|
}
|
|
|
|
if(defaultrole == null) {
|
|
biscuit.error("Cannot find captcha default role!");
|
|
return;
|
|
}
|
|
|
|
Member member = g.getMemberById(user.getId());
|
|
|
|
g.addRoleToMember(member, newrole).complete();
|
|
g.removeRoleFromMember(member, defaultrole).complete();
|
|
p.remove();
|
|
token = null;
|
|
|
|
log(BColor.YELLOW_BOLD + user.getName() + " successfully completed a captcha challenge. Granting role.");
|
|
biscuit.eventLog(" ``" + user.getName() +"`` " + user.getAsMention() + " successfully completed a captcha challenge. Granting role.");
|
|
}
|
|
}
|
|
|
|
public void removeFiles() {
|
|
File captcha;
|
|
if(!Main.isPlugin) {
|
|
//Biscuit is running standalone. Remove file from this directory
|
|
captcha = new File("captcha/" + captchaUser.getUser().getId() + ".jpg");
|
|
}else {
|
|
//Biscuit is running as Spigot plugin. Remove file from this directory
|
|
captcha = new File(PluginCore.plugin.getDataFolder(), "captcha/" + captchaUser.getUser().getId() + ".jpg");
|
|
}
|
|
captcha.delete();
|
|
}
|
|
|
|
//More characters may be replaced/removed here based on
|
|
//How many/what type of errors users commonly make
|
|
private String leeway(String s) {
|
|
s = s.replace("0", "O");
|
|
return s;
|
|
}
|
|
|
|
private void log(String msg) {
|
|
String prefix = "";
|
|
if(captchaUser.inTestMode()) {
|
|
prefix = "[TEST] ";
|
|
}
|
|
Main.getMainBiscuit().log(prefix + msg);
|
|
}
|
|
|
|
private void respond(String msg) {
|
|
String prefix = "";
|
|
if(captchaUser.inTestMode()) {
|
|
prefix = "[TEST] ";
|
|
}
|
|
if(channel instanceof TextChannel) {
|
|
MessageText.send((TextChannel)channel, prefix + msg);
|
|
}else if(channel instanceof PrivateChannel) {
|
|
MessageText.send((PrivateChannel)channel, prefix + msg);
|
|
}
|
|
}
|
|
|
|
}
|