Adapt to new BonjourMadame website and add true random
This commit is contained in:
parent
cd29d6748f
commit
7ce05cd028
@ -12,7 +12,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
public class Ass extends NumberedCommande {
|
||||
|
||||
public Ass() {
|
||||
super(LogManager.getLogger(), "http://les400culs.com/","featured-img","img");
|
||||
super(LogManager.getLogger(), "http://les400culs.com/","-2/","featured-img","img");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -11,7 +11,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
public class Boobs extends NumberedCommande {
|
||||
|
||||
public Boobs() {
|
||||
super(LogManager.getLogger(), "http://lesaintdesseins.fr/","featured-img","img");
|
||||
super(LogManager.getLogger(), "http://lesaintdesseins.fr/","-2/","featured-img","img");
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -1,9 +1,11 @@
|
||||
package net.Broken.Commands.Over18;
|
||||
|
||||
import net.Broken.Commande;
|
||||
import net.Broken.Tools.Command.NumberedCommande;
|
||||
import net.Broken.Tools.EmbedMessageUtils;
|
||||
import net.Broken.Tools.FindContentOnWebPage;
|
||||
import net.Broken.Tools.Redirection;
|
||||
import net.Broken.Tools.TrueRandom;
|
||||
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -14,50 +16,15 @@ import java.io.IOException;
|
||||
/**
|
||||
* Madame command that return random picture from dites.bonjourmadame.fr
|
||||
*/
|
||||
public class Madame implements Commande{
|
||||
public class Madame extends NumberedCommande {
|
||||
Logger logger = LogManager.getLogger();
|
||||
MessageReceivedEvent event;
|
||||
public String HELP="T'es sérieux la?";
|
||||
public String HELP = "T'es sérieux la?";
|
||||
|
||||
@Override
|
||||
public void action(String[] args, MessageReceivedEvent event) {
|
||||
this.event = event;
|
||||
Redirection redirect = new Redirection();
|
||||
boolean success=false;
|
||||
boolean error=false;
|
||||
int errorCp=0;
|
||||
while(!success && !error)
|
||||
{
|
||||
try {
|
||||
|
||||
String url = redirect.get("http://dites.bonjourmadame.fr/random");
|
||||
logger.debug("URL: "+url);
|
||||
if(scanPageForTipeee(url, logger)){
|
||||
logger.debug("Advertisement detected! Retry! ("+url+")");
|
||||
}
|
||||
else{
|
||||
event.getTextChannel().sendMessage(url).queue();
|
||||
success=true;
|
||||
public Madame() {
|
||||
super(LogManager.getLogger(), "http://www.bonjourmadame.fr/page/", "/");
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
errorCp++;
|
||||
logger.warn("Erreur de redirection. (Essais n°"+errorCp+")");
|
||||
if(errorCp>5)
|
||||
{
|
||||
logger.error("5 Erreur de redirection.");
|
||||
error=true;
|
||||
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:warning: **__Erreur de redirection (5 essais), Réessayez__**:warning: ").queue();
|
||||
|
||||
}
|
||||
|
||||
}catch (StringIndexOutOfBoundsException e){
|
||||
logger.catching(e);
|
||||
event.getTextChannel().sendMessage(EmbedMessageUtils.getInternalError()).queue();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrivateUsable() {
|
||||
@ -77,24 +44,47 @@ public class Madame implements Commande{
|
||||
|
||||
/**
|
||||
* Detect if picture link go to Tepeee
|
||||
*
|
||||
* @param url
|
||||
* @return true is Tepeee link is detected
|
||||
* @throws StringIndexOutOfBoundsException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static boolean scanPageForTipeee(String url, Logger logger) throws StringIndexOutOfBoundsException, IOException{
|
||||
public static boolean scanPageForTipeee(String url, Logger logger) throws StringIndexOutOfBoundsException, IOException {
|
||||
String content = FindContentOnWebPage.getSourceUrl(url);
|
||||
String imgClickLink = content.substring(content.indexOf("photo post"));
|
||||
String imgClickLink = content.substring(content.indexOf("class=\"post-content"));
|
||||
imgClickLink = imgClickLink.substring(imgClickLink.indexOf("<a"));
|
||||
imgClickLink = imgClickLink.substring(imgClickLink.indexOf("\""));
|
||||
imgClickLink = imgClickLink.substring(0, imgClickLink.indexOf("\">"));
|
||||
imgClickLink = imgClickLink.substring(1);
|
||||
logger.debug("Image link: " + imgClickLink);
|
||||
if(imgClickLink.contains("tipeee")){
|
||||
logger.debug("Detect tipeee link! ");
|
||||
logger.trace("Image link: " + imgClickLink);
|
||||
if (imgClickLink.contains("tipeee")) {
|
||||
logger.trace("Detect tipeee link! ");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String poll() throws IOException {
|
||||
boolean success = false;
|
||||
String imgUrl = null;
|
||||
while (!success ) {
|
||||
|
||||
checkRandom();
|
||||
int randomResult = randomQueue.poll();
|
||||
String url = baseURL + randomResult + urlSuffix;
|
||||
logger.debug("URL: " + url);
|
||||
if (scanPageForTipeee(url, logger)) {
|
||||
logger.debug("Advertisement detected! Retry! (" + url + ")");
|
||||
} else {
|
||||
imgUrl = FindContentOnWebPage.doYourJob(url, "post-content", "img");
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
}
|
||||
return imgUrl;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
@NoDev()
|
||||
public class Pipe extends NumberedCommande {
|
||||
public Pipe() {
|
||||
super(LogManager.getLogger(), "http://feelation.com/","featured-img","img");
|
||||
super(LogManager.getLogger(), "http://feelation.com/","-2/","featured-img","img");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,6 +2,7 @@ package net.Broken.Tools.Command;
|
||||
import net.Broken.Commande;
|
||||
import net.Broken.Tools.FindContentOnWebPage;
|
||||
import net.Broken.Tools.LimitChecker;
|
||||
import net.Broken.Tools.TrueRandom;
|
||||
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -9,6 +10,9 @@ import org.apache.logging.log4j.Logger;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* Abstact class used for all command that need to find the max number of page on a web site.
|
||||
@ -16,12 +20,13 @@ import java.net.URL;
|
||||
@Ignore
|
||||
public abstract class NumberedCommande implements Commande{
|
||||
private Logger logger = LogManager.getLogger();
|
||||
private int minNumber = 1;
|
||||
private int maxNumber = -1;
|
||||
private String baseURL;
|
||||
private String divClass;
|
||||
private String htmlType;
|
||||
|
||||
protected int minNumber = 1;
|
||||
protected int maxNumber = -1;
|
||||
protected String baseURL;
|
||||
protected String divClass;
|
||||
protected String htmlType;
|
||||
protected String urlSuffix;
|
||||
protected LinkedBlockingQueue<Integer> randomQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
@ -30,28 +35,33 @@ public abstract class NumberedCommande implements Commande{
|
||||
* @param divClass DivClass to search to extract image
|
||||
* @param htmlType HTML tag to extract image (img)
|
||||
*/
|
||||
public NumberedCommande(Logger logger, String baseURL, String divClass, String htmlType) {
|
||||
public NumberedCommande(Logger logger, String baseURL, String urlSuffix, String divClass, String htmlType) {
|
||||
this.logger = logger;
|
||||
this.baseURL = baseURL;
|
||||
this.divClass = divClass;
|
||||
this.htmlType = htmlType;
|
||||
this.urlSuffix = urlSuffix;
|
||||
try {
|
||||
logger.debug("Checking max...");
|
||||
maxNumber = LimitChecker.doYourJob(baseURL, minNumber);
|
||||
maxNumber = LimitChecker.doYourJob(baseURL, 2, urlSuffix);
|
||||
logger.info("Limit is "+maxNumber);
|
||||
} catch (IOException e) {
|
||||
logger.catching(e);
|
||||
}
|
||||
}
|
||||
|
||||
public NumberedCommande(Logger logger, String baseURL, String urlSuffix){
|
||||
this(logger, baseURL, urlSuffix, null, null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action(String[] args, MessageReceivedEvent event) {
|
||||
try
|
||||
{
|
||||
if(args.length == 0)
|
||||
{
|
||||
int randomResult = (int) (minNumber + (Math.random() * (maxNumber - minNumber)));
|
||||
String result = FindContentOnWebPage.doYourJob(baseURL + randomResult + "-2", divClass, htmlType);
|
||||
String result = poll();
|
||||
event.getTextChannel().sendMessage(event.getAuthor().getAsMention()+"\n"+result).queue();
|
||||
|
||||
}
|
||||
@ -64,7 +74,7 @@ public abstract class NumberedCommande implements Commande{
|
||||
|
||||
int newNumber = maxNumber;
|
||||
try {
|
||||
newNumber = LimitChecker.doYourJob(baseURL, maxNumber);
|
||||
newNumber = LimitChecker.doYourJob(baseURL, maxNumber, urlSuffix);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -89,7 +99,7 @@ public abstract class NumberedCommande implements Commande{
|
||||
huc.connect();
|
||||
int result = huc.getResponseCode();
|
||||
if (result == 200) {
|
||||
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n" + baseURL + number + "-2/").queue();
|
||||
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n" + baseURL + number + urlSuffix).queue();
|
||||
} else {
|
||||
event.getTextChannel().sendMessage(event.getAuthor().getAsMention() + "\n:warning: **__Erreur__** :warning:\n:arrow_right: Page introuvable (404)").queue();
|
||||
}
|
||||
@ -119,4 +129,27 @@ public abstract class NumberedCommande implements Commande{
|
||||
}
|
||||
|
||||
|
||||
private void completeRandom() throws IOException {
|
||||
TrueRandom trueRandom = TrueRandom.getINSTANCE();
|
||||
ArrayList<Integer> numbers = trueRandom.getNumbers(minNumber, maxNumber);
|
||||
|
||||
randomQueue.addAll(numbers);
|
||||
|
||||
}
|
||||
|
||||
protected void checkRandom() throws IOException {
|
||||
logger.trace("Queue size: " + randomQueue.size());
|
||||
if(randomQueue.isEmpty()){
|
||||
logger.debug("Queue empty, update it.");
|
||||
completeRandom();
|
||||
}
|
||||
}
|
||||
|
||||
public String poll() throws IOException {
|
||||
checkRandom();
|
||||
int randomResult = randomQueue.poll();
|
||||
return FindContentOnWebPage.doYourJob(baseURL + randomResult + urlSuffix, divClass, htmlType);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import net.Broken.DB.Repository.GuildPreferenceRepository;
|
||||
import net.Broken.MainBot;
|
||||
import net.Broken.SpringContext;
|
||||
import net.Broken.Tools.DayListener.NewDayListener;
|
||||
import net.Broken.Tools.FindContentOnWebPage;
|
||||
import net.Broken.Tools.Redirection;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
@ -13,6 +14,11 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -30,15 +36,31 @@ public class DailyMadame implements NewDayListener{
|
||||
private Logger logger = LogManager.getLogger();
|
||||
@Override
|
||||
public void onNewDay() {
|
||||
Redirection redirect = new Redirection();
|
||||
|
||||
List<Guild> guilds = MainBot.jda.getGuilds();
|
||||
|
||||
String imgUrl;
|
||||
try {
|
||||
int day = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
|
||||
if(day != Calendar.MONDAY && day != Calendar.SUNDAY){
|
||||
LocalDate now = LocalDate.now().minusDays(1);
|
||||
String date = DateTimeFormatter.ofPattern("yyyy/MM/dd").format(now);
|
||||
|
||||
String url = "http://www.bonjourmadame.fr/" + date + "/";
|
||||
|
||||
imgUrl = FindContentOnWebPage.doYourJob(url, "post-content", "img");
|
||||
|
||||
|
||||
}else {
|
||||
Madame command = (Madame) MainBot.commandes.get("madame");
|
||||
imgUrl = command.poll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
for(Guild guild : guilds){
|
||||
TextChannel chanel = null;
|
||||
boolean success=false;
|
||||
boolean error=false;
|
||||
int errorCp=0;
|
||||
logger.debug(guild.getName());
|
||||
if(guildPreferenceRepository.findByGuildId(guild.getId()).get(0).isDailyMadame()){
|
||||
for(TextChannel iterator : guild.getTextChannels())
|
||||
@ -50,32 +72,11 @@ public class DailyMadame implements NewDayListener{
|
||||
}
|
||||
}
|
||||
if(chanel != null){
|
||||
while(!success && !error)
|
||||
{
|
||||
try {
|
||||
|
||||
String url = redirect.get("http://dites.bonjourmadame.fr/random");
|
||||
logger.debug("URL: "+url);
|
||||
if(Madame.scanPageForTipeee(url, logger)){
|
||||
logger.debug("Advertisement detected! Retry! ("+url+")");
|
||||
}
|
||||
else{
|
||||
chanel.sendMessage("Le Daily Madame mes petits cochons :kissing_heart:\n" + url).queue();
|
||||
success=true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
errorCp++;
|
||||
logger.warn("Erreur de redirection. (Essais n°"+errorCp+")");
|
||||
if(errorCp>5)
|
||||
{
|
||||
logger.error("5 Erreur de redirection.");
|
||||
error=true;
|
||||
chanel.sendMessage("Le Daily Madame mes petits cochons :kissing_heart: \n" + imgUrl).queue();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.info("No NSFW chanel found for " + guild.getName() + ", ignoring it!");
|
||||
}
|
||||
@ -83,7 +84,8 @@ public class DailyMadame implements NewDayListener{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}catch (IOException e) {
|
||||
logger.catching(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,9 @@ public class FindContentOnWebPage {
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String doYourJob(String url, String divClass, String htmlType) throws IOException {
|
||||
// System.out.println(url);
|
||||
System.out.println(url);
|
||||
String source = getSourceUrl(url);
|
||||
int divIndex = source.indexOf(divClass);
|
||||
int divIndex = source.indexOf("class=\""+divClass);
|
||||
String sub = source.substring(divIndex);
|
||||
// System.out.println(sub);
|
||||
sub = sub.replace(divClass,"");
|
||||
|
@ -22,7 +22,7 @@ public class LimitChecker {
|
||||
* @return max Number
|
||||
* @throws IOException
|
||||
*/
|
||||
public static int doYourJob(String baseURL, int minNumber) throws IOException {
|
||||
public static int doYourJob(String baseURL, int minNumber, String suffix) throws IOException {
|
||||
int number = minNumber;
|
||||
URL u = null;
|
||||
boolean redirected = false;
|
||||
@ -30,7 +30,7 @@ public class LimitChecker {
|
||||
|
||||
while(!redirected )
|
||||
{
|
||||
String origin = baseURL+number+"-2/";
|
||||
String origin = baseURL+number+suffix;
|
||||
String newUrl = redirection.get(origin);
|
||||
logger.trace("Origin URL: "+origin+" Result: "+newUrl);
|
||||
if(newUrl.equals(origin))
|
||||
@ -43,7 +43,7 @@ public class LimitChecker {
|
||||
logger.debug("First pass: "+number);
|
||||
while(!redirected )
|
||||
{
|
||||
String origin = baseURL+number+"-2/";
|
||||
String origin = baseURL+number+suffix;
|
||||
String newUrl = redirection.get(origin);
|
||||
logger.trace("Origin URL: "+origin+" Result: "+newUrl);
|
||||
if(newUrl.equals(origin))
|
||||
@ -56,7 +56,7 @@ public class LimitChecker {
|
||||
logger.debug("Second pass: "+number);
|
||||
while(!redirected )
|
||||
{
|
||||
String origin = baseURL+number+"-2/";
|
||||
String origin = baseURL+number+suffix;
|
||||
String newUrl = redirection.get(origin);
|
||||
logger.trace("Origin URL: "+origin+" Result: "+newUrl);
|
||||
if(newUrl.equals(origin))
|
||||
@ -69,7 +69,7 @@ public class LimitChecker {
|
||||
logger.debug("Third pass: "+number);
|
||||
while(!redirected )
|
||||
{
|
||||
String origin = baseURL+number+"-2/";
|
||||
String origin = baseURL+number+suffix;
|
||||
String newUrl = redirection.get(origin);
|
||||
logger.trace("Origin URL: "+origin+" Result: "+newUrl);
|
||||
if(newUrl.equals(origin))
|
||||
|
@ -2,6 +2,7 @@ package net.Broken.Tools;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
@ -23,16 +24,19 @@ public class Redirection {
|
||||
*/
|
||||
public String get(String urlString) throws IOException {
|
||||
System.setProperty("http.agent","Googlebot");
|
||||
URLConnection con = new URL(urlString).openConnection();
|
||||
HttpURLConnection con = (HttpURLConnection) new URL(urlString).openConnection();
|
||||
con.setRequestProperty("User-Agent","Googlebot/2.1 (+http://www.googlebot.com/bot.html)");
|
||||
//System.out.println( "orignal url: " + con.getURL() );
|
||||
con.connect();
|
||||
//System.out.println( "connected url: " + con.getURL() );
|
||||
InputStream is = null;
|
||||
if(con.getResponseCode() != 200)
|
||||
return "";
|
||||
is = con.getInputStream();
|
||||
String urlReturn=con.getURL().toString();
|
||||
//System.out.println( "redirected url: " + con.getURL() );
|
||||
is.close();
|
||||
|
||||
return urlReturn;
|
||||
}
|
||||
|
||||
|
83
src/main/java/net/Broken/Tools/TrueRandom.java
Normal file
83
src/main/java/net/Broken/Tools/TrueRandom.java
Normal file
@ -0,0 +1,83 @@
|
||||
package net.Broken.Tools;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TrueRandom {
|
||||
|
||||
private static TrueRandom INSTANCE = new TrueRandom();
|
||||
|
||||
public static TrueRandom getINSTANCE() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private Logger logger = LogManager.getLogger();
|
||||
|
||||
private String url = "https://api.random.org/json-rpc/2/invoke";
|
||||
private String apiKey = System.getenv("RANDOM_API_KEY");
|
||||
|
||||
private TrueRandom() {
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getNumbers(int min, int max) throws IOException {
|
||||
HttpClient httpClient = HttpClientBuilder.create().build();
|
||||
|
||||
String postVal = "{\"jsonrpc\":\"2.0\",\"method\":\"generateIntegers\",\"params\":{\"apiKey\":\"" + apiKey + "\",\"n\":50,\"min\":" + min + ",\"max\":" + max + ",\"replacement\":" + (((max - min) >= 50) ? "false" : "true") + "},\"id\":41}";
|
||||
StringEntity entity = new StringEntity(postVal, ContentType.APPLICATION_JSON);
|
||||
HttpPost request = new HttpPost(url);
|
||||
request.setEntity(entity);
|
||||
request.setHeader("Accept", "application/json");
|
||||
request.setHeader("Content-type", "application/json");
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
int status = response.getStatusLine().getStatusCode();
|
||||
logger.debug("Status: " + status);
|
||||
|
||||
if(status != 200){
|
||||
logger.error("Request fail! Status: " + status);
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
InputStream responseIS = response.getEntity().getContent();
|
||||
String content = IOUtils.toString(responseIS, "UTF-8");
|
||||
logger.trace(content);
|
||||
|
||||
JSONObject json = new JSONObject(content);
|
||||
if(json.keySet().contains("error")){
|
||||
logger.error("Request fail!");
|
||||
logger.error("Request : " + postVal);
|
||||
logger.error("Response : " + content);
|
||||
throw new IOException();
|
||||
|
||||
}
|
||||
|
||||
logger.debug("Request left: " + json.getJSONObject("result").getInt("requestsLeft"));
|
||||
logger.debug("Bits left: " + json.getJSONObject("result").getInt("bitsLeft"));
|
||||
logger.debug("Numbers: " + json.getJSONObject("result").getJSONObject("random").getJSONArray("data"));
|
||||
|
||||
List<Object> numbers = json.getJSONObject("result").getJSONObject("random").getJSONArray("data").toList();
|
||||
|
||||
ArrayList<Integer> converted = new ArrayList<>();
|
||||
for (Object nbr : numbers) {
|
||||
converted.add((Integer) nbr);
|
||||
}
|
||||
return converted;
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user