GAScript - stergere emailuri din GMail folosind un spreadsheet

Va trebuie un cont GMail si in Google Drive va creati un spreadsheet cu denumirea sterge_emailuri si redenumiti sheet cu denumirea fiecare_saptamana.

Folositi  meniu Extensions - App Script pentru a deschide un script nou  si il redenumiti sterge_emailuri_project , adaugati codul sursa de mai jos si salvati pentru a rula:

function batchDeleteEmailSheet() {

  // moveThreadsToTrash() permite doar până la 100 de thread-uri la un moment dat

  var batchSize = 100;


  // Încărcați adresele de email din coloana AA a spreadsheet-ului

  var spreadsheetId = 'ID-ul efectiv al spreadsheet-ului'; // apare in URL spreadsheet-ului : docs.google.com/spreadsheets/d/ID-ul_efectiv_al_spreadsheet-ului/edit#gid=0

  var sheetName = 'fiecare_saptamana ';

  var spreadsheet = SpreadsheetApp.openById(spreadsheetId);

  var sheet = spreadsheet.getSheetByName(sheetName);

  var data = sheet.getRange('A1:' + sheet.getLastRow()).getValues();

  var emailAddresses = data.map(function(row) {

  Logger.log(row[0])

  return row[0]; // Obțineți prima (și singura) valoare din fiecare rând din coloana AA

  });

  // Verificați dacă există date în coloana AA

  // if (!data || data.length === 0) {

  //   Logger.log("Nu există adrese de email în coloana AA.");

  //   return;

  // }


  // Filtrați și curățați adresele de email

  // var emailAddresses = data

  //   .map(function(row) {

  //     return row[0];

  //   })

  //   .filter(function(email) {

  //     return email.trim() !== ""; // Eliminați adresele goale sau cu spații

  //   });


  // Verificați dacă există adrese de email valide

  // if (emailAddresses.length === 0) {

  //   Logger.log("Nu există adrese de email valide în coloana AA.");

  //   return;

  // }


  // Generați query-ul cu adresele de email

  var query = 'label:inbox (' + emailAddresses.join(' OR ') + ')';

  Logger.log("Query: " + query); // Afișați query-ul în jurnalul de stocare


  // Căutați thread-urile pe baza query-ului

  var threads = GmailApp.search(query, 0, 400); // Returnăm mai puțin de 500 de rezultate pentru a evita timeout-uri

 

  // Ștergeți thread-urile în loturi

  for (var j = 0; j < threads.length; j += batchSize) {

    GmailApp.moveThreadsToTrash(threads.slice(j, j + batchSize));

  }

}

In coloana A adaugati mailuri pe fiecare rand, apoi rulati in editor functia batchDeleteEmailSheet .

Exemplu:

noreply@projects.blender.org

nouveau@lists.freedesktop.org

newsletter@news.altex.ro

news@mail.xing.com

promotion@aliexpress.com

@cel

@domo



Aceast rulaj va deschide o fereastra prin care se cere permisiunea de access la mail.

Eu am folosit un trigger care le sterge automat in functie de prioritati sau durata. 

NOTA: Incercati pentru verificare sa goliti folder Trash si apoi sa verificati daca a ajuns emailurile corect sterse in acest folder.


GAScript - trigger pentru executie functie

In editorul de GAScript aveti in stanga un ceas ce va permite sa creati un trigger care va apela o functie, in acest caz eu am apelat functia de stergere a mailuri-lor batchDeleteEmailSheet.

// Funcție trigger - rulează scriptul la fiecare luni la ora 23:00

function createTrigger() {

  ScriptApp.newTrigger('batchDeleteEmailSheet')

      .timeBased()

      .onWeekDay(ScriptApp.WeekDay.MONDAY)

      .atHour(23)

      .nearMinute(35)

      .create();

}

NOTA: Daca triggerul este functional atunci nu veti avea :


Owned by Last run Deployment Event Function     Error rate 

Me             Oct 9, 2023, 11:19:19 PM Head       Time-based batchDeleteEmailSheet    0%



GAScript - salvarea mailurilor in google drive

In editorul de GAScript creati functia de salvare a mailuri-lor din coloana B , denumita saveEmailBodyToFile.

// Funcție trigger - rulează scriptul la fiecare luni la ora 23:00

function saveEmailBodyToFile() {

  var spreadsheetId = 'ID-ul efectiv al spreadsheet-ului';; // Înlocuiți cu ID-ul efectiv al spreadsheet-ului

  var sheetName = 'fiecare_saptamana';


  // Obține adresele de email din coloana B1 în jos

  var spreadsheet = SpreadsheetApp.openById(spreadsheetId);

  var sheet = spreadsheet.getSheetByName(sheetName);

  var data = sheet.getRange('B1:B' + sheet.getLastRow()).getValues();

  var emailAddresses = data.map(function(row) {

    return row[0];

  });


  // Iterați prin adresele de email și preluați corpul email-ului pentru fiecare

  for (var i = 0; i < emailAddresses.length; i++) {

    var emailAddress = emailAddresses[i];


    // Găsiți emailul în inbox-ul dvs. (puteți adăuga orice altă logică de filtrare a emailurilor)

    var threads = GmailApp.search('from:' + emailAddress, 0, 1);

    if (threads.length > 0) {

      var thread = threads[0];

      var message = thread.getMessages()[0];

      var emailBody = message.getPlainBody(); // Obțineți corpul email-ului


      // Creați un folder pe Google Drive unde să salvați fișierul

      var folder = DriveApp.createFolder('EmailBodies_TriggerDeleteMails');


      // Creați un fișier cu corpul email-ului și salvați-l în folder

      var fileName = 'EmailBody_' + emailAddress.replace('@', '_at_') + '.txt'; // Numele fișierului cu adresa de email

      var file = folder.createFile(fileName, emailBody);


      Logger.log('Corpul email-ului de la ' + emailAddress + ' a fost salvat în fișierul ' + file.getName() + ' în folderul ' + folder.getName());

    }

  }

}

Iata cum apare un astfel de mail salvat in drive cu denumirea EmailBody_mailout_at_maillist.codeproject.com.txt pentru mailul mailout[@]maillist.codeproject.com: 

[image: Feedback] <http://www.codeproject.com> 

Please Help Us Make Developer Content Better 


We want to know what you love and hate about developer focused content. Can 

you please spare about a minute to tell us what you think 

<https://apps.developermedia.com/click/2650905?_z=132023101311017275> about 

the content you live and breathe by every day. Tell us what you love, hate, 

and what's missing in developer docs. 


*The Good, the Bad and the Ugly CodeProject Content Survey 

<https://apps.developermedia.com/click/2650906?_z=132023101311017275>*


We're only interested in overall trends in the responses from you and the 

other members who are taking this survey. Individual responses are never 

published or made public. *Ensuring your privacy is extremely important to 

us.*


*Click here to take the survey. 

<https://apps.developermedia.com/click/2650907?_z=132023101311017275>* 


Thank you in advance for your time - we really appreciate it! 

NOTA: Poti folosi un trigger sa salveze mailuri importante, atentie din testele mele si experienta mea google , nu exista garantia ca rezultatele sunt 100% si este si normal ... deoarece ofera servicii specializate, insa pentru o prelucrare partiala functioneaza si conteaza si ce obiectiv trebuie indeplinit.

Solutii - stocare cloud free

Sunt multe solutii de a stoca fisiere in cloud , in plus puteti folosi internxt.com - 10Gb free si mega.io/storage - 20 Gb free .

GAScript - salvarea partiala a adreselor de mail in google drive

In editorul de GAScript folositi acest cod sursa pentru a salva in coloana C o parte din adresele de mail cu functia denumita getEmailAddressesToSpreadsheet.

function getEmailAddressesToSpreadsheet() {

// selectia spreadsheet cu Id din URL de la browser, similar celorlalte tutoriale

// apare in URL spreadsheet-ului : docs.google.com/spreadsheets/d/ID-ul_efectiv_al_spreadsheet-ului/edit#gid=0

  var spreadsheetId = 'ID-ul efectiv al spreadsheet-ului'

  var sheetName = 'fiecare_saptamana ';

 

  var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);

  var emails = [];

 

  // Obțineți toate emailurile din contul dvs. de Gmail

  var threads = GmailApp.getInboxThreads();

  var emailRegex = /<([^>]+)>/; // Expresie regulată pentru a găsi adresele de email între "<" și ">"

 

  for (var i = 0; i < threads.length; i++) {

    var messages = threads[i].getMessages();

    for (var j = 0; j < messages.length; j++) {

      var message = messages[j];

      var from = message.getFrom();

      var matches = emailRegex.exec(from);

      if (matches && matches.length > 1) {

        var email = matches[1]; // Extrageți adresa de email din expresia regulată

        if (emails.indexOf(email) === -1) {

          emails.push(email);

        }

      }

    }

  }

   // Adăugați adresele de email în coloana C a Spreadsheet-ului

  for (var k = 0; k < emails.length; k++) {

    sheet.getRange(k + 1, 3).setValue(emails[k]);

  }

}


NOTA: La mine a adaugat in coloana C un numar de 160 de adrese de mail. Un numar cam fix, si mai stiu ca scripturile google au limitari de prelucrare - asemanator search in web unde trebuie sa specifici numarul de pagini. Totusi cu scripturile din tutorialele anterioare se poate face un management simplu pentru email-uri. O sa revin si cu alte imbunatatiri la acest managent al mailurilor in tutoriale viitoare.

GAScript - prelucrare coloana A cu afisare - insumare doar valori numerice 

In acest tutorial am sa va arat cum sa faceti o prelucrare simpla a valorilor numerice prin insumare si sa fie afisata ca un dialog in spreadsheet. Va trebui sa creati un spreadsheet sa redenumiti sheet cu denumirea test001 si din meniu sa treceti in editorul de scripturi GAScript. In editorul de GAScript aveti un fisier denumit Code.gs in care adaugam scriptul care va crea un meniu Menu cu un submeniu denumit Insumare Valori Matrice - Col A .

Iata scriptul: 

function onOpen() {

    var ui = SpreadsheetApp.getUi();

    ui.createMenu('Menu')

        .addItem('Insumare Valori Matrice - Col A', 'openDialog')

        .addToUi();

}

function insumareValoriMatrice(data) {

  var suma = 0;

  for (var i = 0; i < data.length; i++) {

    for (var j = 0; j < data[i].length; j++) {

      var valoare = data[i][j];

      if (!isNaN(valoare)) {

        // Verificăm dacă valoarea este un număr cu Number

        suma += Number(valoare);

      }

    }

  }

 

  return suma;

}


function getCellContent() {

  // Înlocuiți cu ID-ul efectiv al spreadsheet-ului din URL asa cum am explicat in vechile tutoriale

  var spreadsheetId = 'ID-ul efectiv al spreadsheet-ului'

  var sheetName = 'test001';

  var spreadsheet = SpreadsheetApp.openById(spreadsheetId);

  var sheet = spreadsheet.getSheetByName(sheetName);

  var data = sheet.getRange('A1:' + sheet.getLastRow()).getValues();

  var sumaValorilor = insumareValoriMatrice(data);

  Logger.log('Suma valorilor din col A este : ' + sumaValorilor);

  return ('Suma valorilor din col A este : '+sumaValorilor);

}

function openDialog() {

  var html = HtmlService.createTemplateFromFile('index')

                        .evaluate();

  SpreadsheetApp

    .getUi()

    .showModalDialog(html, 'InsumareValoriMatrice Col A');

}

In partea stanga o sa vedeti Files si un semn + pentru a adauga / crea fisiere de tip Script sau HTML .

O sa cream un fisier denumit index de tip HTML, se va adauga automat extensia .html.

In acest fisier adugam codul sursa: 

<!DOCTYPE html>

<html>

  <head>

    <base target="_top">

  </head>

  <body>

    <h1><?!= getCellContent() ?></h1>

  </body>

</html>

Acest fisier va afisa rezultatul functiei getCellContent()din prelucratea scriptului Code.gs.

Selectam functia onOpen din editorul GAScript si o rulam o singura data - pentru a fi introdusa in meniul de lucru al spreadseet.

Adaugam valori in coloana A pentru a fi prelucrate. Eu am folosit secventa : 1,2,3,76,70,1000,#,$,a,b,c,22

Din meniul principal selectam noul item din meniu principal denumit Menu si apoi submeniul Insumare Valori Matrice - Col A.

Va aparea un dialog creat cu continutul din index.html si valoarea calculata in cazul meu valorilor mele de ... 1174

NOTA: Aceasta prelucrare este mult mai avantajoasa pentru ca detinem controlul de prelucrare prin script. Se poate prelucra prin script cerinte mult mai complexe specifice cerintelor utilizatorului. As putea folosi prelucrari si sume de control pentru verificarea IBAN-urilor, cartilor de identitate, adrese de ipv4 sau ipv6, diverse formule de calcul logistic ... 

Unelte - vizualizare fisiere deschise in sistemul de operare Windows. 

In aceasta serie de tutoriale am sa va arat unelte software care va permit sa intelegeti si sa folositi sistemul de operare Windows.

Azi am sa va prezint un tool de la www.nirsoft.net - opened_files_view care va arata fisierele deschise chiar daca au fost eliminate folosind un alt soft de curatare a sistemului.

NOTA: Pe website nirsoft.net gasit si alte unelte software care va pot ajuta sa intelegeti si alte capabilitati ale sistemului de operare.

GAScript - numarul de mailuri primite conform coloana A cu completare in coloana B

Tutorial de azi rezolva o problema simpla in managementul mailurilor primite in GMail si anume afisarea numarului de mailuri primite in conordanta cu o anumita lista de adrese de mail. Va trebui sa folositi vechiul proiect din tutorialele anterioare sau sa creati un spreadsheet sa redenumiti sheet cu denumirea test001 si din meniu sa treceti in editorul de scripturi GAScript. In coloana A vom avea o lista de adrese de mail iar in coloana B vom primi rezultatul rulari functiei de baza a scriptului. In editorul de GAScript aveti un fisier denumit Code.gs in care adaugam functile necesare rezultatului final. Pentru o mai buna lizibiliatate a codului sursa si sa intelegem modul de functionare am folosite trei functii: getLastDataRow - returneaza ultimul rand, countEmailOccurrences(targetEmail) - găsește numărul de apariții pentru o adresa de mail si functia care trebuie sa o rulati pentru a adauga in coloana B denumita countAndAddToColumnB.

Iata scriptul: 

// Găsește ultimul rând într-o anumită coloană care conține date

function getLastDataRow(sheetName, column) {

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);

  if (!sheet) {

    Logger.log('Foaia cu numele ' + sheetName + ' nu a fost găsită.');

    return 'stop';

  }


  var columnData = sheet.getRange(column + '1:' + column + sheet.getLastRow()).getValues();

  for (var i = columnData.length - 1; i >= 0; i--) {

    if (columnData[i][0] !== '') {

      return i + 1// Se adaugă 1 pentru a obține numărul rândului

    }

  }

  return 'stop';

}

// Găsește numărul de apariții pentru targetEmail

function countEmailOccurrences(targetEmail) {

  // Căutăm în Gmail doar în ultimele 6 luni

  var sixMonthsAgo = new Date();

  sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);

 

  //var targetEmail = 'noreply@projects.blender.org';

  var query = 'from:' + targetEmail;


  var threads = GmailApp.search(query);

  var numberOfOccurrences = threads.length;


  Logger.log('Numărul de apariții pentru ' + targetEmail + ' este: ' + numberOfOccurrences);

  return numberOfOccurrences;

}


function countAndAddToColumnB() {

  // Încărcați adresele de email din coloana AA a spreadsheet-ului

  var spreadsheetId = 'ID-ul efectiv al spreadsheet-ului'; // Înlocuiți cu ID-ul efectiv al spreadsheet-ului

  var sheetName = 'fiecare_saptamana';

  var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);

  // Rândul de la care să începeți căutarea

  var startRow = 1;

  // Ultimul rând din foaia de calcul

  var endRowA = getLastDataRow(sheetName, 'A');


  for (var i = startRow; i <= endRowA; i++) {

    var emailAddress = sheet.getRange(i, 1).getValue();

    var count = 0;

    // Căutăm în Gmail doar în ultimele 6 luni

    var sixMonthsAgo = new Date();

    sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);

    // Verifică rezultatul și continuă dacă nu este "stop"

    if (endRowA !== '') {

      //Logger.log('Ultimul rând în coloana A: ' + endRowA);

      // Continuă cu restul codului pentru coloana A

      var count = countEmailOccurrences(emailAddress)

    } else {

      Logger.log('Nu există date în coloana A. Operația a fost oprită.');

    }

    // Adăugăm numărul de apariții în coloana B

    sheet.getRange(i, 2).setValue(count);

  }

}

In zona de Execution log vor aparea mesajele definite :

9:24:14 PM Notice Execution started

9:24:15 PM Info Numărul de apariții pentru noreply@projects.blender.org este: 437

9:24:15 PM Info Numărul de apariții pentru nouveau@lists.freedesktop.org este: 0

9:24:15 PM Info Numărul de apariții pentru newsletter@news.altex.ro este: 1

9:24:16 PM Info Numărul de apariții pentru promotion@aliexpress.com este: 1

9:24:16 PM Info Numărul de apariții pentru calendar-notification@google.com este: 6

...

In zona coloana B vor fi adaugate valorile cu numarul de aparitii a mailurilor corespondente cu adresele de mail din coloana A.


Best online IDE- use 

Tutorial de azi rezolva o problema simpla pentru cei ce invata programare web. Iata un I.D.E. online care rezolva destul de simplu configurari de web development, proiecte multiple si ofera posibilitatea de a dezvolta si testa proiecte simple de tip one-man project sau team. Il gasiti la StackBlitz 

In dreapta vedeti un embled cu un proiect simple creat de mine cu OpenStreetMap.


GAScript - Preluarea notificarilor din contul de GitHub

Tutorial de azi rezolva o problema simpla de preluare a notificarilor din contul de GitHub.

Daca aveti un cont de GitHub atunci sigur aveti folost optiunea de Watch pentru a va anunta in contul de Github ca sunt modificari la continutul unui repo. 

GitHub permite sa folositi unelte online sau GraphQL - le gasiti in cartea scrisa de mine cu exemple.

Pentru a folosi GAScript de la google vom folosi autentifiarea acesta.

Iata scriptul care afiseaza in zona Logger date despre notificarile de la contul cu token alocat

// functie preluare token setat in contul de GitHub

// unde am setat sa citeasca doar notifications pentru a le prelua cu 'https://api.github.com/notifications'

function getGitToken() {

    var AUTH_TOKEN = "ghp_xxxxxx";

    return AUTH_TOKEN

}


function getGitHubNotifications() {

  // Token-ul GitHub set just for settings - few days

  const GIT_API_URL = 'https://api.github.com/notifications';

  // Opțiunile cererii : setare 'method'  de tip GET si configurarea pentru 'headers'

  var urlFetchOptions = {

    "method": "GET",

    "headers": {

      "Accept": "application/vnd.github.v3+json",

      "Content-Type": "application/json",

      "Authorization": `Bearer ${getGitToken()}`,

    }

  }

  var gitResponse = UrlFetchApp.fetch(GIT_API_URL, urlFetchOptions);

  // Afisare raspuns cu Logger

  Logger.log(gitResponse);

}

In zona de Execution log vor aparea mesajele definite :

  4:24:00 PM

Notice

Execution started

4:24:01 PM

Info

Logging output too large. Truncating output. [{"id":"8546996934","unread":true,"reason":"subscribed","updated_at":"2023-11-26T14:07:42Z","last_read_at":null,"subject":{"title":"Someone please explain ‘MouseEvent.OfX/OfY’","url":null,"latest_comment_url":null,"type":"Discussion"},"repository":{"id":113807330,"node_id":"MDEwOlJlcG9zaXRvcnkxMTM4MDczMzA=","name":"Terminal.Gui","full_name":"gui-cs/Terminal.Gui","private":false,"owner":{"login":"gui-cs","id":106351764,"node_id":"O_kgDOBlbMlA","avatar_url":"https://avatars.githubusercontent.com/u/106351764?

...



Unelte - antivirusi si unelte similare - KVRT- 001.

In tutorial de azi voi prezenta o unealta tip antivirus si similar. Este un mod de exprimare zona aceasta din securitatea informatiei procesate este foarte complexa. Aceasta unealta este singura care mi-a detectat si afisat un raspuns cu posibile intrusiuni. 

NOTA : Cei ce lucreaza cu programul de ansamblare si au fisiere executabile de anumite tipuri pot fi detectate fals de acesta unealta software pentru ca face o detectie euristica. Detectia euristica a aparut in trecut ca un promotor al inteligentei artificiale odata cu aparitia virusurilor polimorfi creati cu un utilitar MTE care introducea secvente de cod masina in codul masina al virusului. Practic secventa de detectie din parsarea cu antivirus se modifica si antiivrusul devenea ineficient.

Unealte se numeste kvrt este creata de kaspersky-labs.com si poate fi gasita la acest URL.

Unelte - programe open-source pentru grafica.

In tutorial de azi voi unelte software pentru grafica le gasiti pe web-siturile oficiale cu un simplu search:

Pentru partea de imagini vectoriale recomand Inkscape.

Pentru pictura si desen pe tableta recomand Krita.

Pentru partea de 3D recomand software Blender 3D.

GAScript - afisare in grafic PIE a dimensiunilor fisierelor din Google Drive.

In tutorial de azi voi prezenta un script care afiseaza intr-un chart tip PIE dimensiunile fisierelor din Google Drive.

Iata codul sursa folosit:

function generateDriveUsageReportPie() {

  var drive = DriveApp.getRootFolder();

  var files = drive.getFiles();


  var data = [['Nume Fișier', 'Dimensiune (KB)']];

 

  while (files.hasNext()) {

    var file = files.next();

    var fileSizeBytes = file.getSize();

    var fileSizeKB = fileSizeBytes / 1024; // Convertim dimensiunea în KB

    data.push([file.getName(), fileSizeKB]);

  }


  // Deschide sau creează un Google Sheet

  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

  var sheet = spreadsheet.getSheetByName('Drive Usage Report');

  if (!sheet) {

    sheet = spreadsheet.insertSheet('Drive Usage Report');

  }


  // Se sterg datele existente

  sheet.clear();


  // Se scrie datele în tabel

  sheet.getRange(1, 1, data.length, data[0].length).setValues(data);


  // Aceasta sterge manual graficele existente din fișierul Google Sheets

  var charts = sheet.getCharts();

  for (var i = 0; i < charts.length; i++) {

    sheet.removeChart(charts[i]);

  }


  // Adaugă un grafic tip Pie Chart cu datele obtinmute

  var chart = sheet.newChart()

    .asPieChart()

    .setTitle('Utilizare Google Drive')

    .addRange(sheet.getRange(2, 1, data.length - 1, 2))  // Exclude header row

    .setPosition(5, 1, 0, 0)

    .setOption('title', 'Utilizare Google Drive')

    .setOption('legend', {position: 'top'})

    .build();


  sheet.insertChart(chart);


  Logger.log('Raport generat cu succes.');

}

   


Unelte - website cu programe open-source 

Iata un website cu programe open-source pe acest website: Open Source Alternatives to Proprietary Software.


Unelte - Analytics GA4   

Pentru a seta noua cerinta Google Analytics : If you haven't completed migration, finish setting up your Google Analytics 4 property before your connected Universal Analytics property is permanently deleted on Jul 1, 2024. To maintain access to data from this property, you should download your data now.o to Setup Assistant

trebuie sa ajungeti la o setare in care sa fie activati toti pasii, vezi imaginea de mai sus.

Free - carti gratis

Daca nu va place sa cautati zilnic pe google books sau amazon iata alte optiuni pentru carti gratis:

O lista cu carti unele gratis va trimite si pe mail noutati : bookbub.com.


Programare - cross-platform cu MSYS2

MSYS2 este distribuție de software și o platformă de construcție pentru Windows. Oferă un mediu asemănător Unix, o interfață de linie de comandă și un depozit de software care facilitează instalarea, utilizarea, construirea și portarea software-ului pe Windows. Asta înseamnă Bash, Autotools, Make, Git, GCC, GDB..., toate ușor de instalat prin Pacman, un manager de pachete cu funcții complete.

MSYS2 te lasa sa folosesti un Unix environment pentru Windows si astfel iti permite sa creezi programe executabile windows din linux cunoscute ca cross-platform folosind librarii dedicate.

Poti sa descarcati de aici ultima versiune si sa il instalati.

Apoi va trebui sa rulati comenzile :

pacman -Syu

pacman -S mingw-w64-x86_64-toolchain

pacman -S base-devel gcc vim cmake

pacman -S development

Creaza un fisier denumit test.cpp si adauga acest cod sursa:

#include <ncurses/ncurses.h>

int main() {

    initscr();          // Initialize screen

    printw("Hello World"); // Print to screen

    refresh();          // Refresh the screen

    getch();            // Pause the screen output

    endwin();           // Deallocate memory and exit ncurses

    return 0;

}

Ruleaza comanda :

$ g++ test.cpp -o test.exe -lncurses -DNCURSES_STATIC

Copie fisierele DLL cerute de executabil din folderul:

\msys64\usr\bin

In cazul acestui cod sursa simplu a avut nevoie de:

msys-2.0.dll si msys-ncursesw6.dll

Rezultatul rularii fisierului test.exe este o consola care afiseaza textul: Hello World

Iata un exemplu mai complex pe care l-am gasit pe web si l-am testat. Creaza un patrat ce poate fi miscat cu sagetile:

/* ncurses.h includes stdio.h */

#include <ncurses/ncurses.h> 

WINDOW *create_newwin(int height, int width, int starty, int startx);

void destroy_win(WINDOW *local_win);

int main(int argc, char *argv[])

{

    WINDOW *my_win;

    int startx, starty, width, height;

    int ch;

    initscr(); /* Start curses mode */

    raw(); /* Line buffering disabled, Pass on

* everty thing to me */

    noecho();

    keypad(stdscr, TRUE); /* I need that nifty F2 */

    height = 3;

    width = 10;

    starty = (LINES - height) / 2; /* Calculating for a center placement */

    startx = (COLS - width) / 2; /* of the window */

    printw("Press F2 to exit");

    refresh();

    my_win = create_newwin(height, width, starty, startx);

    while((ch = getch()) != KEY_F(2))

    {

switch(ch)

{

    case KEY_LEFT:

destroy_win(my_win);

my_win = create_newwin(height, width, starty,--startx);

break;

    case KEY_RIGHT:

destroy_win(my_win);

my_win = create_newwin(height, width, starty,++startx);

break;


    case KEY_UP:

destroy_win(my_win);

my_win = create_newwin(height, width, --starty,startx);

break;


    case KEY_DOWN:

destroy_win(my_win);

my_win = create_newwin(height, width, ++starty,startx);

break;

}

    }

    endwin(); /* End curses mode   */

    return 0;

}

WINDOW *create_newwin(int height, int width, int starty, int startx)

{

    WINDOW *local_win;

    local_win = newwin(height, width, starty, startx);

    box(local_win, 0 , 0); /* 0, 0 gives default characters for the vertical and horizontal lines */

    wrefresh(local_win); /* Show that box */

    return local_win;

}

void destroy_win(WINDOW *local_win)

{

    /* box(local_win, ' ', ' '); : This won't produce the desired

  * result of erasing the window. It will leave it's four corners 

* and so an ugly remnant of window.  */

    wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');

/* The parameters taken are 

* 1. win: the window on which to operate

* 2. ls: character to be used for the left side of the window 

* 3. rs: character to be used for the right side of the window 

* 4. ts: character to be used for the top side of the window 

* 5. bs: character to be used for the bottom side of the window 

  * 6. tl: character to be used for the top left corner of the window 

* 7. tr: character to be used for the top right corner of the window 

* 8. bl: character to be used for the bottom left corner of the window 

* 9. br: character to be used for the bottom right corner of the window */

    wrefresh(local_win);

    delwin(local_win);

}

Poate imi gasesc putin timp si fac o versiune windows pentru programul cu codul sursa ncurses de pe repo meu de GitHub, acesta imi permite sa ascult radio online pe Fedora linux.





Programare - FASM - adunare folosind registri MMX

FASM (flat assembler) este un limbaj de asamblare. Acesta suportă programarea pe arhitecturile de calculatoare IA-32 și x86-64 folosind sintaxa Intel . Este creata de Tomasz Grysztar. Este destul de maleabil - poti folosi macroinstructiuni si structuri de date mai avansate. Este destul de vechi fasm - manual , o varianta mai imbunatatita si diferita este fasmg - manual

Exemplu de azi iti arata cum sa folosesti instructiuni MMX pentru a realiza o adunare simpla. Nu am avut un procesor mai avansat asa ca m-am oprit la MMX. De ce stiu sa lucrez cu limbajul de programare pentru ca prima mea specialitate a implicat lucru cu programe ce rulau cu cod sursa asamblare. La mine acest program a rulat de doua ori in primele run-uri desi am scos primul invoke de afisare si dupa ce am rulat de mai multe ori a rulat normal. Cumva pointerul la registru program pentru acest run a dublat executia si apoi a revenit ... posibil ceva in sistemul de operare ... Codul sursa este destul de aliniat in executie ... poate fi mult mai aliniat si optimizat - ar insemna consum de resursa timp.

format PE GUI 4.0

entry Start

include 'INCLUDE/WIN32AX.INC'

SECTION '.data' DATA READABLE WRITEABLE executable

  consoleTitle db 'Add two numbers using MMX ',0

  ;offset dd ?

  hConOut dd ?

  FOREGROUND_GREEN = 10

  FOREGROUND_INTENSITY = 10

  addr dd ?

  n dd ?

  sizeof.output = 256  ; I don't find a sizeof for output

  sizeof.prompt = 256  ; I don't find a sizeof for output

  num1 dd 15

  num2 dd 20

  result dd ?

  prompt db 'Two numbers to add: ',0

  fo db 'The result is: %d',0   ; format ??

  output db 16 dup (0)

section '.code' code readable writeable executable

Start:

    invoke AllocConsole

    invoke GetStdHandle, STD_OUTPUT_HANDLE

    mov [hConOut], eax

    invoke SetConsoleTitle,  consoleTitle

    invoke SetConsoleTextAttribute, [hConOut], FOREGROUND_GREEN or FOREGROUND_INTENSITY

    invoke WriteConsole, [hConOut],  prompt, sizeof.prompt, addr n, 0

    ; Read the two numbers from the console

    invoke ReadConsole, [hConOut], addr num1, 4, addr n, 0

    invoke ReadConsole, [hConOut], addr num2, 4, addr n, 0

    ; Add the two numbers with MMX

    movd mm0, [num1]

    movd mm1, [num2]

    paddw mm0, mm1

    movd [result], mm0

    emms

    ; Print the result to the console

    cinvoke wsprintf,  output,  fo, [result]

    invoke WriteConsole, [hConOut],  output, sizeof.output, addr n, 0

    invoke Sleep, 5000

    invoke FreeConsole

    invoke MessageBox,0,'Done ! Exit',0,0

    invoke ExitProcess,0

section         '.idata' import data readable writeable

library         kernel32,'KERNEL32.DLL',user32,'USER32.DLL',gdi32,'GDI32.DLL'

include         'INCLUDE/API/KERNEL32.INC'

include         'INCLUDE/API/USER32.INC'

include         'INCLUDE/API/GDI32.INC'


Free - aplicatii android utile

Iata cateva applicatii android pe care le folosesc si sunt utile:

IDE pentru programare grafica pe telefon mobil - nivel incepator : APDE - Android Processing IDE.

IDE pentru programare cu shadere pe telefon mobil cu posibilitate salvare wallpaper - nivel mediu : Shader Editor.

Manager activitati si planificare : Todoist: to-do list & planner.

Aplicatie pentru orice sport si drumetii cu harta incorporata : Wiki Loc.

Aplicatie pentru Romania - Office's Department of Emergency Situations : DSU.

Aplicatie pentru monitorizarea si avertizarea calitatii aerului : uRADMonitor.

Aplicatie pentru monitorizarea si avertizarea asteroizi - sunt destui : AsteroidAlert.

Aplicatie cu melodii vechi pe categorii si ani : Rewind: Music Time Travel.

Aplicatie cu banda desenta - se gasesc si free insa majoritatea costa : AveComics.

Aplicatie carti de la amazon kindle - se gasesc si free insa majoritatea costa : Amazon Kindle.

Copilot - testare copilot cu raspuns despre Kickstarter si alte functionalitati.

Copilot vine cu multiple optiuni de inteligenta artificiala :

Partea care ma intereseaza este legat de development si prelucrarea de informatii alocata inteligentei artificiale.

Azi am vazut un video legat de development-ul unui joc pe un proiect kickstarter - Night Stones, asa ca m-am gandit sa testez utilitarul copilot pentru a vedea acuratetea informatilor legate de acest online tool. 

Copilot vine cu raspunsuri sunt destul de corecte:

1. Cum funcționează kickstarter și care este scopul angajamentului - pledged în acest proces?

Kickstarter este o platformă de finanțare colectivă care permite creatorilor să-și transforme proiectele în realitate, strângând fonduri de la o comunitate de susținători. Iată cum funcționează:

Pe scurt, Kickstarter conectează creatorii cu susținătorii, permițând proiectelor inovatoare să prindă viață prin sprijinul și finanțarea colectivă. Suma promisă joacă un rol crucial în transformarea acestor eforturi creative în realitate!

2. Ce impedimente pot avea ca creator în utilizarea Kickstart?

Când ești creator pe Kickstarter, există câteva aspecte importante de luat în considerare și pot apărea diverse impedimente. Iată câteva dintre ele:

Amintiți-vă că Kickstarter nu este un magazin, iar susținătorii contribuie la crearea ceva nou, nu la precomandarea unui produs deja existent. Fiți deschiși și sinceri în comunicarea cu susținătorii și faceți tot posibilul să finalizați proiectul în ciuda eventualelor obstacole.

GAScript - Monitorizarea video-urilor din youtube ...

Tutorial de azi rezolva o problema simpla pentru monitorizarea videoclipurilor din youtube si adaugarea acestora intr-un spreadshet.

Spreadsheet va contine un cap tabel la randul 1A si incepand de la randul 2A pe coloana A puteti adauga link din bara de adrese pentru fiecare videoclip de pe youtube monitorizat.

Eu am multe scripturi cu API de la YouTube, daca va intereseaza sa imi scrieti la pagina de contact, pentru ca resursa mea de timp este limitata.

Iata scriptul pe care l-am folosit

// function onOpen() {

  let ui = SpreadsheetApp.getUi();

  ui.createMenu('YouTube').addItem('Get stats', 'getStats').addToUi();

}


function getStats() {

  let sheet = SpreadsheetApp.getActiveSheet();


  // Get range without the header row

  let dataRange = sheet.getDataRange().offset(1, 0, sheet.getLastRow() - 1);

  let values = dataRange.getValues();

  let videoUrls = [];

  let currentStats = [];


  extractVideoUrl_(values, videoUrls);

  getCurrentStats_(videoUrls, currentStats);

  writeStats_(currentStats, dataRange);

  doFormatting_(sheet);

}


function extractVideoUrl_(values, videoUrls) {

  values.forEach(function(video) {

    videoUrls.push(video[0]);

  });

  return videoUrls;

}


function getCurrentStats_(videoUrls, currentStats) {

  videoUrls.forEach(function(videoUrl) {

    if(videoUrl != "") {

      let videoId = extractVideoIdFromUrl_(videoUrl);

      let detailsResponse = getVideoDetails_(videoId);


      let title = detailsResponse.items[0].snippet.title;

      let publishDate = detailsResponse.items[0].snippet.publishedAt;

      let publishDateFormatted = new Date(publishDate);

      let views = detailsResponse.items[0].statistics.viewCount;

      let likes = detailsResponse.items[0].statistics.likeCount;

      let comments = detailsResponse.items[0].statistics.commentCount;


      currentStats.push([title, publishDateFormatted, views, comments, likes]);

    }

  });

  return currentStats;

}


function extractVideoIdFromUrl_(url) {

  let videoId = url.split('v=')[1];

  let ampersandPosition = videoId.indexOf('&');

  if(ampersandPosition != -1) {

    videoId = videoId.substring(0, ampersandPosition);

  }

  return videoId;

}


function getVideoDetails_(videoId) {

  let part = "snippet,statistics";

  let response = YouTube.Videos.list(part, {'id': videoId});

  return response;

}


function writeStats_(currentStats, dataRange) {

  let newDataRange = dataRange.offset(0, 1, currentStats.length, currentStats[0].length).setValues(currentStats);

}


function doFormatting_(sheet) {

  sheet.getRange('D:F').setNumberFormat('#,###');

  sheet.getRange('C:C').setNumberFormat('dd.mm.yyyy');

  sheet.getDataRange().offset(1, 0, sheet.getLastRow() -1).sort({column: 4, ascending: false});

}

Windows - DISM and Get-Capabilities.

Tutorial de azi , DISM poate fi folosit pentru a verifica dacă anumite capacități sau caracteristici  :

Aceasta comanda am rulat-o pe cont administrator

DISM /Online /Get-Capabilities /Format:Table | Find "Installed"

App.StepsRecorder~~~~0.0.1.0                             | Installed

App.Support.QuickAssist~~~~0.0.1.0                       | Installed

Browser.InternetExplorer~~~~0.0.11.0                     | Installed

DirectX.Configuration.Database~~~~0.0.1.0                | Installed

Hello.Face.18967~~~~0.0.1.0                              | Installed

Language.Basic~~~en-US~0.0.1.0                           | Installed

Language.Basic~~~ro-RO~0.0.1.0                           | Installed

Language.Handwriting~~~en-US~0.0.1.0                     | Installed

Language.Handwriting~~~ro-RO~0.0.1.0                     | Installed

Language.OCR~~~en-US~0.0.1.0                             | Installed

Language.OCR~~~ro-RO~0.0.1.0                             | Installed

Language.Speech~~~en-US~0.0.1.0                          | Installed

Language.TextToSpeech~~~en-US~0.0.1.0                    | Installed

Language.TextToSpeech~~~ro-RO~0.0.1.0                    | Installed

MathRecognizer~~~~0.0.1.0                                | Installed

Media.WindowsMediaPlayer~~~~0.0.12.0                     | Installed

Microsoft.Windows.MSPaint~~~~0.0.1.0                     | Installed

Microsoft.Windows.Notepad~~~~0.0.1.0                     | Installed

Microsoft.Windows.PowerShell.ISE~~~~0.0.1.0              | Installed

Microsoft.Windows.WordPad~~~~0.0.1.0                     | Installed

NetFX3~~~~                                               | Installed

OneCoreUAP.OneSync~~~~0.0.1.0                            | Installed

OpenSSH.Client~~~~0.0.1.0                                | Installed

Print.Fax.Scan~~~~0.0.1.0                                | Installed

Print.Management.Console~~~~0.0.1.0                      | Installed

Tools.Graphics.DirectX~~~~0.0.1.0                        | Installed

Windows.Client.ShellComponents~~~~0.0.1.0                | Installed


Aceast rezultat dupa raspunsul copilot reprezinta:


Folosirea DISM pentru a elimina din acestea care nu sunt in concordanta cu calculatorul meu, exemplu : Hello.Face.18967 mi-a generat eroare pentru ca nu era activata si se poate dezinstala :

DISM /Online /Disable-Feature /FeatureName:Hello.Face.18967~~~~0.0.1.0


Deployment Image Servicing and Management tool

Version: 10.0.19041.3636


Image Version: 10.0.19045.3930



Error: 0x800f080c


Feature name Hello.Face.18967~~~~0.0.1.0 is unknown.

A Windows feature name was not recognized.

Use the /Get-Features option to find the name of the feature in the image and try the command again.


The DISM log file can be found at C:\WINDOWS\Logs\DISM\dism.log


C:\WINDOWS\system32>DISM /Online /Remove-Capability /CapabilityName:Hello.Face.18967~~~~0.0.1.0


Deployment Image Servicing and Management tool

Version: 10.0.19041.3636


Image Version: 10.0.19045.3930


[==========================100.0%==========================]

The operation completed successfully.

Programare - FASM - IAT and INT - source code .Import Address Tableaaa

Tutorial de azi este pentru cei avansați în călătoria către calea de analiză malware si protectie a codului sursa executabil.

Este un cod sursa gasit de mine pe web care foloseste tehnologia IAT - Import Address Table.

Deoarece ambele indică aceeași structură de date, principala diferență dintre IAT și INT este că INT nu este suprascris de încărcătorul Windows atunci când executabilul este încărcat în memorie, dar intrările IAT sunt suprascrise cu adresa reală a funcției importate.

Am folosit acest cod sursa si FASM cu versiunea 17330: 

format PE64 NX GUI  6.0

entry start


macro import_directory_table [lib] {

forward

        dd rva IAT__#lib

        dd 0

        dd 0

        dd rva NAME__#lib 

        dd rva IAT__#lib


common

        dd 5 dup(0)


forward

        NAME__#lib db `lib, ".DLL", 0

}


macro import_functions libname, [funcnames] {

forward

      if $ & 1

         db 0

      end if

      IMPORTNAME__#funcnames dw 0

                             db `funcnames, 0

common

        IAT__#libname:

forward

        funcnames dq rva IMPORTNAME__#funcnames


common

        dq 0

}



macro call64_putreg param*, reg*

{

        if ~ (reg eqtype rax)

           display "target must be a register"

           err

        end if

        if ~ param eq reg

            mov reg, param

        end if

}


macro call64 fn*, [arg]

{

common

        local nargs, arg_idx, stack_space


        if nargs <= 4

           stack_space = 5 * 8

        else if nargs & 1

           stack_space = nargs * 8

        else

           stack_space = (nargs + 1) * 8

        end if


        if stack_space

           sub rsp, stack_space

        end if


        arg_idx = 0


forward

        match ,arg

        \{

        \}

        match any,arg

        \{

           arg_idx = arg_idx + 1

           if arg_idx = 1

               call64_putreg arg, rcx

           else if arg_idx = 2

               call64_putreg arg, rdx

           else if arg_idx = 3

               call64_putreg arg, r8

           else if arg_idx = 4

               call64_putreg arg, r9

           else

               mov qword [rsp + (arg_idx-1)*8], arg

           end if


        \}

common

        nargs = arg_idx

        call fn

        if stack_space

           add rsp, stack_space

        end if

}


section '.text' code readable executable

        HelloStr db "Hello, World!", 0

start:

        call64 [MessageBoxA], 0, HelloStr, HelloStr, 0

        call64 [ExitProcess], 0


section '.idata' import readable writeable

        import_directory_table KERNEL32, USER32

        import_functions KERNEL32, ExitProcess

        import_functions USER32, MessageBoxA

Am testat cu fasm si functioneaza forte bine.