Skip to content

Commit

Permalink
Merge pull request #9 from vpoluyaktov/fix_Incorrect_github_url
Browse files Browse the repository at this point in the history
Github repo url fixed. Few UI improvements.
  • Loading branch information
vpoluyaktov committed Jan 20, 2024
2 parents a706a87 + 4464790 commit b01048f
Show file tree
Hide file tree
Showing 22 changed files with 152 additions and 96 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,13 @@ To install Audiobook Builder (`abb_ia`) on your system, follow these steps:
4. Run the binary file by executing the command `./abb_ia`. The TUI interface will appear.
5. Follow the instructions on the application interface to do a search, create an audiobook, and upload it to the [Audiobookshelf server](https://www.audiobookshelf.org) if necessary. You can try searching for:

- **Old Time Radio Researches Group: Single Episodes**
- **Old Time Radio Researchers Group: Single Episodes**

- **BBC Radio 4: Radio Drama** (make sure to check if the show is copyrighted).
- **Boxcars711:***
- **Greg Lauer:***
- **Relic Radio:***
- **Radio Memories Network:***
- **CBC: Radio Mystery Theater**

6. Enjoy listening to an audiobook on your favorite device.
Expand Down
24 changes: 24 additions & 0 deletions internal/audiobookshelf/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package audiobookshelf

import "path/filepath"

// Calculate Audiobookshelf directory structure (see: https://www.audiobookshelf.org/docs#book-directory-structure)
func GetDestignationPath(outputDir string, series string, author string) string {
destPath := filepath.Join(outputDir, author)
if series != "" {
destPath = filepath.Join(destPath, author+" - "+series)
}
return destPath
}

func GetDestignationDir(series string, seriesNo string, title string, narrator string) string {
abTitle := ""
if series != "" && seriesNo != "" {
abTitle = seriesNo + ". "
}
abTitle += title
if narrator != "" {
abTitle += " {" + narrator + "}"
}
return abTitle
}
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func Load() {
"History",
"Podcast",
"Nonfiction",
"Education",
"News",
"Speech",
}
Expand Down
7 changes: 6 additions & 1 deletion internal/controller/boot_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,12 @@ func (c *BootController) checkFFmpeg() bool {

func (c *BootController) checkNewVersion() {

latestVersion, err := github.GetLatestVersion(config.Instance().GetRepoOwner(), config.Instance().GetRepoName())
if config.Instance().AppVersion() == "0.0.0" {
// this is local dev version. Don't check new version
return
}
git := github.NewClient(config.Instance().GetRepoOwner(), config.Instance().GetRepoName())
latestVersion, err := git.GetLatestVersion()
if err != nil {
logger.Error("Can't check new version: " + err.Error())
return
Expand Down
5 changes: 3 additions & 2 deletions internal/controller/build_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,10 @@ func (c *BuildController) dispatchMessage(m *mq.Message) {

func (c *BuildController) stopBuild(cmd *dto.StopCommand) {
c.stopFlag = true
logger.Debug(mq.BuildController + ": Received StopBuild command")
logger.Info(fmt.Sprintf("Building the audiobook: %s - %s...", c.ab.Author, c.ab.Title))
}

func (c *BuildController) startBuild(cmd *dto.BuildCommand) {
logger.Info(mq.BuildController + " received " + cmd.String())
c.stopFlag = false
c.startTime = time.Now()
c.ab = cmd.Audiobook
Expand All @@ -94,6 +93,8 @@ func (c *BuildController) startBuild(cmd *dto.BuildCommand) {
c.mq.SendMessage(mq.BuildController, mq.Footer, &dto.UpdateStatus{Message: "Building audiobook..."}, false)
c.mq.SendMessage(mq.BuildController, mq.Footer, &dto.SetBusyIndicator{Busy: true}, false)

logger.Info(fmt.Sprintf("Building the audiobook: %s - %s...", c.ab.Author, c.ab.Title))

// prepare .mp3 file list
c.createFilesLists(c.ab)
// prepare metadata
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/cleanup_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (c *CleanupController) dispatchMessage(m *mq.Message) {
}

func (c *CleanupController) cleanUp(cmd *dto.CleanupCommand, requestor string) {
logger.Info(mq.CleanupController + " received " + cmd.String())
logger.Debug(mq.CleanupController + " received " + cmd.String())
c.ab = cmd.Audiobook

if !(c.ab.Config.IsSaveMock() || c.ab.Config.IsUseMock()) {
Expand Down
26 changes: 9 additions & 17 deletions internal/controller/copy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"path/filepath"
"time"

"abb_ia/internal/audiobookshelf"
"abb_ia/internal/dto"
"abb_ia/internal/utils"

Expand Down Expand Up @@ -85,7 +86,6 @@ func (c *CopyController) dispatchMessage(m *mq.Message) {

func (c *CopyController) startCopy(cmd *dto.CopyCommand) {
c.startTime = time.Now()
logger.Info(mq.CopyController + " received " + cmd.String())
c.ab = cmd.Audiobook

// update part size and whole audiobook size after re-encoding
Expand All @@ -106,6 +106,8 @@ func (c *CopyController) startCopy(cmd *dto.CopyCommand) {
c.mq.SendMessage(mq.CopyController, mq.Footer, &dto.UpdateStatus{Message: "Copying audiobook files to Audiobookshelf..."}, false)
c.mq.SendMessage(mq.CopyController, mq.Footer, &dto.SetBusyIndicator{Busy: true}, false)

logger.Info(fmt.Sprintf("Copying the audiobook: %s - %s to %s/...", c.ab.Author, c.ab.Title, c.ab.Config.OutputDir))

c.stopFlag = false
c.filesCopy = make([]fileCopy, len(c.ab.Parts))
jd := utils.NewJobDispatcher(c.ab.Config.GetConcurrentDownloaders())
Expand Down Expand Up @@ -141,27 +143,17 @@ func (c *CopyController) copyAudiobookPart(ab *dto.Audiobook, partId int) {
defer file.Close()

// Calculate Audiobookshelf directory structure (see: https://www.audiobookshelf.org/docs#book-directory-structure)
destPath := filepath.Join(ab.Config.GetOutputDir(), ab.Author)
if ab.Series != "" {
destPath = filepath.Join(destPath, ab.Author+" - "+ab.Series)
}
abTitle := ""
if ab.Series != "" && ab.SeriesNo != "" {
abTitle = ab.SeriesNo + ". "
}
abTitle += ab.Title
if ab.Narator != "" {
abTitle += " {" + ab.Narator + "}"
}
destPath := audiobookshelf.GetDestignationPath(ab.Config.GetOutputDir(), ab.Series, ab.Author)
destDir := audiobookshelf.GetDestignationDir(ab.Series, ab.SeriesNo, ab.Title, ab.Narrator)

destPath = filepath.Clean(filepath.Join(destPath, abTitle, filepath.Base(part.M4BFile)))
destDir := filepath.Dir(destPath)
filePath := filepath.Clean(filepath.Join(destPath, destDir, filepath.Base(part.M4BFile)))
fullPath := filepath.Dir(filePath)

if err := os.MkdirAll(destDir, 0750); err != nil {
if err := os.MkdirAll(fullPath, 0750); err != nil {
logger.Error("Can't create output directory: " + err.Error())
return
}
f, err := os.OpenFile(destPath, os.O_CREATE|os.O_WRONLY, 0644)
f, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
logger.Fatal("Can't create Audiobookshelf .m4b file: " + err.Error())
return
Expand Down
4 changes: 3 additions & 1 deletion internal/controller/download_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (c *DownloadController) stopDownload(cmd *dto.StopCommand) {

func (c *DownloadController) startDownload(cmd *dto.DownloadCommand) {
c.startTime = time.Now()
logger.Info(mq.DownloadController + " received " + cmd.String())

c.mq.SendMessage(mq.DownloadController, mq.Footer, &dto.UpdateStatus{Message: "Downloading mp3 files..."}, false)
c.mq.SendMessage(mq.DownloadController, mq.Footer, &dto.SetBusyIndicator{Busy: true}, false)

Expand All @@ -75,6 +75,8 @@ func (c *DownloadController) startDownload(cmd *dto.DownloadCommand) {
c.ab.TotalSize = item.TotalSize
c.ab.TotalDuration = item.TotalLength

logger.Info(fmt.Sprintf("Downloading IA item: %s - %s...", c.ab.Author, c.ab.Title))

// update Book info on UI
c.mq.SendMessage(mq.DownloadController, mq.DownloadPage, &dto.DisplayBookInfoCommand{Audiobook: c.ab}, true)

Expand Down
3 changes: 2 additions & 1 deletion internal/controller/encoding_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ func (c *EncodingController) stopEncoding(cmd *dto.StopCommand) {

func (c *EncodingController) startEncoding(cmd *dto.EncodeCommand) {
c.startTime = time.Now()
logger.Info(mq.EncodingController + " received " + cmd.String())

c.ab = cmd.Audiobook
c.stopFlag = false
Expand All @@ -79,6 +78,8 @@ func (c *EncodingController) startEncoding(cmd *dto.EncodeCommand) {
c.mq.SendMessage(mq.EncodingController, mq.Footer, &dto.UpdateStatus{Message: "Re-encoding mp3 files..."}, false)
c.mq.SendMessage(mq.EncodingController, mq.Footer, &dto.SetBusyIndicator{Busy: true}, false)

logger.Info(fmt.Sprintf("Re-encoding mp3 files: %s - %s...", c.ab.Author, c.ab.Title))

// re-encode files
jd := utils.NewJobDispatcher(c.ab.Config.GetConcurrentEncoders())
for i, f := range c.ab.Mp3Files {
Expand Down
9 changes: 7 additions & 2 deletions internal/controller/search_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (c *SearchController) dispatchMessage(m *mq.Message) {
}

func (c *SearchController) search(cmd *dto.SearchCommand) {
logger.Info(mq.SearchController + " received " + cmd.String())
logger.Info(fmt.Sprintf("Searching for: %s - %s", cmd.Condition.Author, cmd.Condition.Title))
c.mq.SendMessage(mq.SearchController, mq.Footer, &dto.UpdateStatus{Message: "Fetching Internet Archive items..."}, false)
c.mq.SendMessage(mq.SearchController, mq.Footer, &dto.SetBusyIndicator{Busy: true}, false)
c.totalItemsFetched = 0
Expand All @@ -73,12 +73,14 @@ func (c *SearchController) search(cmd *dto.SearchCommand) {
c.mq.SendMessage(mq.SearchController, mq.Footer, &dto.UpdateStatus{Message: ""}, false)
c.mq.SendMessage(mq.SearchController, mq.SearchPage, &dto.SearchComplete{Condition: cmd.Condition}, false)
if itemsFetched == 0 {
logger.Info("Nothing found")
c.mq.SendMessage(mq.SearchController, mq.SearchPage, &dto.NothingFoundError{Condition: cmd.Condition}, false)
} else {
logger.Info(fmt.Sprintf("Items fetched: %d", c.totalItemsFetched))
}
}

func (c *SearchController) getGetNextPage(cmd *dto.GetNextPageCommand) {
logger.Info(mq.SearchController + " received " + cmd.String())
c.mq.SendMessage(mq.SearchController, mq.Footer, &dto.UpdateStatus{Message: "Fetching Internet Archive items..."}, false)
c.mq.SendMessage(mq.SearchController, mq.Footer, &dto.SetBusyIndicator{Busy: true}, false)
resp := c.ia.GetNextPage(cmd.Condition.Author, cmd.Condition.Title, "audio")
Expand All @@ -93,7 +95,10 @@ func (c *SearchController) getGetNextPage(cmd *dto.GetNextPageCommand) {
c.mq.SendMessage(mq.SearchController, mq.Footer, &dto.UpdateStatus{Message: ""}, false)
c.mq.SendMessage(mq.SearchController, mq.SearchPage, &dto.SearchComplete{Condition: cmd.Condition}, false)
if itemsFetched == 0 {
logger.Info("Last page reached")
c.mq.SendMessage(mq.SearchController, mq.SearchPage, &dto.LastPageMessage{Condition: cmd.Condition}, false)
} else {
logger.Info(fmt.Sprintf("Items fetched: %d", c.totalItemsFetched))
}
}

Expand Down
7 changes: 5 additions & 2 deletions internal/controller/upload_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@ func (c *UploadController) dispatchMessage(m *mq.Message) {
}

func (c *UploadController) absScan(cmd *dto.AbsScanCommand) {
logger.Info(mq.UploadController + " received " + cmd.String())

ab := cmd.Audiobook
url := ab.Config.GetAudiobookshelfUrl()
username := ab.Config.GetAudiobookshelfUser()
password := ab.Config.GetAudiobookshelfPassword()
libraryName := ab.Config.GetAudiobookshelfLibrary()


if url != "" && username != "" && password != "" && libraryName != "" {
absClient := audiobookshelf.NewClient(url)
err := absClient.Login(username, password)
Expand Down Expand Up @@ -94,13 +95,15 @@ func (c *UploadController) absScan(cmd *dto.AbsScanCommand) {

func (c *UploadController) absUpload(cmd *dto.AbsUploadCommand) {
c.startTime = time.Now()
logger.Info(mq.UploadController + " received " + cmd.String())

c.ab = cmd.Audiobook
url := c.ab.Config.GetAudiobookshelfUrl()
username := c.ab.Config.GetAudiobookshelfUser()
password := c.ab.Config.GetAudiobookshelfPassword()
libraryName := c.ab.Config.GetAudiobookshelfLibrary()

logger.Info(fmt.Sprintf("Uploading the audiobook: %s - %s to %s...", c.ab.Author, c.ab.Title, c.ab.Config.AudiobookshelfUrl))

if url != "" && username != "" && password != "" && libraryName != "" {
absClient := audiobookshelf.NewClient(url)
err := absClient.Login(username, password)
Expand Down
2 changes: 1 addition & 1 deletion internal/dto/audiobook.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Audiobook struct {
Genre string
Series string
SeriesNo string
Narator string
Narrator string
Year string
CoverURL string
CoverFile string
Expand Down
46 changes: 34 additions & 12 deletions internal/github/client.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
package github

import (
"encoding/json"
"fmt"
"net/http"
)

type GithubClient struct {
token string
repoOwner string
repoName string
}

func NewClient(repoOwner string, repoName string) (*GithubClient) {
c := &GithubClient{repoOwner: repoOwner, repoName: repoName}
return c
}

func NewClient(token string) (*GithubClient, error) {
c := &GithubClient{token: token}
return c, nil
type Release struct {
TagName string `json:"tag_name"`
}

func (c *GithubClient) GetLatestVer(owner string, repo string) (string, error) {
ver := ""
func (c *GithubClient) GetLatestVersion() (string, error) {
url := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", c.repoOwner, c.repoName)

// curl -L \
// -H "Accept: application/vnd.github+json" \
// -H "Authorization: Bearer <TOKEN>" \
// -H "X-GitHub-Api-Version: 2022-11-28" \
// https://api.github.com/repos/vpoluyaktov/abb_ia/releases/latest
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()

return ver, nil
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("failed to fetch latest release: %s", resp.Status)
}

var release Release
err = json.NewDecoder(resp.Body).Decode(&release)
if err != nil {
return "", err
}

return release.TagName, nil
}

28 changes: 0 additions & 28 deletions internal/github/utils.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,11 @@
package github

import (
"encoding/json"
"fmt"
"net/http"

"github.com/hashicorp/go-version"
)

type Release struct {
TagName string `json:"tag_name"`
}

func GetLatestVersion(owner string, repo string) (string, error) {
url := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", owner, repo)

resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("failed to fetch latest release: %s", resp.Status)
}

var release Release
err = json.NewDecoder(resp.Body).Decode(&release)
if err != nil {
return "", err
}

return release.TagName, nil
}

func CompareVersions(version1 string, version2 string) (int, error) {
v1, err := version.NewVersion(version1)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions internal/ia/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ type SearchResponse struct {
BackupLocation string `json:"backup_location,omitempty"`
ExternalIdentifier strArray `json:"external-identifier,omitempty"`
Genre strArray `json:"genre,omitempty"`
Language string `json:"language,omitempty"`
Language strArray `json:"language,omitempty"`
Licenseurl string `json:"licenseurl,omitempty"`
StrippedTags strArray `json:"stripped_tags,omitempty"`
} `json:"docs"`
Expand Down Expand Up @@ -92,7 +92,7 @@ type ItemDetails struct {
Files map[string]struct {
Source string `json:"source"`
Format string `json:"format"`
Original string `json:"original"`
Original strArray `json:"original"`
Length string `json:"length"`
Mtime string `json:"mtime"`
Size string `json:"size"`
Expand Down
Loading

0 comments on commit b01048f

Please sign in to comment.