// NNM-Club torrent filess mass downloader // Created for Uploaders group // Copyright (c) 2012-2020 Vladimir "fat0troll" Hodakov package fetcher import ( "os" "path/filepath" "strconv" "time" "github.com/anacrolix/torrent/metainfo" "github.com/dustin/go-humanize" "github.com/kennygrant/sanitize" ) func createOutputDir(prefix string, forumID int) { path, _ := filepath.Abs(filepath.Join(prefix, strconv.Itoa(forumID))) if err := os.Mkdir(path, os.ModePerm); err != nil { dlog.Fatal().Str("путь создания", path).Err(err).Msg("Невозможно создать поддиректорию для торрент-файлов") } outputDirPath = path } func download(topic *forumTopic) { forumTopicInProgress++ dlog.Info().Str("название топика", topic.Name).Int("количество топиков", len(forumTopics)). Int("номер топика", forumTopicInProgress).Msg("Скачивается топик") fileName, err := downloadFile(topic.Link, true) if err != nil { dlog.Error().Err(err).Str("название топика", topic.Name).Msg("Не удалось загрузить страницу топика. Пропуск") return } querier, err := obtainQuerier(fileName) if err != nil { dlog.Error().Err(err).Str("название топика", topic.Name).Str("ссылка на топик", topic.Link). Msg("Не удалось получить обработчик для страницы топика. Пропуск") return } lastModified := getLastModeratedDate(querier) if lastModified == "" { dlog.Warn().Str("название топика", topic.Name).Str("ссылка на топик", topic.Link). Msg("Топик не проверен модератором. Пропуск") return } downloadLink := getDownloadLink(querier) if downloadLink == "" { dlog.Warn().Str("название топика", topic.Name).Str("ссылка на топик", topic.Link). Msg("Не найдена ссылка для скачивания торрента. Пропуск") return } tempF, err := downloadFile("https://"+c.Config.URL+"/forum/"+downloadLink, false) if err != nil { dlog.Warn().Err(err).Str("название топика", topic.Name).Str("ссылка на топик", topic.Link). Msg("Не удалось скачать торрент-файл через несколько попыток. Пропуск") return } result := outputDirPath + "/" + lastModified + "-" + sanitize.BaseName(topic.Name) + ".torrent" err = moveFile(tempF, result) if err != nil { dlog.Warn().Err(err).Str("название топика", topic.Name).Str("ссылка на топик", topic.Link). Msg("Не удалось сохранить торрент-файл. Пропуск") return } f, _ := os.Open(result) defer f.Close() // Check downloaded torrent and get some metadata metadata, err := metainfo.Load(f) if err != nil { dlog.Warn().Err(err).Str("название топика", topic.Name).Str("ссылка на топик", topic.Link). Msg("Скачанный файл не является торрент-файлом. Пропуск") return } unmarshalledMetadata, _ := metadata.UnmarshalInfo() totalLength += unmarshalledMetadata.TotalLength() } func fetch(forumID int) { startPage := "https://" + c.Config.URL + "/forum/viewforum.php?f=" + strconv.Itoa(forumID) time.Sleep(5 * time.Second) startPageFile, err := downloadFile(startPage, true) if err != nil { dlog.Error().Err(err).Msg("Не удалось получить данные с форума") } if uberDebug { dlog.Info().Str("имя файла", startPageFile).Msg("Получена стартовая страница форума") } err = setQuerier(startPageFile, "forumPage", 1) if err != nil { dlog.Fatal().Err(err).Msg("Не удалось создать обработчик для страницы") } dlog.Info().Str("название форума", getForumName(forumPages[1])).Msg("Определён форум для загрузки") getNavigation(forumPages[1]) downloadAdditionalPages() for _, forumPage := range forumPages { getTopics(forumPage) } dlog.Info().Int("топиков для скачивания", len(forumTopics)).Msg("Определены все топики для скачивания") for _, forumTopic := range forumTopics { download(forumTopic) } } func printStats() { dlog.Info().Int("топиков обработано", len(forumTopics)). Str("объём раздела при полном скачивании", humanize.Bytes(uint64(totalLength))). Str("директория с торрент-файлами", outputDirPath). Msg("Работа завершена успешно. Загруженные торрент-файлы расположены в директории, указанной при старте.") }