void CyclingAnalyticsUploader::requestUploadCyclingAnalytics() { parent->progressLabel->setText(tr("Upload ride to CyclingAnalytics...")); parent->progressBar->setValue(parent->progressBar->value()+10/parent->shareSiteCount); QEventLoop eventLoop; QNetworkAccessManager networkMgr; connect(&networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestUploadCyclingAnalyticsFinished(QNetworkReply*))); connect(&networkMgr, SIGNAL(finished(QNetworkReply *)), &eventLoop, SLOT(quit())); QUrl url = QUrl( "https://www.cyclinganalytics.com/api/me/upload" ); QNetworkRequest request = QNetworkRequest(url); QString boundary = QVariant(qrand()).toString()+QVariant(qrand()).toString()+QVariant(qrand()).toString(); TcxFileReader reader; QByteArray file = reader.toByteArray(context, ride->ride(), parent->altitudeChk->isChecked(), parent->powerChk->isChecked(), parent->heartrateChk->isChecked(), parent->cadenceChk->isChecked()); // MULTIPART ***************** QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); multiPart->setBoundary(boundary.toLatin1()); request.setRawHeader("Authorization", (QString("Bearer %1").arg(token)).toLatin1()); QHttpPart activityNamePart; activityNamePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"title\"")); activityNamePart.setBody(QString(parent->titleEdit->text()).toLatin1()); QHttpPart dataTypePart; dataTypePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"format\"")); dataTypePart.setBody("tcx"); QHttpPart filenamePart; filenamePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"filename\"")); filenamePart.setBody("file.tcx"); QHttpPart filePart; filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"data\"; filename=\"file.tcx\"; type=\"text/xml\"")); filePart.setBody(file); multiPart->append(activityNamePart); multiPart->append(filenamePart); multiPart->append(dataTypePart); multiPart->append(filePart); QScopedPointer<QNetworkReply> reply( networkMgr.post(request, multiPart) ); multiPart->setParent(reply.data()); parent->progressBar->setValue(parent->progressBar->value()+30/parent->shareSiteCount); parent->progressLabel->setText(tr("Upload ride... Sending to CyclingAnalytics")); eventLoop.exec(); }
/* make a multipart HTTP POST at the following path "/restapi/public/activities/upload.json" on selflloops web site using SSL. The requested parameters are: - "email" the email of a valid SelfLoops account - "pw" the password - "tcxfile" the zipped TCX file (example: test.tcx.gz). On success, response message contains a JSON encoded data with the new "activity_id" created. On error, SelfLoops response contains a JSON encoded data with "error_code" and "message" key. */ void SelfLoopsUploader::requestUploadSelfLoops() { parent->progressLabel->setText(tr("Upload ride to Selfloops...")); parent->progressBar->setValue(parent->progressBar->value()+10/parent->shareSiteCount); QEventLoop eventLoop; QNetworkAccessManager networkMgr; connect(&networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestUploadSelfLoopsFinished(QNetworkReply*))); connect(&networkMgr, SIGNAL(finished(QNetworkReply *)), &eventLoop, SLOT(quit())); QUrl url = QUrl( "https://www.selfloops.com/restapi/public/activities/upload.json" ); QNetworkRequest request = QNetworkRequest(url); QString boundary = QVariant(qrand()).toString()+QVariant(qrand()).toString()+QVariant(qrand()).toString(); // The TCX file have to be gzipped TcxFileReader reader; QByteArray file = zCompress(reader.toByteArray(context, ride->ride(), parent->altitudeChk->isChecked(), parent->powerChk->isChecked(), parent->heartrateChk->isChecked(), parent->cadenceChk->isChecked())); QString username = appsettings->cvalue(context->athlete->cyclist, GC_SELUSER).toString(); QString password = appsettings->cvalue(context->athlete->cyclist, GC_SELPASS).toString(); // MULTIPART ***************** QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::MixedType); multiPart->setBoundary(boundary.toLatin1()); QHttpPart emailPart; emailPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"email\"")); emailPart.setBody(username.toLatin1()); QHttpPart passwordPart; passwordPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"pw\"")); passwordPart.setBody(password.toLatin1()); QHttpPart filePart; filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"tcxfile\"; filename=\"myfile.tcx.gz\"; type=\"application/x-gzip\"")); filePart.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-gzip"); filePart.setBody(file); multiPart->append(emailPart); multiPart->append(passwordPart); multiPart->append(filePart); QScopedPointer<QNetworkReply> reply( networkMgr.post(request, multiPart) ); multiPart->setParent(reply.data()); parent->progressBar->setValue(parent->progressBar->value()+30/parent->shareSiteCount); parent->progressLabel->setText(tr("Upload ride... Sending to Selfloops")); eventLoop.exec(); }
void SportPlusHealthUploader::requestUpload() { parent->progressLabel->setText(tr("sending to SportPlusHealth...")); parent->progressBar->setValue(parent->progressBar->value()+10/parent->shareSiteCount); QString username = appsettings->cvalue(context->athlete->cyclist, GC_SPORTPLUSHEALTHUSER).toString(); QString password = appsettings->cvalue(context->athlete->cyclist, GC_SPORTPLUSHEALTHPASS).toString(); //Building the message content QHttpMultiPart *body = new QHttpMultiPart( QHttpMultiPart::FormDataType ); //Including the optional session name QHttpPart textPart; textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"session_name\"")); textPart.setBody(QByteArray(insertedName.toLatin1())); body->append(textPart); //Including the content data type QHttpPart dataTypePart; dataTypePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"format\"")); dataTypePart.setBody("tcx"); body->append(dataTypePart); //Including file in the request TcxFileReader reader; QByteArray file = reader.toByteArray(context, ride->ride(), parent->altitudeChk->isChecked(), parent->powerChk->isChecked(), parent->heartrateChk->isChecked(), parent->cadenceChk->isChecked()); QHttpPart filePart; filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"datafile\"; filename=\"sph_file.tcx\"; type=\"text/xml\"")); filePart.setBody(file); body->append(filePart); //Sending the authenticated post request to the API parent->progressBar->setValue(parent->progressBar->value()+20/parent->shareSiteCount); QUrl url(SPH_URL + "/" + username + "/importGC"); QNetworkRequest request; request.setUrl(url); request.setRawHeader("Authorization", "Basic " + QByteArray(QString("%1:%2").arg(username).arg(password).toLatin1()).toBase64()); networkMgr.post(request, body); parent->progressBar->setValue(parent->progressBar->value()+10/parent->shareSiteCount); }
int RideImportWizard::process() { // set progress bar limits - for each file we // will make 5 passes over the files // 1. checking it is a file ane readable // 2. parsing it with the RideFileReader // 3. [optional] collect date/time information from user // 4. copy file into Library // 5. Process for CPI (not implemented yet) // So, therefore the progress bar runs from 0 to files*4. (since step 5 is not implemented yet) progressBar->setMinimum(0); progressBar->setMaximum(filenames.count()*4); // Pass one - Is it valid? phaseLabel->setText(tr("Step 1 of 4: Check file permissions")); for (int i=0; i < filenames.count(); i++) { // get fullpath name for processing QFileInfo thisfile(filenames[i]); if (thisfile.exists() && thisfile.isFile() && thisfile.isReadable()) { // is it one we understand ? QStringList suffixList = RideFileFactory::instance().suffixes(); QRegExp suffixes(QString("^(%1)$").arg(suffixList.join("|"))); suffixes.setCaseSensitivity(Qt::CaseInsensitive); if (suffixes.exactMatch(thisfile.suffix())) { // Woot. We know how to parse this baby tableWidget->item(i,5)->setText(tr("Queued")); } else { tableWidget->item(i,5)->setText(tr("Error - Unknown file type")); } } else { // Cannot open tableWidget->item(i,5)->setText(tr("Error - Not a valid file")); } progressBar->setValue(progressBar->value()+1); } QApplication::processEvents(); if (aborted) { done(0); } repaint(); // Pass 2 - Read in with the relevant RideFileReader method phaseLabel->setText(tr("Step 2 of 4: Validating Files")); for (int i=0; i< filenames.count(); i++) { // does the status say Queued? if (!tableWidget->item(i,5)->text().startsWith(tr("Error"))) { QStringList errors; QFile thisfile(filenames[i]); tableWidget->item(i,5)->setText(tr("Parsing...")); tableWidget->setCurrentCell(i,5); QApplication::processEvents(); if (aborted) { done(0); } this->repaint(); QList<RideFile*> rides; RideFile *ride = RideFileFactory::instance().openRideFile(mainWindow, thisfile, errors, &rides); // is this an archive of files? if (rides.count() > 1) { int here = i; // remove current filename from state arrays and tableview filenames.removeAt(here); blanks.removeAt(here); tableWidget->removeRow(here); // resize dialog according to the number of rows we expect int willhave = filenames.count() + rides.count(); resize(920 + ((willhave > 16 ? 24 : 0) + (willhave > 9 && willhave < 17) ? 8 : 0), 118 + (willhave > 16 ? 17*20 : (willhave+1) * 20)); // ok so create a temporary file and add to the tableWidget int counter = 0; foreach(RideFile *extracted, rides) { // write as a temporary file, using the original // filename with "-n" appended QString fulltarget = QDir::tempPath() + "/" + QFileInfo(thisfile).baseName() + QString("-%1.tcx").arg(counter+1); TcxFileReader reader; QFile target(fulltarget); reader.writeRideFile(mainWindow, extracted, target); deleteMe.append(fulltarget); delete extracted; // now add each temporary file ... filenames.insert(here, fulltarget); blanks.insert(here, true); // by default editable tableWidget->insertRow(here+counter); QTableWidgetItem *t; // Filename t = new QTableWidgetItem(); t->setText(fulltarget); t->setFlags(t->flags() & (~Qt::ItemIsEditable)); tableWidget->setItem(here+counter,0,t); // Date t = new QTableWidgetItem(); t->setText(tr("")); t->setFlags(t->flags() | Qt::ItemIsEditable); t->setBackgroundColor(Qt::red); tableWidget->setItem(here+counter,1,t); // Time t = new QTableWidgetItem(); t->setText(tr("")); t->setFlags(t->flags() | Qt::ItemIsEditable); tableWidget->setItem(here+counter,2,t); // Duration t = new QTableWidgetItem(); t->setText(tr("")); t->setFlags(t->flags() & (~Qt::ItemIsEditable)); tableWidget->setItem(here+counter,3,t); // Distance t = new QTableWidgetItem(); t->setText(tr("")); t->setFlags(t->flags() & (~Qt::ItemIsEditable)); tableWidget->setItem(here+counter,4,t); // Import Status t = new QTableWidgetItem(); t->setText(tr("")); t->setFlags(t->flags() & (~Qt::ItemIsEditable)); tableWidget->setItem(here+counter,5,t); counter++; tableWidget->adjustSize(); QApplication::processEvents(); } // progress bar needs to adjust... progressBar->setMaximum(filenames.count()*4); // then go back one and re-parse from there rides.clear(); i--; goto next; // buttugly I know, but count em across 100,000 lines of code }
if (heartrateChk->isChecked()) out += ", \"heartrate\""; out += "]}"; QUrl url = QUrl(STRAVA_URL2 + "/upload"); QNetworkRequest request = QNetworkRequest(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); progressBar->setValue(40); progressLabel->setText(tr("Upload ride... Sending")); networkMgr.post( request, out.toAscii()); } else { QByteArray data; QUrl params; TcxFileReader reader; params.addQueryItem("token", token); params.addQueryItem("type", "tcx"); params.addQueryItem("data", reader.toByteArray(mainWindow, ride->ride(), altitudeChk->isChecked(), powerChk->isChecked(), heartrateChk->isChecked(), cadenceChk->isChecked())); data = params.encodedQuery(); QUrl url = QUrl(STRAVA_URL2 + "/upload"); QNetworkRequest request = QNetworkRequest(url); request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded"); progressBar->setValue(40); progressLabel->setText(tr("Upload ride... Sending")); networkMgr.post( request, data); }
// Documentation is at: // https://strava.pbworks.com/w/page/39241255/v2%20upload%20create void StravaUploader::requestUploadStrava() { parent->progressLabel->setText(tr("Upload ride to Strava...")); parent->progressBar->setValue(parent->progressBar->value()+10/parent->shareSiteCount); QEventLoop eventLoop; QNetworkAccessManager networkMgr; int year = ride->fileName.left(4).toInt(); int month = ride->fileName.mid(5,2).toInt(); int day = ride->fileName.mid(8,2).toInt(); int hour = ride->fileName.mid(11,2).toInt(); int minute = ride->fileName.mid(14,2).toInt();; int second = ride->fileName.mid(17,2).toInt();; QDate rideDate = QDate(year, month, day); QTime rideTime = QTime(hour, minute, second); QDateTime rideDateTime = QDateTime(rideDate, rideTime); connect(&networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestUploadStravaFinished(QNetworkReply*))); connect(&networkMgr, SIGNAL(finished(QNetworkReply *)), &eventLoop, SLOT(quit())); TcxFileReader reader; QUrl url = QUrl( "https://www.strava.com/api/v3/uploads" ); // The V3 API doc said "https://api.strava.com" but it is not working yet QNetworkRequest request = QNetworkRequest(url); //QString boundary = QString::number(qrand() * (90000000000) / (RAND_MAX + 1) + 10000000000, 16); QString boundary = QVariant(qrand()).toString()+QVariant(qrand()).toString()+QVariant(qrand()).toString(); QByteArray file = reader.toByteArray(context, ride->ride(), parent->altitudeChk->isChecked(), parent->powerChk->isChecked(), parent->heartrateChk->isChecked(), parent->cadenceChk->isChecked()); // MULTIPART ***************** QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); multiPart->setBoundary(boundary.toLatin1()); QHttpPart accessTokenPart; accessTokenPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"access_token\"")); accessTokenPart.setBody(token.toLatin1()); QHttpPart activityTypePart; activityTypePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"activity_type\"")); activityTypePart.setBody("ride"); QHttpPart activityNamePart; activityNamePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"activity_name\"")); activityNamePart.setBody(QString(parent->titleEdit->text()).toLatin1()); QHttpPart dataTypePart; dataTypePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"data_type\"")); dataTypePart.setBody("tcx"); QHttpPart externalIdPart; externalIdPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"external_id\"")); externalIdPart.setBody("Ride"); QHttpPart privatePart; privatePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"private\"")); privatePart.setBody("TRUE"); QHttpPart filePart; filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/xml")); filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"file.tcx\"; type=\"text/xml\"")); filePart.setBody(file); multiPart->append(accessTokenPart); multiPart->append(activityTypePart); multiPart->append(activityNamePart); multiPart->append(dataTypePart); multiPart->append(externalIdPart); multiPart->append(privatePart); multiPart->append(filePart); QScopedPointer<QNetworkReply> reply( networkMgr.post(request, multiPart) ); multiPart->setParent(reply.data()); parent->progressBar->setValue(parent->progressBar->value()+30/parent->shareSiteCount); parent->progressLabel->setText(tr("Upload ride... Sending to Strava")); eventLoop.exec(); }