Поиск по этому блогу

воскресенье, 26 февраля 2023 г.

Coding. Список файлов на диске Google Drive

 Apps Script

Очень удобная вещь этот App Script со встроенной IDE и хорошим мануалом
yt manuals Laurence Svekis - к этим мануалам прилагается код в Git репозитории


// под свои нужды я написала код для получения всех файлов, хранящихся на Google Drive

function saveAllFiles2sheet() {
var ssid = '1q5BtsLViJBYgmwsnQJlrwe7deU9lYkuCh15_jlHpD7U' 
const ss = SpreadsheetApp.openById(ssid).getSheetByName('log');
// header
ss.appendRow(['Folder','FileName''ID''MD5''Modified''Created''size''permissons']);
var files = DriveApp.getFiles();
while (files.hasNext()) {
  var file = files.next();
sid = file.getId()
let parentFolder = file.getParents().next().getName()  
  let obj = {
            fileName:file.getName(),   //DriveApp.getFileById(sid).getName(),
            mimeType :file.getMimeType(), //DriveApp.getFileById(sid).getTargetMimeType,
            fileId:sid,
            fileMd5Drive.Files.get(sid)['md5Checksum'],
            folderFileparentFolder
            dataCreatedfile.getDateCreated(),
            dataLastUpd : file.getLastUpdated(), //DriveApp.getFileById(sid).getLastUpdated
            sizefile.getSize(),
            filePermissionfile.getSharingPermission()
          } 
   

  let slog = obj.fileName + '; ' +  obj.fileId + '; ' + obj.fileMd5 + '; 'parentFolder
  Logger.log(slog);
  
  ss.appendRow([obj.folderFileobj.fileNameobj.fileIdobj.fileMd5obj.dataLastUpdobj.dataCreatedobj.sizeobj.filePermission]);
}

function save2sheetsBiId(sid) {
var ssid = '1q5BtsLViJBYgmwsnQJlrwe7deU9lYkuCh15_jlHpD7U' 
const ss = SpreadsheetApp.openById(ssid).getSheetByName('log');
let file = DriveApp.getFileById(sid)
let parentFolder = file.getParents().next().getName() 
let permissions = file.getSharingPermission()
Logger.log(permissions)

  let obj = {
            fileName:file.getName(),   //DriveApp.getFileById(sid).getName(),
            mimeType :file.getMimeType(), //DriveApp.getFileById(sid).getTargetMimeType,
            fileId:sid,
            fileMd5Drive.Files.get(sid)['md5Checksum'],
            folderFileparentFolder
            dataCreatedfile.getDateCreated(),
            dataLastUpd : file.getLastUpdated(), //DriveApp.getFileById(sid).getLastUpdated
            sizefile.getSize(),
            filePermissionfile.getSharingPermission()
          } 
let slog = obj.fileName + '; ' +  obj.fileId + '; ' + obj.fileMd5 + '; 'parentFolder + '; ' + obj.filePermission
  Logger.log(slog);
  
  ss.appendRow([obj.folderFileobj.fileNameobj.fileIdobj.fileMd5obj.dataLastUpdobj.dataCreatedobj.sizeobj.filePermission]);


}


function myFunction() {

//save2sheetsBiId('1oGhGUz0-wjtSZzmmIY2-LIcRxLCoUo9h') // файл по ID
 saveAllFiles2sheet() // получение всего списка файлов
}

Особая фича от Google - триггеры, ке можно привязать к любому действию, будь то
загрузка файлов или редактирование документов, тот же код можно привязать к триггеру
загрузки файлов

Стандартный пример из мануала "загрузка фалов" можно дополнить функцией
записи в sheet информации о файле

function onFormSubmit(e) {
....
    // Moves the files to the destination folder.
    if (fileUploads.length > 0) {
      fileUploads.forEach((fileId) => {
        DriveApp.getFileById(fileId).moveTo(destFolder);
        console.log(`File Copied: ${fileId}`)
// save to sheets
save2sheetsBiId(fileId)
...



среда, 15 февраля 2023 г.

Алгоритм разбора XML to map (golang)

1. Зачем?

В golang предусмотрена стандартная библиотека (пакет) для работы с XML файлами. Вы должны определить структуру XML и с помощью нее делать разбор (Marshaling, unmarshaling) XML fe Go by Example: XML

но, каждый раз когда вам потребуется заменить структуру XML, придется переписывать код.

или использовать универсальное решение - разбор XML в map, где ключ - это имя ноды с атрибутом, а значение - содержимое ноды.

  

 // from ini xml to map 

// parent must not contain strings only child node & parent must delimeter with LF (/n)
// каждая нода разделяется символом перевода строки
// для XML это не есть обязательное условие, но по факту для читабельности это стандарт 
func parseXML2map(fname string, sibling string) {
	loadXML2slice(fname, sibling) // внешняя процедура, кя просто берет XML файл и закидывает 
                                    // ветку для кй имя Parent Node = sibling 

	iniV := strings.Split(glSlice[1], "<")
	containNode := ""
	nameNode := ""
	fullName := ""
	ParentNode := ""
	for _, val := range iniV {
		containNode = ""

		node := strings.Split(val, ">")
		if len(node) >= 2 {
			nameNode = node[0] // ParentNode + ">" +
			// for safety and clear win CR symbol
                        // функция очищает строку от непечатных символов 
                        // ArrByte[i] > 0 && ArrByte[i] <= 28 с 0 по 28 символ
                        // например, firstByte[0] == 10 - перенос строки заменяется пробелом
			containNode = clearNotPrnSymbols(node[1])
			containNode = strings.Trim(containNode, " ")
			//fmt.Printf("i = %d, val = %s, len %d ", i, containNode, len(containNode))

		}

		if strings.Index(nameNode, "/") < 0 {
			ParentNode = ParentNode + ">" + nameNode
			//fmt.Println("parent ", ParentNode)
		}
		fullName = ParentNode
		//fmt.Println(" fullName ", fullName)
		//fmt.Println("node ", nameNode, strings.Index(nameNode, "/"))
		if strings.Index(nameNode, "/") == 0 { // тэг закрывающий
			tmp := strings.Split(ParentNode, ">")
			tmp_last := ">" + tmp[len(tmp)-1]
			ParentNode = strings.Replace(ParentNode, tmp_last, "", -1)


			continue
		}			

		glIniVariables[fullName] = containNode
		

	} // eo for
	
	// !!!! Iteration order is not specified and may vary from iteration to iteration. ((((((
	// вывод результата
        fmt.Println("out map ")
	for key, value := range glIniVariables {
		fmt.Println(key, "value ", value)
	}

}

Пример на входе XML
<ini>
<second>
<sitename type="ext">http://historybookspace.rf.gd/</sitename>
<header>?xml version="1.0" encoding="UTF-8"?;urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
</header>
<foot>urlset</foot>
<structuresitemap>url;loc;absloc;sha;lastmod;size;fmode</structuresitemap>
<structurebook>pagename;loc;fname;md5;dateload;size;fmode</structurebook>
</second>
<test>
<three>test node</three>
</test>
</ini>

На выходе

out map 
>>ini>second>sitename - name of node and his parents
type="ext" - attribute 
http://historybookspace.rf.gd/ - node contains
>>ini>second>sitename type="ext" value http://historybookspace.rf.gd/ >>ini>second>structurebook value pagename;loc;fname;md5;dateload;size;fmode >>ini>test value >>ini>second value >>ini value >>ini>second>header value ?xml version="1.0" encoding="UTF-8"?;urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" >>ini>second>foot value urlset >>ini>second>structuresitemap value url;loc;absloc;sha;lastmod;size;fmode >>ini>test>three value test node

2. Зачем?

теперь мы получили массив (map[key, value]), по которому можно искать значения XML
в golang для поиска есть пакет Regexp, кй позволяет проводит поиск по регулярным выражениям
структуру XML мы сохранили, в значении key, где указано имя ноды и ее предки 
атрибуты сохранили в значении key
содержимое ноды в value