func processFREReport(db *sql.DB, dataDir string, year int) error {
	url := fmt.Sprintf("http://dados.cvm.gov.br/dados/CIA_ABERTA/DOC/FRE/DADOS/fre_cia_aberta_%d.zip", year)
	zipfile := fmt.Sprintf("%s/fre_%d.zip", dataDir, year)
	fmt.Print("[          ] Download do arquivo FRE")
	files, err := fetchFiles(url, dataDir, zipfile)
	if err != nil {
		return err
	}
	patterns := []string{"fre_cia_aberta_distribuicao_capital_%d.csv"}
	for _, p := range patterns {
		pattern := fmt.Sprintf(p, year)
		reqFile, err := findFile(files, pattern)
		if err == ErrItemNotFound {
			filesCleanup(files)
			return fmt.Errorf("arquivo %s não encontrado", reqFile)
		}
		if err = parsers.ImportCsv(db, "FRE", reqFile); err != nil {
			return err
		}
	}
	filesCleanup(files)  
	return nil
}
processFREReport download FRE (Reference Form) files from CVM and store
them on DB.
package fetch
import (
	"database/sql"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
	"github.com/dude333/rapina/parsers"
	"github.com/dustin/go-humanize"
	_ "github.com/mattn/go-sqlite3"  
	"github.com/pkg/errors"
)
var (
	ErrFileNotFound = errors.New("file not found")
	ErrItemNotFound = errors.New("item not found")
)
func CVM(db *sql.DB, dataDir string) error {
	now := time.Now().Year()
	try(processQuarterlyReport, db, dataDir, "Arquivo ITR não encontrado", now, now-1, 2)
	try(processAnnualReport, db, dataDir, "Arquivo DFP não encontrado", now-1, 2010, 2)
	try(processFREReport, db, dataDir, "Arquivo FRE não encontrado", now-1, 2010, 2)
	return nil
}
type fn func(*sql.DB, string, int) error
func try(f fn, db *sql.DB, dataDir, errMsg string, now, limit, n int) {
	tries := n
	var err error
	for year := now; tries > 0 && year >= limit; year-- {
		fmt.Printf("[>] %d ---------------------\n", year)
		err = f(db, dataDir, year)
		if err == ErrFileNotFound {
			fmt.Printf("[x] %s\n", errMsg)
			tries--
			continue
		} else if err != nil {
			fmt.Printf("[x] Erro ao processar arquivo de %d: %v\n", year, err)
			tries--
		} else {
			tries = n
		}
	}
}
func processAnnualReport(db *sql.DB, dataDir string, year int) error {
	url := fmt.Sprintf("http://dados.cvm.gov.br/dados/CIA_ABERTA/DOC/DFP/DADOS/dfp_cia_aberta_%d.zip", year)
	zipfile := fmt.Sprintf("%s/dfp_%d.zip", dataDir, year)
	fmt.Print("[          ] Download do arquivo DFP")
	files, err := fetchFiles(url, dataDir, zipfile)
	if err != nil {
		return err
	}
	dataTypes := []string{"BPA", "BPP", "DRE", "DFC_MD", "DFC_MI", "DVA"}
	for _, dt := range dataTypes {
		pattern := fmt.Sprintf("dfp_cia_aberta_%s_con_%d.csv", dt, year)
		reqFile, err := findFile(files, pattern)
		if err == ErrItemNotFound {
			filesCleanup(files)
			return fmt.Errorf("arquivo %s não encontrado", reqFile)
		}
		if err = parsers.ImportCsv(db, dt, reqFile); err != nil {
			return err
		}
	}
	filesCleanup(files)  
	return nil
}
func processQuarterlyReport(db *sql.DB, dataDir string, year int) error {
	url := fmt.Sprintf("http://dados.cvm.gov.br/dados/CIA_ABERTA/DOC/ITR/DADOS/ITR_CIA_ABERTA_%d.zip", year)
	zipfile := fmt.Sprintf("%s/itr_%d.zip", dataDir, year)
	fmt.Print("[          ] Download do arquivo ITR")
	files, err := fetchFiles(url, dataDir, zipfile)
	if err != nil {
		return err
	}
	dataTypes := []string{"BPA", "BPP", "DRE", "DFC_MD", "DFC_MI", "DVA"}
	for _, dt := range dataTypes {
		pattern := fmt.Sprintf("ITR_CIA_ABERTA_%s_con_%d.csv", dt, year)
		reqFile, err := findFile(files, pattern)
		if err == ErrItemNotFound {
			filesCleanup(files)
			return fmt.Errorf("arquivo %s não encontrado", reqFile)
		}
		if err = parsers.ImportCsv(db, dt+"_ITR", reqFile); err != nil {
			return err
		}
	}
	filesCleanup(files)  
	return nil
}