Subversion Repositories SmartDukaan

Rev

Rev 37393 | Rev 37407 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
29451 manish 1
package com.smartdukaan.cron.scheduled;
2
 
36420 amit 3
import com.spice.profitmandi.common.web.client.HttpClientFactory;
30209 amit.gupta 4
import com.spice.profitmandi.dao.model.ImeiActivationTimestampModel;
5
import com.spice.profitmandi.dao.repository.fofo.ActivatedImeiRepository;
6
import com.spice.profitmandi.service.inventory.InventoryService;
36420 amit 7
import org.apache.http.NameValuePair;
8
import org.apache.http.client.entity.UrlEncodedFormEntity;
9
import org.apache.http.client.methods.CloseableHttpResponse;
10
import org.apache.http.client.methods.HttpGet;
11
import org.apache.http.client.methods.HttpPost;
12
import org.apache.http.impl.client.BasicCookieStore;
13
import org.apache.http.impl.client.CloseableHttpClient;
14
import org.apache.http.message.BasicNameValuePair;
15
import org.apache.http.util.EntityUtils;
29451 manish 16
import org.apache.logging.log4j.LogManager;
17
import org.apache.logging.log4j.Logger;
18
import org.json.JSONObject;
19
import org.springframework.beans.factory.annotation.Autowired;
20
import org.springframework.stereotype.Component;
36260 amit 21
import org.springframework.transaction.annotation.Propagation;
22
import org.springframework.transaction.annotation.Transactional;
29451 manish 23
 
36420 amit 24
import java.io.IOException;
25
import java.nio.charset.StandardCharsets;
30209 amit.gupta 26
import java.time.LocalDate;
27
import java.time.format.DateTimeFormatter;
30335 amit.gupta 28
import java.util.ArrayList;
29
import java.util.List;
29451 manish 30
 
31
@Component
32
class VivoImeiActivationService {
33
 
33453 amit.gupta 34
    @Autowired
35
    InventoryService inventoryService;
29451 manish 36
 
33453 amit.gupta 37
    @Autowired
38
    CaptchaService captchaService;
29466 amit.gupta 39
 
33453 amit.gupta 40
    @Autowired
41
    ActivatedImeiRepository activatedImeiRepository;
29451 manish 42
 
33453 amit.gupta 43
    private static final Logger LOGGER = LogManager.getLogger(VivoImeiActivationService.class);
29451 manish 44
 
36260 amit 45
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
33453 amit.gupta 46
    public void checkImeiActivation() throws Exception {
47
        if (LocalDate.now().getDayOfMonth() == 1) return;
36253 amit 48
 
49
        List<ImeiActivationTimestampModel> imeisActivationList = activatedImeiRepository
36580 amit 50
                .selectImeiActivationPendingByBrand("Vivo", 4);
36253 amit 51
        LOGGER.info("Secondary imeisActivationList = {}, size = {}", imeisActivationList, imeisActivationList.size());
52
 
53
        processImeis(imeisActivationList);
54
    }
55
 
36260 amit 56
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
36253 amit 57
    public void checkImeiActivationTertiary() throws Exception {
58
        if (LocalDate.now().getDayOfMonth() == 1) return;
59
 
60
        List<ImeiActivationTimestampModel> imeisActivationList = activatedImeiRepository
61
                .selectImeiActivationPendingByBrandTertiary("Vivo", 2);
62
        LOGGER.info("Tertiary imeisActivationList = {}, size = {}", imeisActivationList, imeisActivationList.size());
63
 
64
        processImeis(imeisActivationList);
65
    }
66
 
67
    private void processImeis(List<ImeiActivationTimestampModel> imeisActivationList) throws Exception {
68
        if (imeisActivationList.isEmpty()) return;
69
 
36420 amit 70
        BasicCookieStore cookieStore = new BasicCookieStore();
71
        try (CloseableHttpClient httpClient = HttpClientFactory.apacheHttpWithCookies(cookieStore)) {
72
            // Seed the session cookies
73
            HttpGet seed = new HttpGet("https://www.vivo.com/in/support/IMEI");
74
            try (CloseableHttpResponse seedResponse = httpClient.execute(seed)) {
75
                EntityUtils.consumeQuietly(seedResponse.getEntity());
33453 amit.gupta 76
            }
29466 amit.gupta 77
 
36420 amit 78
            for (ImeiActivationTimestampModel imeiActivationTimestampModel : imeisActivationList) {
37402 amit 79
                Captcha captcha = this.getNewCaptcha(httpClient, cookieStore);
80
                if (captcha == null) {
37393 amit 81
                    // Solver returned something that is not a captcha code (it was down
82
                    // for 46 days returning an nginx 502 page, which used to be submitted
83
                    // to Vivo verbatim). Skip; this IMEI is picked up on the next run.
84
                    continue;
85
                }
37402 amit 86
                this.getImeiActivation(captcha, httpClient, imeiActivationTimestampModel);
33453 amit.gupta 87
            }
36253 amit 88
        }
33453 amit.gupta 89
    }
29451 manish 90
 
37402 amit 91
    /** A solved captcha: the code, plus the image it came from so the verdict can be reported. */
92
    static final class Captcha {
93
        final String code;
94
        final byte[] image;
29451 manish 95
 
37402 amit 96
        Captcha(String code, byte[] image) {
97
            this.code = code;
98
            this.image = image;
99
        }
100
    }
101
 
102
    public Captcha getNewCaptcha(CloseableHttpClient httpClient, BasicCookieStore cookieStore) throws Exception {
103
        HttpGet request = new HttpGet("https://www.vivo.com/in/support/generatingCodes");
104
 
105
        // Kept in memory rather than written to a shared /tmp/captcha.jpg: the two
106
        // Vivo jobs run concurrently and used to overwrite each other's image. The
107
        // bytes are needed for the verdict report anyway.
108
        byte[] bytes;
36420 amit 109
        try (CloseableHttpResponse response = httpClient.execute(request)) {
37402 amit 110
            bytes = EntityUtils.toByteArray(response.getEntity());
36253 amit 111
        }
29451 manish 112
 
37402 amit 113
        String code = captchaService.getCaptchaCode(bytes);
114
        return code == null ? null : new Captcha(code, bytes);
33453 amit.gupta 115
    }
29451 manish 116
 
37402 amit 117
    public void getImeiActivation(Captcha captcha, CloseableHttpClient httpClient,
33453 amit.gupta 118
                                  ImeiActivationTimestampModel vivoImeiAndActivationTimeStampModel) throws Exception {
29451 manish 119
 
33453 amit.gupta 120
        String imei = vivoImeiAndActivationTimeStampModel.getSerialNumber();
29466 amit.gupta 121
 
36420 amit 122
        List<NameValuePair> form = new ArrayList<>();
123
        form.add(new BasicNameValuePair("imei", imei));
37402 amit 124
        form.add(new BasicNameValuePair("code", captcha.code));
36420 amit 125
        HttpPost post = new HttpPost("https://www.vivo.com/in/support/checkCode");
126
        post.setEntity(new UrlEncodedFormEntity(form, StandardCharsets.UTF_8));
29466 amit.gupta 127
 
36253 amit 128
        JSONObject imeiActivationJson;
36420 amit 129
        try (CloseableHttpResponse response2 = httpClient.execute(post)) {
130
            imeiActivationJson = new JSONObject(EntityUtils.toString(response2.getEntity()));
36253 amit 131
        }
132
 
33453 amit.gupta 133
        JSONObject data = imeiActivationJson.getJSONObject("data");
134
        int status = data.getInt("status");
37402 amit 135
 
136
        // Vivo is the only judge of whether our guess was right; status 0 means the
137
        // captcha was wrong. Hand that back so the sample becomes training data.
138
        captchaService.reportVerdict(captcha.image, captcha.code, status != 0);
139
 
33453 amit.gupta 140
        if (status == 0) {
141
            LOGGER.info("Found invalid captcha");
142
            return;
143
        } else if (status == 2) {
144
            LOGGER.info("Received status 2 for {}, data {}", imei, data);
36253 amit 145
            activatedImeiRepository.saveActivation(imei, null);
33453 amit.gupta 146
            return;
147
        }
29451 manish 148
 
33453 amit.gupta 149
        JSONObject imeiQueryDto = data.getJSONObject("imeiQueryDto");
150
        LOGGER.info("imeiQueryDto - {}", imeiQueryDto);
151
        String dueTimeString = imeiQueryDto.getString("dueTime");
29466 amit.gupta 152
 
36253 amit 153
        if (dueTimeString.equals("")) {
154
            activatedImeiRepository.saveActivation(imei, null);
155
            return;
33453 amit.gupta 156
        }
29469 amit.gupta 157
 
33453 amit.gupta 158
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
159
        dueTimeString = dueTimeString.split(" ")[0];
160
        LocalDate dueDate = LocalDate.parse(dueTimeString, formatter);
30343 amit.gupta 161
 
36253 amit 162
        activatedImeiRepository.saveActivation(imei, dueDate.atStartOfDay().minusYears(1));
163
        LOGGER.info("activatedImei saved for {} with dueDate {}", imei, dueDate.atStartOfDay());
33453 amit.gupta 164
    }
36253 amit 165
}