34 QUrl URLFromClientID (
const QString&
id,
const QStringList& scope)
36 auto url = QUrl::fromEncoded (
"https://oauth.vk.com/authorize?redirect_uri=http%3A%2F%2Foauth.vk.com%2Fblank.html&response_type=token&state=");
38 (QStringLiteral (
"client_id"), id)
39 (QStringLiteral (
"scope"), scope.join (
','));
45 const QString&
id,
const QStringList& scope,
50 , AccountHR_ (accName)
51 , AuthNAM_ (new QNetworkAccessManager (this))
55 , URL_ (URLFromClientID (ID_, scope))
56 , ScheduleTimer_ (new QTimer (this))
58 AuthNAM_->setCookieJar (Cookies_);
59 Cookies_->Load (cookies);
61 ScheduleTimer_->setSingleShot (
true);
62 connect (ScheduleTimer_,
67 IsRequestScheduled_ =
false;
76 return !Token_.isEmpty () &&
77 (!ValidFor_ || ReceivedAt_.secsTo (QDateTime::currentDateTime ()) < ValidFor_);
82 return !Token_.isEmpty () || !Cookies_->allCookies ().isEmpty ();
87 const auto& newUrl = URLFromClientID (ID_, scope);
93 ReceivedAt_ = QDateTime ();
105 for (
const auto& queue : PrioManagedQueues_)
107 for (
const auto& queue : ManagedQueues_)
114 InvokeQueues (Token_);
120 QFutureInterface<AuthKeyResult_t> iface;
121 iface.reportStarted ();
130 [
this, iface] ()
mutable { ReportFutureResult (iface, Token_); });
134 return iface.future ();
141 qWarning () << Q_FUNC_INFO
142 <<
"cannot manage request queue if queue manager wasn't set";
146 ManagedQueues_ << queue;
155 qWarning () << Q_FUNC_INFO
156 <<
"cannot manage request queue if queue manager wasn't set";
160 PrioManagedQueues_ << queue;
167 SilentMode_ = silent;
170 void VkAuthManager::InvokeQueues (
const QString& token)
172 ScheduleTrack (token);
174 for (
auto queue : PrioManagedQueues_)
175 while (!queue->isEmpty ())
177 const auto& pair = queue->takeFirst ();
178 const auto& f = pair.first;
179 Queue_->
Schedule ([f, token] { f (token); },
nullptr, pair.second);
182 for (
auto queue : ManagedQueues_)
183 while (!queue->isEmpty ())
185 const auto& f = queue->takeFirst ();
186 Queue_->
Schedule ([f, token] { f (token); });
190 void VkAuthManager::RequestURL (
const QUrl& url)
192 qDebug () << Q_FUNC_INFO << url;
193 auto reply = AuthNAM_->get (QNetworkRequest (url));
195 &QNetworkReply::finished,
197 [
this, reply] { HandleGotForm (reply); });
200 void VkAuthManager::RequestAuthKey ()
202 if (IsRequestScheduled_ && ScheduleTimer_->isActive ())
203 ScheduleTimer_->stop ();
209 IsRequesting_ =
true;
212 bool VkAuthManager::CheckReply (QUrl location)
214 if (location.path () !=
"/blank.html"_ql)
215 return CheckError (location);
217 location = QUrl::fromEncoded (location.toEncoded ().replace (
'#',
'?'));
218 const QUrlQuery query { location };
219 Token_ = query.queryItemValue (QStringLiteral (
"access_token"));
220 ValidFor_ = query.queryItemValue (QStringLiteral (
"expires_in")).toInt ();
221 ReceivedAt_ = QDateTime::currentDateTime ();
222 qDebug () << Q_FUNC_INFO << Token_ << ValidFor_;
223 IsRequesting_ =
false;
225 InvokeQueues (Token_);
232 bool VkAuthManager::CheckError (
const QUrl& url)
234 if (url.path () !=
"/error"_ql)
237 const auto errNum = QUrlQuery { url }.queryItemValue (QStringLiteral (
"err")).toInt ();
239 IsRequesting_ =
false;
241 qWarning () << Q_FUNC_INFO
253 tr (
"VK.com authentication for %1 failed because of error %2. "
254 "Report upstream please.")
258 Proxy_->GetEntityManager ()->HandleEntity (e);
263 void VkAuthManager::ScheduleTrack (
const QString& key)
268 if (!Proxy_->GetSettingsManager ()->property (
"TrackVK").toBool ())
273 QUrl url { QStringLiteral (
"https://api.vk.com/method/stats.trackVisitor") };
274 Util::UrlOperator { url }
275 (QStringLiteral (
"access_token"), key);
277 auto reply = AuthNAM_->get (QNetworkRequest { url });
279 &QNetworkReply::finished,
281 &QNetworkReply::deleteLater);
288 ReceivedAt_ = QDateTime ();
295 class CloseEventFilter :
public QObject
299 CloseEventFilter (
const F& handler, QObject *handlee)
300 : QObject { handlee }
301 , Handler_ { handler }
303 handlee->installEventFilter (
this);
306 bool eventFilter (QObject*, QEvent *event)
override
308 if (event->type () == QEvent::Close)
317 const auto& browsers = Proxy_->GetPluginsManager ()->GetAllCastableTo<
IWebBrowser*> ();
318 if (browsers.isEmpty ())
321 tr (
"Could not authenticate %1 since authentication requires a browser plugin. "
322 "Consider installing one like Poshuku.")
325 Proxy_->GetEntityManager ()->HandleEntity (e);
333 viewWidget->setWindowTitle (tr (
"VK.com authentication for %1")
335 viewWidget->setWindowFlags (Qt::Window);
336 viewWidget->resize (800, 600);
339 Browser_->Load (URL_);
341 SIGNAL (urlChanged (
const QUrl&)),
343 SLOT (handleUrlChanged (
const QUrl&)));
345 new CloseEventFilter { [
this] { emit
authCanceled (); }, viewWidget };
348 void VkAuthManager::HandleGotForm (QNetworkReply *reply)
350 reply->deleteLater ();
352 if (reply->error () != QNetworkReply::NoError &&
353 reply->error () != QNetworkReply::AuthenticationRequiredError)
355 qWarning () << Q_FUNC_INFO
357 << reply->errorString ();
359 IsRequesting_ =
false;
361 if (!IsRequestScheduled_)
363 IsRequestScheduled_ =
true;
364 ScheduleTimer_->start (30000);
370 const auto& location = reply->header (QNetworkRequest::LocationHeader).toUrl ();
371 if (location.isEmpty ())
377 if (CheckReply (location))
380 RequestURL (location);
383 void VkAuthManager::handleUrlChanged (
const QUrl& url)
385 if (!CheckReply (url))
VkAuthManager(const QString &accountName, const QString &clientId, const QStringList &scope, const QByteArray &cookies, const ICoreProxy_ptr &, QueueManager *=nullptr, QObject *=nullptr)