Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- param(
- [Parameter(Position = 0)]
- [string]$Arquivo
- )
- $ErrorActionPreference = 'Stop'
- function Selecionar-ArquivoConf {
- Add-Type -AssemblyName System.Windows.Forms
- $dialogo = New-Object System.Windows.Forms.OpenFileDialog
- $dialogo.Title = 'Selecione o arquivo user.conf do AnyDesk'
- $dialogo.Filter = 'Arquivos CONF (*.conf)|*.conf|Todos os arquivos (*.*)|*.*'
- $dialogo.Multiselect = $false
- if ($dialogo.ShowDialog() -ne [System.Windows.Forms.DialogResult]::OK) {
- return $null
- }
- return $dialogo.FileName
- }
- function Ler-ArquivoComCodificacao {
- param([Parameter(Mandatory = $true)][string]$Caminho)
- $bytes = [System.IO.File]::ReadAllBytes($Caminho)
- $encoding = $null
- $texto = $null
- if ($bytes.Length -ge 4 -and $bytes[0] -eq 0x00 -and $bytes[1] -eq 0x00 -and $bytes[2] -eq 0xFE -and $bytes[3] -eq 0xFF) {
- $encoding = New-Object System.Text.UTF32Encoding($true, $true)
- $texto = $encoding.GetString($bytes, 4, $bytes.Length - 4)
- }
- elseif ($bytes.Length -ge 4 -and $bytes[0] -eq 0xFF -and $bytes[1] -eq 0xFE -and $bytes[2] -eq 0x00 -and $bytes[3] -eq 0x00) {
- $encoding = New-Object System.Text.UTF32Encoding($false, $true)
- $texto = $encoding.GetString($bytes, 4, $bytes.Length - 4)
- }
- elseif ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
- $encoding = New-Object System.Text.UTF8Encoding($true)
- $texto = $encoding.GetString($bytes, 3, $bytes.Length - 3)
- }
- elseif ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFF -and $bytes[1] -eq 0xFE) {
- $encoding = New-Object System.Text.UnicodeEncoding($false, $true)
- $texto = $encoding.GetString($bytes, 2, $bytes.Length - 2)
- }
- elseif ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFE -and $bytes[1] -eq 0xFF) {
- $encoding = New-Object System.Text.UnicodeEncoding($true, $true)
- $texto = $encoding.GetString($bytes, 2, $bytes.Length - 2)
- }
- else {
- try {
- $utf8Estrito = New-Object System.Text.UTF8Encoding($false, $true)
- $texto = $utf8Estrito.GetString($bytes)
- $encoding = New-Object System.Text.UTF8Encoding($false)
- }
- catch {
- $encoding = [System.Text.Encoding]::GetEncoding(1252)
- $texto = $encoding.GetString($bytes)
- }
- }
- [PSCustomObject]@{
- Texto = $texto
- Codificacao = $encoding
- }
- }
- function Limpar-Texto {
- param([AllowEmptyString()][string]$Texto)
- if ($null -eq $Texto) { return '' }
- $resultado = [regex]::Replace($Texto, '\s+', ' ')
- return $resultado.Trim(' ', '-', '|')
- }
- function Limpar-Cliente {
- param([AllowEmptyString()][string]$Cliente)
- $resultado = Limpar-Texto $Cliente
- $resultado = [regex]::Replace($resultado, '(?i)ITALICI\s+DISTRIBUIDORA', 'CD DI MADRE')
- $resultado = [regex]::Replace($resultado, '(?i)\bLOJA\s*[123]\b', '')
- $resultado = [regex]::Replace($resultado, '(?i)\bSenha\b', 'SENHA')
- $resultado = [regex]::Replace($resultado, '\s+', ' ')
- $resultado = [regex]::Replace($resultado, '\s+([,;:)])', '$1')
- return $resultado.Trim(' ', '-', '|')
- }
- function Normalizar-Equipamento {
- param([AllowEmptyString()][string]$Equipamento)
- $equip = Limpar-Texto $Equipamento
- if ([string]::IsNullOrWhiteSpace($equip)) { return '' }
- if ($equip -match '(?i)^(SV|DD|DD\s+SV|SV\s+DD|SERVER|SERVIDOR)$') {
- return 'SERVIDOR'
- }
- if ($equip -match '(?i)^AX$') {
- return 'PDV-2'
- }
- if ($equip -match '(?i)^CX$') {
- return 'PDV-1'
- }
- if ($equip -match '(?i)^CX[\s-]*(\d+)$') {
- return ('PDV-' + [int]$Matches[1])
- }
- if ($equip -match '(?i)^PDV$') {
- return 'PDV-1'
- }
- if ($equip -match '(?i)^PDV[\s-]*(\d+)$') {
- return ('PDV-' + [int]$Matches[1])
- }
- return $equip
- }
- function Parece-Equipamento {
- param([AllowEmptyString()][string]$Texto)
- $valor = Limpar-Texto $Texto
- if ([string]::IsNullOrWhiteSpace($valor)) { return $false }
- return $valor -match '(?i)^(SV|DD(?:\s+SV)?|SV\s+DD|AX|CX(?:[\s-]*\d+)?|PDV(?:[\s-]*\d+)?|PC|NT|TERMINAL(?:[\s-]*\d+)?|AUXILIAR|MOTOBOY|NOTEBOOK|BALAN[CÇ]A|SERVIDOR|SERVER|CAIXA(?:[\s-]*\d+)?|TOTEM|TABLET|BAR|COZINHA|IMPRESSORA(?:\s+.*)?)$'
- }
- function Normalizar-Nome {
- param([Parameter(Mandatory = $true)][string]$Nome)
- $nomeOriginal = [regex]::Replace($Nome, '(?i)\bSenha\b', 'SENHA')
- $match = [regex]::Match($nomeOriginal, '^\s*\[(?<codigo>[^\]]+)\]\s*(?<resto>.*)$')
- if (-not $match.Success) {
- return [PSCustomObject]@{
- Nome = $nomeOriginal
- Codigo = ''
- Cliente = $nomeOriginal
- Equipamento = ''
- Reconhecido = $false
- }
- }
- $codigo = Limpar-Texto $match.Groups['codigo'].Value
- if ($codigo -eq '+') { $codigo = 'CLIENTE' }
- $resto = $match.Groups['resto'].Value.Trim()
- $resto = [regex]::Replace($resto, '^\s*\|\s*', '')
- $resto = [regex]::Replace($resto, '^\s*-\s*', '')
- $cliente = ''
- $equipamento = ''
- $indicePipe = $resto.IndexOf('|')
- if ($indicePipe -ge 0) {
- $cliente = $resto.Substring(0, $indicePipe)
- $equipamento = $resto.Substring($indicePipe + 1)
- }
- else {
- $partes = ([regex]'\s+-\s+').Split($resto, 2)
- if ($partes.Count -eq 2 -and (Parece-Equipamento $partes[0])) {
- $equipamento = $partes[0]
- $cliente = $partes[1]
- }
- else {
- $cliente = $resto
- }
- }
- $cliente = Limpar-Cliente $cliente
- $equipamento = Normalizar-Equipamento $equipamento
- $novoNome = "[$codigo] $cliente"
- if (-not [string]::IsNullOrWhiteSpace($equipamento)) {
- $novoNome += " | $equipamento"
- }
- [PSCustomObject]@{
- Nome = $novoNome
- Codigo = $codigo
- Cliente = $cliente
- Equipamento = $equipamento
- Reconhecido = $true
- }
- }
- function Obter-ChaveEquipamento {
- param([AllowEmptyString()][string]$Equipamento)
- if ([string]::IsNullOrWhiteSpace($Equipamento)) {
- return [PSCustomObject]@{ Grupo = 0; Numero = 0; Texto = '' }
- }
- if ($Equipamento -match '(?i)^PDV-(\d+)$') {
- return [PSCustomObject]@{ Grupo = 1; Numero = [int]$Matches[1]; Texto = $Equipamento }
- }
- if ($Equipamento -eq 'SERVIDOR') {
- return [PSCustomObject]@{ Grupo = 3; Numero = 0; Texto = $Equipamento }
- }
- return [PSCustomObject]@{ Grupo = 2; Numero = 0; Texto = $Equipamento }
- }
- function Obter-CaminhoUnico {
- param([Parameter(Mandatory = $true)][string]$CaminhoDesejado)
- if (-not (Test-Path -LiteralPath $CaminhoDesejado)) {
- return $CaminhoDesejado
- }
- $diretorio = [System.IO.Path]::GetDirectoryName($CaminhoDesejado)
- $nome = [System.IO.Path]::GetFileNameWithoutExtension($CaminhoDesejado)
- $extensao = [System.IO.Path]::GetExtension($CaminhoDesejado)
- $contador = 2
- do {
- $alternativo = Join-Path $diretorio ("{0}_{1}{2}" -f $nome, $contador, $extensao)
- $contador++
- } while (Test-Path -LiteralPath $alternativo)
- return $alternativo
- }
- try {
- if ([string]::IsNullOrWhiteSpace($Arquivo)) {
- $Arquivo = Selecionar-ArquivoConf
- if ([string]::IsNullOrWhiteSpace($Arquivo)) {
- Write-Host 'Nenhum arquivo foi selecionado.' -ForegroundColor Yellow
- exit 0
- }
- }
- $Arquivo = [System.IO.Path]::GetFullPath($Arquivo)
- if (-not (Test-Path -LiteralPath $Arquivo -PathType Leaf)) {
- throw "Arquivo não encontrado: $Arquivo"
- }
- $arquivoLido = Ler-ArquivoComCodificacao -Caminho $Arquivo
- $textoCompleto = $arquivoLido.Texto
- $matchesRoster = [regex]::Matches($textoCompleto, '(?m)^(?<prefixo>ad\.roster\.items=)(?<conteudo>[^\r\n]*)')
- if ($matchesRoster.Count -eq 0) {
- throw 'A linha ad.roster.items não foi encontrada. Nenhum arquivo foi alterado.'
- }
- if ($matchesRoster.Count -gt 1) {
- throw 'Mais de uma linha ad.roster.items foi encontrada. Nenhum arquivo foi alterado por segurança.'
- }
- $matchRoster = $matchesRoster[0]
- $conteudoRoster = $matchRoster.Groups['conteudo'].Value
- $terminavaComPontoVirgula = $conteudoRoster.EndsWith(';')
- $segmentos = $conteudoRoster -split ';'
- $itens = New-Object System.Collections.Generic.List[object]
- $segmentosNaoReconhecidos = New-Object System.Collections.Generic.List[string]
- $indiceOriginal = 0
- foreach ($segmento in $segmentos) {
- if ([string]::IsNullOrWhiteSpace($segmento)) { continue }
- $matchItem = [regex]::Match($segmento, '^(?<id1>\d+),(?<id2>\d+),(?<nome>.*),$')
- if (-not $matchItem.Success) {
- $segmentosNaoReconhecidos.Add($segmento)
- $indiceOriginal++
- continue
- }
- $nomeNormalizado = Normalizar-Nome -Nome $matchItem.Groups['nome'].Value
- $codigoGrupo = 2
- $codigoNumero = 0
- if ($nomeNormalizado.Codigo -eq 'CLIENTE') {
- $codigoGrupo = 0
- }
- else {
- $numeroTemporario = 0
- if ([int]::TryParse($nomeNormalizado.Codigo, [ref]$numeroTemporario)) {
- $codigoGrupo = 1
- $codigoNumero = $numeroTemporario
- }
- }
- $chaveEquipamento = Obter-ChaveEquipamento $nomeNormalizado.Equipamento
- $itens.Add([PSCustomObject]@{
- Id1 = $matchItem.Groups['id1'].Value
- Id2 = $matchItem.Groups['id2'].Value
- Nome = $nomeNormalizado.Nome
- Codigo = $nomeNormalizado.Codigo
- Cliente = $nomeNormalizado.Cliente
- Equipamento = $nomeNormalizado.Equipamento
- CodigoGrupo = $codigoGrupo
- CodigoNumero = $codigoNumero
- EquipGrupo = $chaveEquipamento.Grupo
- EquipNumero = $chaveEquipamento.Numero
- IndiceOriginal = $indiceOriginal
- })
- $indiceOriginal++
- }
- $quantidadeAntes = $itens.Count + $segmentosNaoReconhecidos.Count
- $itensOrdenados = $itens | Sort-Object `
- @{ Expression = 'CodigoGrupo'; Ascending = $true }, `
- @{ Expression = 'CodigoNumero'; Ascending = $true }, `
- @{ Expression = 'Codigo'; Ascending = $true }, `
- @{ Expression = 'Cliente'; Ascending = $true }, `
- @{ Expression = 'EquipGrupo'; Ascending = $true }, `
- @{ Expression = 'EquipNumero'; Ascending = $true }, `
- @{ Expression = 'Equipamento'; Ascending = $true }, `
- @{ Expression = 'IndiceOriginal'; Ascending = $true }
- $novosSegmentos = New-Object System.Collections.Generic.List[string]
- foreach ($item in $itensOrdenados) {
- $novosSegmentos.Add(("{0},{1},{2}," -f $item.Id1, $item.Id2, $item.Nome))
- }
- # Segmentos fora do padrão são preservados integralmente no final.
- foreach ($segmentoNaoReconhecido in $segmentosNaoReconhecidos) {
- $novosSegmentos.Add($segmentoNaoReconhecido)
- }
- $novoConteudoRoster = [string]::Join(';', $novosSegmentos)
- if ($terminavaComPontoVirgula -and $novoConteudoRoster.Length -gt 0) {
- $novoConteudoRoster += ';'
- }
- $quantidadeDepois = $novosSegmentos.Count
- if ($quantidadeAntes -ne $quantidadeDepois) {
- throw "Falha de conferência: havia $quantidadeAntes entradas e seriam salvas $quantidadeDepois. Nenhum arquivo foi alterado."
- }
- $inicio = $matchRoster.Index
- $tamanho = $matchRoster.Length
- $novaLinha = $matchRoster.Groups['prefixo'].Value + $novoConteudoRoster
- $novoTextoCompleto = $textoCompleto.Substring(0, $inicio) + $novaLinha + $textoCompleto.Substring($inicio + $tamanho)
- $diretorioArquivo = [System.IO.Path]::GetDirectoryName($Arquivo)
- $nomeSemExtensao = [System.IO.Path]::GetFileNameWithoutExtension($Arquivo)
- $extensao = [System.IO.Path]::GetExtension($Arquivo)
- $carimbo = Get-Date -Format 'yyyyMMdd_HHmmss'
- $caminhoBackup = Join-Path $diretorioArquivo ("{0}.backup_{1}{2}" -f $nomeSemExtensao, $carimbo, $extensao)
- Copy-Item -LiteralPath $Arquivo -Destination $caminhoBackup -Force
- $caminhoSaidaDesejado = Join-Path $diretorioArquivo ("{0}_organizado{1}" -f $nomeSemExtensao, $extensao)
- $caminhoSaida = Obter-CaminhoUnico $caminhoSaidaDesejado
- [System.IO.File]::WriteAllText($caminhoSaida, $novoTextoCompleto, $arquivoLido.Codificacao)
- $caminhoLog = [System.IO.Path]::ChangeExtension($caminhoSaida, '.log.txt')
- $log = @(
- 'ORGANIZADOR DE ANYDESK',
- ('Data: ' + (Get-Date -Format 'dd/MM/yyyy HH:mm:ss')),
- ('Arquivo original: ' + $Arquivo),
- ('Arquivo organizado: ' + $caminhoSaida),
- ('Backup: ' + $caminhoBackup),
- ('Entradas antes: ' + $quantidadeAntes),
- ('Entradas depois: ' + $quantidadeDepois),
- ('Segmentos fora do padrão preservados: ' + $segmentosNaoReconhecidos.Count)
- ) -join [Environment]::NewLine
- [System.IO.File]::WriteAllText($caminhoLog, $log, (New-Object System.Text.UTF8Encoding($true)))
- Write-Host ''
- Write-Host 'Arquivo organizado com sucesso.' -ForegroundColor Green
- Write-Host ("Entradas antes: {0}" -f $quantidadeAntes)
- Write-Host ("Entradas depois: {0}" -f $quantidadeDepois)
- Write-Host ("Backup: {0}" -f $caminhoBackup)
- Write-Host ("Resultado: {0}" -f $caminhoSaida)
- Write-Host ("Relatório: {0}" -f $caminhoLog)
- if ($segmentosNaoReconhecidos.Count -gt 0) {
- Write-Host ("Aviso: {0} segmento(s) fora do padrão foram mantidos sem alteração no final da lista." -f $segmentosNaoReconhecidos.Count) -ForegroundColor Yellow
- }
- Start-Process explorer.exe -ArgumentList ('/select,"' + $caminhoSaida + '"')
- }
- catch {
- Write-Host ''
- Write-Host 'ERRO:' -ForegroundColor Red
- Write-Host $_.Exception.Message -ForegroundColor Red
- exit 1
- }
Advertisement
Add Comment
Please, Sign In to add comment