Skip to content

Mini proyectos

Generador de contraseña segura

Genera contraseñas con todos letras manicuras y mayúsculas, símbolos y números. Solicitándole al usuario cuantos caracteres debe contener la contraseña.

import 'dart:convert';
import 'dart:math';
import 'dart:io';

void main(List<String> args) {
  String letterLower = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
  String letterUpper = letterLower.toUpperCase();
  String numbers = "0123456789";
  String symbols = "\";!#\$%&/()=*][_:;-.,}{+¿\'}]";

  int passwordLength = 8;
  String password = "";

  print("Cual sera el largo de la contraseña?")  ;
  passwordLength = int.parse(stdin.readLineSync(encoding: utf8)!);

  while(password.length < passwordLength){
    password += letterLower[Random().nextInt(letterLower.length-1)];
    password += letterUpper[Random().nextInt(letterUpper.length-1)];
    password += numbers[Random().nextInt(numbers.length-1)];
    password += symbols[Random().nextInt(symbols.length-1)];
  }

  print("Tu nueva super contraseña SEGURA ES: $password");
}

Reto

  • Preguntar por cada tipo símbolo, para ser incluido (símbolos, letras mayúscula o minúscula, números)
  • debe dar el largo de contraseña correcto, dato quiero una contraseña de 3, sean 3 caracteres, etc.

Ordenador de documentos

Aplicación de terminal o cli, que se le da una dirección de una carpeta de nuestro sistema, analizando las extensiones que le hemos dado, creando las carpetas necesarias, moviendo los archivos con la extension indicada a la carpeta correspondiente.

Archivo de las funciones generales

read_files.dart
import 'dart:io';

const extensionWord = <String>[".doc", ".docx"];
const extensionPDF = <String>[".pdf"];
const extensionExe = <String>[".exe", ".bat"];
const extensionImages = <String>[".jpeg", ".jpg", ".png", ".gif"];
const extensionCompress = <String>[".zip", ".rar", ".7zip", ".tar", ".tar.gz"];
const folders = <String>["Word","Imagenes","Comprimidos","pdf","ejecutables","Otros"];

Map<String, List<String>> extensionMap = {
  "Word":extensionWord,
  "pdf": extensionPDF,
  "ejecutables": extensionExe,
  "Imagenes":extensionImages,
  "Comprimidos": extensionCompress
};

/**
 * leer los archivos de una carpeta y/o sub carpetas
 */
List<String> readFiles(String pathDir, [bool recursive = false]) {
  var paths = <String>[];
  var dir = Directory(pathDir);
  var files = dir.listSync(followLinks: false, recursive: recursive);

  for(final file in files){
    paths.add(file.path);
  }

 return paths;
}

bool createFolders(String pathDir){
  for (final folder in folders){
    Directory("$pathDir${Platform.pathSeparator}$folder").createSync();
  }
    return true;
}

bool moveFile(String pathBase, String pathNewDir){

    String name_file = pathBase.split(Platform.pathSeparator).last;

    print("$pathBase -> $pathNewDir${Platform.pathSeparator}$name_file");
    File(pathBase).rename("$pathNewDir${Platform.pathSeparator}$name_file");

    return true;
}

String getNameFolder(String path){
    String folder = "Otros";
    String name_file = path.split(Platform.pathSeparator).last;

    for(final key in extensionMap.keys){
      var listExt = extensionMap[key];
      for(final ext in listExt!){
        if(name_file.endsWith(ext)){
          return key;
        }
      }
    }

    return folder;

}

//main es para pruebas
void main(List<String> args) {
  String pathDir = "C:\\Users\\usuario\\Documents\\prueba";
  final paths = readFiles(pathDir);
  createFolders(pathDir);

  for(final path in paths){
    moveFile(
      path,
      pathDir+Platform.pathSeparator+ getNameFolder(path));
  }

}

Archivo main

main.dart
import 'dart:io';

import 'read_files.dart'; // importamos la librería de funciones

/**
 * Punto de entrada de la aplicación
 */
void main(List<String> args) {
  String pathDir = args[0];

  final paths = readFiles(pathDir);
  createFolders(pathDir);
  try {
    for (final path in paths) {
      moveFile(path, pathDir + Platform.pathSeparator + getNameFolder(path));
    }
  } catch (e) {}
}

Forma de uso

dart main.dart "C:\\Users\\usuario\\Documents\\prueba" # sin compilar

./ordenador "C:\\Users\\usuario\\Documents\\prueba"  # con el binario compilado

Reto

  • Que verifique si es un archivo o carpeta, y que ignore las carpetas y solo mueva los archivos
  • Leer un archivo de configuración de los formatos y a la carpeta que se deben mover
  • Verificar si la carpeta ya existe, y evite volver a crearla
  • Verificar que la ruta que de el usuario sea valida
  • En caso que de mal algún parámetro, no de parámetros o se exceda, mandar el mensaje de ayuda de como funciona la aplicación

Descargar

Verificación de cambio de cantidad de archivos y carpetas, dado un directorio

En este proyecto queremos generar un archivo snapshot con el listado de todo el contenido de una carpeta o carpetas, todo contenido en un archivo de configuración. Este archivo de configuración contiene las rutas de las carpetas a analizar. Se generara un archivo con el listado de todos los archivos de esa carpeta, que se utilizara después para hacer la companion, para saber si ha existido algún cambio dentro de ella

read_config.dart
// archivo de configuración
//  - leer el archivo (function)
import 'dart:convert';
import 'dart:io';

/// This function read a json file with the config
Future<Map<String, dynamic>> readFileConfig(String path) async {
  File file = File(path);
  String content = await file.readAsString();
  var json = jsonDecode(content);
  return json;
}

/// This function write json file with the new config
Future<void> writeFileConfig(
    String pathFile, Map<String, dynamic> config) async {
  File file = File(pathFile);
  JsonEncoder encoder = JsonEncoder.withIndent("\t");
  String json = encoder.convert(config);
  await file.writeAsString(json);
}
lib/folder.dar
// Leer el contenido de una carpeta
// generar el archivo base y estar leyendo la misma carpeta
// para comparar

import 'dart:io';

import 'package:cleaner/read_config.dart';

class Folder {
  final String _pathFolder;
  String _pathSnapshot = "";
  late final String _pathJSONConfig;

  Folder(
      {required String pathDir,
      String pathSnapshot = "",
      required String pathJsonConfig})
      : _pathFolder = pathDir,
        _pathSnapshot = pathSnapshot,
        _pathJSONConfig = pathJsonConfig;

  // get list from files and folders from the dir
  Future<List<FileSystemEntity>> _getContentDir() async {
    Directory dir = Directory(_pathFolder);
    return await dir.list(recursive: true).toList();
  }

  /// Creates the file that will contain the list of files and folders,
  /// only gives it the title of the columns
  Future<String> _createFileSnapshot([String path = ""]) async {
    if (path.isEmpty) path = Directory.current.path;
    String time =
        "${DateTime.now().day}_${DateTime.now().month}_${DateTime.now().year}_${DateTime.now().hour}_${DateTime.now().minute}";
    String fullPath =
        "$path${Platform.pathSeparator}snapshot_${_nameFileCSV()}_$time.csv";
    print("Snapshot created at: $fullPath");
    File snapshot = File(fullPath);
    await snapshot.create();
    await snapshot.writeAsString("path, tipo\n");
    _pathSnapshot = snapshot.path;
    return snapshot.path;
  }

  /// Save the content from folder
  Future<void> _saveContent(List<FileSystemEntity> listFiles) async {
    File fileSnapshot = File(_pathSnapshot);

    String row = "";
    for (final element in listFiles) {
      if (element is File) {
        //print("es un ARCHIVO:${element.path}");
        row += "\"${element.path}\",file\n";
      } else if (element is Directory) {
        //print("es una CARPETA:${element.path}");
        row += "\"${element.path}\",folder\n";
      }
      fileSnapshot.writeAsString(row, mode: FileMode.append);
    }
  }

  /// Read data from file snapshot.csv and return a list with content
  Future<List<String>> _readSnapshot([String path = ""]) async {
    if (path.isNotEmpty) _pathSnapshot = path;

    final File snapshotBase = File(_pathSnapshot);
    List<String> files = [];
    for (final row in await snapshotBase.readAsLines()) {
      String path = row.split(",")[0];
      if (path == "path") continue;
      files.add(path);
    }
    return files;
  }

  /// compare the length from snapshot file to list file now
  Future<bool> compareSnapshot([String pathSnapshotBase = ""]) async {
    if (pathSnapshotBase.isNotEmpty) _pathSnapshot = pathSnapshotBase;

    List<String> snapshotBase = await _readSnapshot(_pathSnapshot);
    List<FileSystemEntity> snapshotNow = await _getContentDir();

    return snapshotBase.length == snapshotNow.length;
  }

  // get the name from folder
  String _nameFileCSV() {
    print("El path completo $_pathFolder");
    String name = _pathFolder;
    if (_pathFolder.endsWith(Platform.pathSeparator)) {
      name = _pathFolder.substring(0, _pathFolder.length - 2);
    }

    name = name.substring(name.lastIndexOf(Platform.pathSeparator) + 1);
    print("nombre corto: $name");
    return name;
  }

  // get snapshot from file or create a new
  Future<List<String>> getSnapshot([int position = -1]) async {
    Map<String, dynamic> json = await readFileConfig(_pathJSONConfig);

    if (_pathSnapshot.isNotEmpty && position != -1) {
      _pathSnapshot = List<String>.from(json["snapshot"] ?? [])[position];
    } else {
      await _createFileSnapshot();
      await _saveContent(await _getContentDir());
      List<String> snapshots = List<String>.from(json["snapshot"] ?? []);
      snapshots.add(_pathSnapshot);
      json["snapshot"] = snapshots;
      await writeFileConfig(_pathJSONConfig, json);
    }

    return await _readSnapshot(_pathSnapshot);
  }
}
bin/main.dart
import 'dart:io';

import 'package:cleaner/folder.dart';
import 'package:cleaner/read_config.dart';

// ignore: constant_identifier_names
const HELP = """
cleaner <file_config.json>

cleaner cleaner.config.json
""";

void main(List<String> args) async {
  try {
    if (args.length == 1 && args[0].isNotEmpty && File(args[0]).existsSync()) {
      String pathConfig = args[0];

      Map<String, dynamic> jsonConfig = await readFileConfig(pathConfig);
      List<String> pathDirs = List<String>.from(jsonConfig["directories"]);
      List<String> pathSnapshots =
          List<String>.from(jsonConfig["snapshot"] ?? <String>[]);

      for (int i = 0; i < pathDirs.length; i++) {
        String snapShotPath = pathSnapshots.isNotEmpty ? pathSnapshots[i] : "";
        Folder folder = Folder(
            pathDir: pathDirs[i],
            pathJsonConfig: pathConfig,
            pathSnapshot: snapShotPath);

        await folder.getSnapshot(i);
        bool compare = await folder.compareSnapshot();
        print(compare ? "OK" : "CAMBIO");
      }
    } else {
      print("Error");
      print(HELP);
    }
  } catch (e) {
    print(e);
    print("Error");
    print(HELP);
  }
}

Archivo de configuración que lee la aplicación

Nota: La sección de exclude no esta implementado

cleaner.config.json
{
 "directories": [
  "path absolute 1",
  "path absolute 1"
 ],
 "exclude": {
  "directories": [],
  "ext": []
 }
}

Reto

  • Implementar la sección de exclude, para que evite agregar al snapshot ciertas carpetas y/o extensiones de archivos que se especifiquen en el archivo de configuración.
  • Eliminar las carpetas y archivos nuevos que no estaban en el snapshot original
  • Implementar una base de datos SQLite para optimizar la busque y comparación de archivos
  • Generar y guardar su hash, para hacer mas eficiente la búsqueda
  • Generar un archivo con el listado de archivos y carpetas que no estaban en el snapshot original
  • Todo lo que se te venga a la mente y te pueda ser util

Descargar el compilado para Linux arch64