Doesn't seem like iTunes connect has basic exporting of user emails from Prerelease > External testers
Needed to export emails to CSV
Does anyone have a script or workaround solution?
Thanks!
You can use pilot (from Fastlane) to do that :
To export in a CSV file: fastlane pilot export
$ fastlane pilot list
+--------+--------+--------------------------+-----------+
| Internal Testers |
+--------+--------+--------------------------+-----------+
| First | Last | Email | # Devices |
+--------+--------+--------------------------+-----------+
| Felix | Krause | felix#krausefx.com | 2 |
+--------+--------+--------------------------+-----------+
+-----------+---------+----------------------------+-----------+
| External Testers |
+-----------+---------+----------------------------+-----------+
| First | Last | Email | # Devices |
+-----------+---------+----------------------------+-----------+
| Max | Manfred | email#email.com | 0 |
| Detlef | Müller | detlef#krausefx.com | 1 |
+-----------+---------+----------------------------+-----------+
Just use console get Email, First Name, Last Name
Paste this into console
https://gist.github.com/creaoy/80d1092283a5d0fa1070
Upon trial and error (because I'm desperate), I found a way out, the low tech way.
Go to Activity > iOS History > All Builds > Testers
This is the page where you see all of your external and internal testers' emails, name, status, sessions, crashes and devices. Select all rows and paste them into excel. It will display all information in each cell nicely :) Select the first column in excel and you have all the emails only.
I expanded creaoy's script to include the Status (Notified/Installed x.xx). Still works for me today.
Scroll all the way down so all testers are loaded. Then paste this in Safari's error console and hit enter.
var text = '';
$('.col-email').each(function(index,el) {
if (index == 0) {
text = 'Email, First Name, Last Name, Status\n';
}
else {
//Email
text = text + $.trim($(el).find("a").text()) + ',';
//First Name
text = text + $.trim($($($($('.col-name')[index]).find("span")[0]).find("span")[0]).text()) + ',';
//Last Name
text = text + $.trim($($($($('.col-name')[index]).find("span")[0]).find("span")[1]).text()) + ',';
//Status
text = text + $.trim($($($($('.col-status')[index]).find("div")[0]).find("span")[0]).text()) + '\n';
}
});
var a = document.createElement("a");
var file = new Blob([text], {type: 'text/csv'});
a.href = URL.createObjectURL(file);
a.download = name; a.click();
Not as yet. You can only import a csv file but not create one from the users there.
You can copy the rows, edit them in TextEdit/Notepad in the format:
fistname,lastname,email
and save that as csv to use when you want to import those emails later.
It would be good if they implemented it to do this automatically, or at least having the option to send the updates to specific groups that you can create.
I made a little console hack that extracts just the emails. Improve to your liking :-)
https://gist.github.com/larsparendt/a67d25b1611db67ba67b
Some great answers, but wanted to add another option. BoardingBot is a tool that lets you send TestFlight invites automatically, as well as emails to your beta testers. So this might fill your need for contacting your beta testers.
Disclaimer: I'm the founder of BoardingBot :)
Since iTunes Connect is now an angular app, many of the answers on this page no longer work. However if you have the Angular/Batarang extension for Chrome you can paste this script in the console (cmd+i) and it will spit out a csv. Note that first you have to inspect an item in the list (cmd + shift + c) to get a reference to $scope. Also don't forget to scroll down to make the page auto-load the whole list.
var text = '';
angular.forEach($scope.filteredTesters, function(val) {
text += val.firstName.value + ',';
text += val.lastName.value + ',';
text += val.emailAddress.value + '\n';
});
var a = document.createElement("a");
var file = new Blob([text], {type: 'text/csv'});
a.href = URL.createObjectURL(file);
a.download = name; a.click();
Edit:
The below method is flakey - there is a great ruby gem for managing testflight testers called Fastlane pilot. I woudl recommend looking into that instead: https://github.com/fastlane/fastlane/tree/master/pilot
Found a google chrome extension that will do the job:
Table capture:https://chrome.google.com/webstore/detail/table-capture/iebpjdmgckacbodjpijphcplhebcmeop/reviews?hl=en
Also needed to filter out duplicates, which can be done using Google spreadsheets
If you just need the emails and have a text editor with regex replacement you can do this
Scroll to the bottom of the list in itunesconnect so you get all rows
Copy all the rows into text editor of your choice (I used sublime text)
replace ^.*\n\n with <empty string>. This removes all names
replace \n\s\n with ,.
replace \n with ,.
and you're left with a CSV of all the emails
if like me you also needed the date this is the code you need:
var text = '';
$('.col-email').each(function(index,el) {
if (index == 0) {
text = 'Email, First Name, Last Name, Status, Date\n';
}
else {
//Email
text = text + $.trim($(el).find("a").text()) + ',';
//First Name
text = text + $.trim($($($($('.col-name')[index]).find("span")[0]).find("span")[0]).text()) + ',';
//Last Name
text = text + $.trim($($($($('.col-name')[index]).find("span")[0]).find("span")[1]).text()) + ',';
//Status
text = text + $.trim($($($($('.col-status')[index]).find("div")[0]).find("span")[0]).text()) + ',';
//Date
text = text + '\"' + $.trim($($($($('.col-status')[index]).find("div")[0]).find("span")[2]).text()) + '\"\n';
}
});
var a = document.createElement("a");
var file = new Blob([text], {type: 'text/csv'});
a.href = URL.createObjectURL(file);
a.download = name; a.click();
I came up with a jQuery solution to output this data to the console in CSV format. It is dependent on the way that the pages selectors are set up but as of now (Sep. 2017), it runs great.
Open up the console on your browser (I use Chrome), copy and paste this code in, hit enter. Quick and dirty.
Edit
I borrowed some code from guido's answer here that triggers an automatic download after hitting enter.
output = "email,first name,last name\n";
jQuery('table.table-itc-testers tr[ng-repeat*="itcUser"]').each(function(){
row = [];
//Email Address
row.push(jQuery(this).find('span a[href*="users_roles"]').text());
// First and last name
full_name = jQuery(this).find('td.sorted > span:not(.ng-hide)');
// If only name is filled out
if(full_name==""){
row.push("");
row.push("");
} else {
row.push(full_name.clone().children().remove().end().text().trim());
row.push(full_name.find('span.lastname').text());
}
output += row.join(",") + "\n";
});
var a = document.createElement("a");
var file = new Blob([output], {type: 'text/csv'});
a.href = URL.createObjectURL(file);
a.download = 'external_testers.csv'; a.click();
Quick Update with a new answer: iTunes Connect now has an easy-to-use download button on the right side of the page!
Related
Basically I've used Google Sheets to create an invoice tracker, and I want to send a reminder email to each of my clients when their invoice is due. I've already set the date and the count down, and now I want to send them the reminder email when the cell value reaches "2" meaning 32 days has passed since I've invoiced them.
I've gathered the codes from different sources online, and also I've set a 24 hr trigger to run the code once in a day. The email template is also in place. Data of each client (dates, names, addresses, etc.) are listed in separate rows.
My problem is that instead of sending 1 single email to the right client, the mailing app sends emails to all clients when any of them have a due invoice!
I'm not sure which function or code I should use.
I tried 'Email_Sent' thing, but couldn't get anywhere good with it!
function CheckMaturity() {
// Fetch invoice maturity
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('InvoiceTracker').activate();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
for (var i = 5;i<=10;i++){
var invoiceMaturityRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('InvoiceTracker').getRange(i, 13);
var invoiceMaturity = invoiceMaturityRange.getValue();
// Check invoice maturity
if (invoiceMaturity = 2){
// Fetch the email address
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('InvoiceTracker').activate();
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('EmailTemplate').getRange(1,1).getValue();
var currentAddress = ss.getRange(i, 15).getValue();
var currentInvoiceNo = ss.getRange(i, 3).getValue();
var currentInvoiceDate = ss.getRange(i, 4).getValue();
var currentClient = ss.getRange(i, 14).getValue();
var messageBody = templateText.replace('{client}',currentClient).replace('{invoiceNo}',currentInvoiceNo).replace('{invoiceDate}', currentInvoiceDate);
var subjectLine = 'Kind reminder - Invoice status';
MailApp.sendEmail(currentAddress, subjectLine, messageBody);{
SpreadsheetApp.getActiveSpreadsheet().toast('Invoice reminder sent to' +currentClient, 'Reminder sent', -1);
}
}
}
}
I want the app to send only one single email to the right (relevant) client.
I think you need the below. Please check the variables and references. The following code should be adjusted. The column 'A' should be replaced with the column in which you have the last record to prevent that you miss any clients. Furthermore, please check the comments in the code below.
.Range("A1047854").End(xlUp).Row
And hereby the full code:
Sub SendEmails()
Dim myOlApp As Outlook.Application, MailItem As Outlook.MailItem
Dim attachmentPath1 As String, attachmentPath2 As String
Set myOlApp = CreateObject("Outlook.Application")
'loop through a sheet (change index)
For i = 1 To ThisWorkbook.Sheets("index").Range("A1047854").End(xlUp).Row
'set key for check (or just do it directly in the if)
invoiceMaturity = ThisWorkbook.Sheets("index").Range("A" & i).Value
If invoiceMaturity = "2" Then
'you can load the variables first, before adding them to the email, or add them directly.
Name = ""
MailAddress = ""
Address = ""
currentInvoiceNo = ""
currentInvoiceDate = ""
currentClient = ""
'make item for each iteration (again)
Set MailItem = myOlApp.CreateItem(olMailItem)
'attachments
attachmentPath1 = "path/to/file.something" 'or set to ""(nothing)
'body
MailItem.HTMLBody = "<B>" & "<h3>" & "DRAFT:" & "</h3>" & "</B>" & "<br>" & _
"Dear, " & "<br>" & "<br>" & _
"Please find enclosed a kind reminder.." & "<br>" & "<br>" & _
"Please note, that.." & "</b>" & "<br>" & "<br>" & _
"Should you have any questions or comments on the above, please do let us know." & "<br>" & "<br>" & _
"Kind regards," & "<br>" & "<br>" & _
"Signature"
MailItem.to = MailAddress 'adjust email
MailItem.Subject = "[subject of email" & "a variable?" 'adjust subject
MailItem.Show 'or mailitem.send
'just to make sure
Set MailItem = ""
End If
Next i
End Sub
I'm using the Perl6 Terminal::Print module for a console based application.
It's working well - however, now I need to prompt the user for a string of text.
What's a good way to do this?
Here is an example of using Terminal::Print::RawInput to get a filename as user input:
use v6;
use Terminal::Print;
use Terminal::Print::RawInput;
my $screen = Terminal::Print.new;
# saves current screen state, blanks screen, and hides cursor
$screen.initialize-screen;
$screen.print-string(9, 23, "Enter filename: ");
my $in-supply = raw-input-supply;
my $filename;
react {
whenever $in-supply -> $c {
done if $c.ord ~~ 3|13; # Enter pressed or CTRL-C pressed
my $char = $c.ord < 32 ?? '' !! $c;
$filename ~= $char;
print $char;
}
}
sleep .1;
$screen.shutdown-screen;
say "Filename entered: '$filename'";
Hi all I am haveing a problem geting a formula into google sheet using script editor. I can get one in that doesn´t work but not one that does.
This one will put the formula in but the formula doesn´t work
function x1() {
var ss3 = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
ss3.getRange("AF2").setFormula("=IF((AND(OR(I2='YOUR TRIP DWL',I2='MEGA PACK DWL (YT + AA + BONUS)'),L2<=0,AD2<>'')),'Send Email', 'Wait')")
var lr3 = ss3. getLastRow();
var filldownrange3 = ss3.getRange(2, 32, lr3-1);
ss3. getRange("AF2").copyTo(filldownrange3);
}
This one shows an Error in script editor but the furmula work in the cells i manually placed in.
function x1() {
var ss3 = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
ss3.getRange("AF2").setFormula("=IF(((AND(OR(I2="YOUR TRIP DWL",I2="MEGA PACK DWL (YT + AA + BONUS)"),M2<=0,AA2<>"",AE2<>""))), "Send Email", "Wait")")
var lr3 = ss3. getLastRow();
var filldownrange3 = ss3.getRange(2, 32, lr3-1);
ss3. getRange("AF2").copyTo(filldownrange3);
The problem is Line 3 with the formula itself as other fumulas are ok, can anyone shed some light on this, Thanks in advance,
I suggest you try your second version with escaping of the internal double quotes.
IF this hels anyone else with the same problem, I have finally solved this problem by changing the double quotes surounding the formula with single quptes and leaving the double quotes inside the formula, so line 4 reads:
ss3.getRange("AF2").setFormula('=IF(((AND(OR(I2="YOUR TRIP DWL",I2="MEGA PACK DWL (YT + AA + BONUS)"),M2<=0,AA2<>"",AE2<>""))), "Send Email", "Wait")');
I have this code, it suppose to get info from external source, send message back to this source asking for desired action and then analyze this response, if the response have '#' in the text, it will write "closed" in some specific cell and then send message that confirm this action.
eventually, it never worked. the first message is sent, but the second message - not. and also the specific cell is not changing.
how can i know where is my problem?
function doPost(e)
{
var contents = JSON.parse(e.postData.contents);
var text = contents.message.text;
var id = contents.message.from.id;
var name = contents.message.from.first_name + " " +
contents.message.from.last_name;
sendText(id, 'Hi ' + name ,' please send your needed action'); //till here, everything works great
if (/^#/.test(text))
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("ServiceC");
SpreadsheetApp.setActiveSheet(sheet);
var getCallID = text.slice(1).split(" ")[0];
getCallID = parseInt(getCallID,10);
var cellToEdit = 'K' + (getCallID + 8) ;
sheet.getRange(cellToEdit).setValue("close");
sendText(id, 'now its closed');
}
Ok i got it ! the text slicing was wrong. i fixed it and it's working like a charm!
I would like to get efficient way of working with Strings in Qt. Since I am new in Qt environment.
So What I am doing:
I am loading a text file, and getting each lines.
Each line has text with comma separated.
Line schema:
Fname{limit:list:option}, Lname{limit:list:option} ... etc.
Example:
John{0:0:0}, Lname{0:0:0}
Notes:limit can be 1 or 0 and the same as others.
So I would like to get Fname and get limit,list,option values from {}.
I am thinking to write a code with find { and takes what is inside, by reading symbol by symbol.
What is the efficient way to parse that?
Thanks.
The following snippet will give you Fname and limit,list,option from the first set of brackets. It could be easily updated if you are interested in the Lname set as well.
QFile file("input.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
qDebug() << "Failed to open input file.";
QRegularExpression re("(?<name>\\w+)\\{(?<limit>[0-1]):(?<list>[0-1]):(?<option>[0-1])}");
while (!file.atEnd())
{
QString line = file.readLine();
QRegularExpressionMatch match = re.match(line);
QString name = match.captured("name");
int limit = match.captured("limit").toInt();
int list = match.captured("list").toInt();
int option = match.captured("option").toInt();
// Do something with values ...
}