Adgoal.php 7.94 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
<?php

namespace App\Models;

use Cache;
use Illuminate\Support\Facades\Redis;
use Log;
use Request;
use LaravelLocalization;

class Adgoal
{
13
14
15
16
17
18
19
20
21
22
23
24
25
    const COUNTRIES = [
        "af", "al", "dz", "um", "as", "vi", "ad", "ao", "ai", "ag", "ar", "am", "aw", "az", "au", "eg", "gq", "et", "bs",
        "bh", "bd", "bb", "be", "bz", "bj", "bm", "bt", "bo", "ba", "bw", "bv", "br", "vg", "io", "bn", "bg", "bf", "bi", "cl", "cn", "ck",
        "cr", "ci", "dk", "de", "dm", "do", "dj", "ec", "sv", "er", "ee", "eu", "fk", "fo", "fj", "fi", "fr", "gf", "pf", "tf", "ga", "gm",
        "ge", "gh", "gi", "gd", "gr", "gb", "uk", "gl", "gp", "gu", "gt", "gn", "gw", "gy", "ht", "hm", "hn", "hk", "in", "id", "iq", "ir",
        "ie", "is", "il", "it", "jm", "sj", "jp", "ye", "jo", "yu", "ky", "kh", "cm", "ca", "cv", "kz", "qa", "ke", "kg", "ki", "cc", "co",
        "km", "cg", "cd", "hr", "cu", "kw", "la", "ls", "lv", "lb", "lr", "ly", "li", "lt", "lu", "mo", "mg", "mw", "my", "mv", "ml", "mt",
        "mp", "ma", "mh", "mq", "mr", "mu", "yt", "mk", "mx", "fm", "md", "mc", "mn", "ms", "mz", "mm", "na", "nr", "np", "nc", "nz", "ni",
        "nl", "an", "ne", "ng", "nu", "kp", "nf", "no", "om", "tp", "at", "pk", "pw", "ps", "pa", "pg", "py", "pe", "ph", "pn", "pl", "pt",
        "pr", "re", "rw", "ro", "ru", "st", "sb", "zm", "ws", "sm", "sa", "se", "ch", "sn", "sc", "sl", "zw", "sg", "sk", "si", "so", "es",
        "lk", "sh", "kn", "lc", "pm", "vc", "sd", "sr", "za", "kr", "sz", "sy", "tj", "tw", "tz", "th", "tg", "to", "tt", "td", "cz", "tn",
        "tm", "tc", "tv", "tr", "us", "ug", "ua", "xx", "hu", "uy", "uz", "vu", "va", "ve", "ae", "vn", "wf", "cx", "by", "eh", "ww", "zr", "cf", "cy",
    ];
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40

    public $hash;
    public $finished = false; // Is true when the Request was sent to and read from Admitad App
    private $affiliates = null;
    private $startTime;

    /**
     * Creates a new Adgoal object which will start a request for affiliate links
     * based on a result List from MetaGer.
     * It will parse the Links of the results and query any affiliate shops.
     * 
     * @param \App\MetaGer $metager
     */
    public function __construct(&$metager)
41
    {
42
        $this->startTime = microtime(true);
43
44
        $publicKey = config("metager.metager.adgoal.public_key");
        $privateKey = config("metager.metager.adgoal.private_key");
45
46
47
        if ($publicKey === false) {
            return true;
        }
48
        $results = $metager->getResults();
49
50
51
52
53
        $linkList = "";
        foreach ($results as $result) {
            if (!$result->new) {
                continue;
            }
54
            $link = $result->originalLink;
55
56
57
58
59
            if (strpos($link, "http") !== 0) {
                $link = "http://" . $link;
            }
            $linkList .= $link . ",";
        }
60
        if (empty($linkList)) {
61
62
            return;
        }
63

64
        $linkList = rtrim($linkList, ",");
65

66
        # Hashwert
67
        $this->hash = md5($linkList . $privateKey);
68

69
        $link = "https://xf.gdprvalidate.de/v4/check";
70

71
72
73
74
75
76
77
        # Which country to use
        # Will be de for metager.de and en for metager.org
        $country = "de";
        if (LaravelLocalization::getCurrentLocale() === "en") {
            $country = "us";
        }
        $preferredLanguage = Request::getPreferredLanguage();
78
79
        if (!empty($preferredLanguage)) {
            if (str_contains($preferredLanguage, "_")) {
80
                $preferredLanguage = substr($preferredLanguage, stripos($preferredLanguage, "_") + 1);
81
            } elseif (str_contains($preferredLanguage, "-")) {
82
                $preferredLanguage = substr($preferredLanguage, stripos($preferredLanguage, "-") + 1);
83
            }
84

85
            $preferredLanguage = strtolower($preferredLanguage);
86

87
88
89
            if (in_array($preferredLanguage, self::COUNTRIES)) {
                $country = $preferredLanguage;
            }
90
        }
91

92
        $postfields = [
93
94
95
96
97
98
99
100
            "key" => $publicKey,
            "panel" => "ZMkW9eSKJS",
            "member" => "338b9Bnm",
            "signature" => $this->hash,
            "links" => $linkList,
            "country" => $country,
        ];

101
102
        // Submit fetch job to worker
        $mission = [
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
            "resulthash" => $this->hash,
            "url" => $link,
            "useragent" => "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0",
            "username" => null,
            "password" => null,
            "headers" => [
                "Content-Type" => "application/x-www-form-urlencoded"
            ],
            "cacheDuration" => 60,
            "name" => "Adgoal",
            "curlopts" => [
                CURLOPT_POST => true,
                CURLOPT_POSTFIELDS => \http_build_query($postfields)
            ]
        ];
118
119
120
        $mission = json_encode($mission);
        Redis::rpush(\App\MetaGer::FETCHQUEUE_KEY, $mission);
    }
121

122
123
124
    public function fetchAffiliates($wait = false)
    {
        if ($this->affiliates !== null) {
125
            return;
126
        }
127
128
129

        $answer = null;
        $startTime = microtime(true);
130
        if ($wait) {
131
            while (microtime(true) - $startTime < 5) {
132
                $answer = Cache::get($this->hash);
133
134
135
136
137
138
                if ($answer === null) {
                    usleep(50 * 1000);
                } else {
                    break;
                }
            }
139
        } else {
140
            $answer = Cache::get($this->hash);
141
        }
142
        $answer = json_decode($answer, true);
143

144
        // If the fetcher had an Error
145
        if ($answer === "no-result") {
146
147
148
149
            $this->affiliates = [];
            return;
        }

150
        if (empty($answer) && !is_array($answer)) {
151
            return;
152
        }
153

154
155
        $this->affiliates = $answer;
    }
156

157
158
159
160
161
162
163
    /**
     * Converts all Affiliate Links.
     * 
     * @param \App\Models\Result[] $results
     */
    public function parseAffiliates(&$results)
    {
164
        if ($this->finished || $this->affiliates === null) {
165
166
            return;
        }
167

168
169
        foreach ($this->affiliates as $partnershop) {
            $targetUrl = $partnershop["url"];
170

171
            $tld = $partnershop["tld"];
172
173

            // Sometimes TLD is null
174
            if (empty($tld)) {
175
176
177
                continue;
            }

178
            $targetHost = parse_url($targetUrl, PHP_URL_HOST);
179

180
181
182
183
            /*
                Adgoal sometimes returns affiliate Links for every URL
                That's why we check if the corresponding TLD matches the orginial URL
            */
184
            if ($targetHost !== false && stripos($targetHost, $tld) === false) {
185
186
187
188
189
190
                continue;
            }
            $preference = config("metager.metager.affiliate_preference", "adgoal");
            foreach ($results as $result) {
                if ($result->originalLink === $targetUrl && (config("metager.metager.affiliate_preference", "adgoal") === "adgoal" || !$result->partnershop)) {
                    # Ein Advertiser gefunden
191
192
193
194
195
                    # Check ob er auf der Blacklist steht
                    if (Redis::hexists(\App\Http\Controllers\AdgoalController::REDIS_BLACKLIST_KEY, $targetHost)) {
                        continue;
                    }

196
197
198
199
                    if ($result->image !== "" && !$result->partnershop) {
                        $result->logo = $partnershop["logo"];
                    } else {
                        $result->image = $partnershop["logo"];
200
                    }
201
202

                    # Den Link hinzufügen:
Dominik Hebeler's avatar
Dominik Hebeler committed
203
204
205
206
                    # Redirect the user over our tracker
                    # see \App\Http\Controllers\AdgoalController 
                    # for more information
                    $result->link = \App\Http\Controllers\AdgoalController::generateRedirectUrl($partnershop["click_url"], $targetUrl);
207
208
                    $result->partnershop = true;
                    $result->changed = true;
209
210
211
                }
            }
        }
212

213
214
215
        $requestTime = microtime(true) - $this->startTime;
        \App\PrometheusExporter::Duration($requestTime, "adgoal");
        $this->finished = true;
216
217
    }
}