Skip to content

Commit

Permalink
feat: auto match and rename sub files
Browse files Browse the repository at this point in the history
Create ci.yml
  • Loading branch information
dreamjz committed Nov 22, 2023
1 parent 975f6f6 commit 1f41ee8
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 38 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main


jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version-file: go.mod
cache: false

- name: Run golangci-lint
uses: golangci/[email protected]
with:
version: v1.54
args: --verbose --timeout=3m --issues-exit-code=1
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@
go.work

# Goland file
.idea
.idea

# test files
test-data
100 changes: 67 additions & 33 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,51 +1,85 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
"os"

"errors"
"github.com/dreamjz/sub-renamer/pkg/episode"
"github.com/dreamjz/sub-renamer/pkg/log"
"github.com/spf13/cobra"
"log/slog"
"os"
"path/filepath"
"strings"
)


var logLevel string

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "sub-renamer",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
Short: "Auto-rename video and subtitle files",
Long: `TODO://`,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 2 {
return errors.New("not enough args")
}

logLevel, err := log.ParseLogLevel(logLevel)
if err != nil {
return err
}
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: logLevel}))
slog.SetDefault(logger)

vidDir, subDir := args[0], args[1]
if !filepath.IsAbs(vidDir) {
vidDir, err = filepath.Abs(vidDir)
if err != nil {
return err
}
}
if !filepath.IsAbs(subDir) {
subDir, err = filepath.Abs(subDir)
if err != nil {
return err
}
}

vidMap, err := episode.ParseEpisodes(vidDir)
if err != nil {
return err
}
subMap, err := episode.ParseEpisodes(subDir)
if err != nil {
return err
}

for ep, vidName := range vidMap {
subName, ok := subMap[ep]
if !ok {
continue
}

subExt := filepath.Ext(subName)

newSubName := strings.TrimSuffix(vidName, filepath.Ext(vidName))

err := os.Rename(filepath.Join(subDir, subName), filepath.Join(subDir, newSubName+subExt))
if err != nil {
return err
}
}

return nil
},
}

func init() {
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "debug", "log level")
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}

func init() {
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.

// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.sub-renamer.yaml)")

// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}


5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ module github.com/dreamjz/sub-renamer
go 1.21

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.1 // indirect
github.com/stretchr/testify v1.8.4 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
17 changes: 17 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0=
github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
4 changes: 0 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package main

import "github.com/dreamjz/sub-renamer/cmd"
Expand Down
73 changes: 73 additions & 0 deletions pkg/episode/episode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package episode

import (
"errors"
"os"
"regexp"
"strconv"
)

var ()

func ParseEpisodes(dir string) (map[int]string, error) {
entries, err := os.ReadDir(dir)
if err != nil {
return nil, err
}

if len(entries) < 2 {
return nil, errors.New("number of file must be greater than 2")
}

epStartIndex, err := getEpPosInName(entries[0].Name(), entries[1].Name())
if err != nil {
return nil, err
}

nameEpMap := make(map[int]string, len(entries))
for _, entry := range entries {
fileName := entry.Name()
epNum := getEpisodeNum(fileName, epStartIndex)
nameEpMap[epNum] = fileName
}

return nameEpMap, nil
}

func getEpPosInName(fileName1, fileName2 string) (int, error) {
r := regexp.MustCompile(`\d+`)
numMatchIndex1 := r.FindAllStringIndex(fileName1, -1)
numMatchIndex2 := r.FindAllStringIndex(fileName2, -1)

if len(numMatchIndex1) != len(numMatchIndex2) {
return -1, errors.New("file names are not in same pattern")
}

for _, subMatch := range numMatchIndex1 {
num1 := fileName1[subMatch[0]:subMatch[1]]
num2 := fileName2[subMatch[0]:subMatch[1]]

if num1 != num2 {
return subMatch[0], nil
}
}

return -1, errors.New("episode number not found")
}

func getEpisodeNum(fileName string, start int) int {
end := start + 1
for isDigit(fileName[end]) {
end++
}

ep, _ := strconv.Atoi(fileName[start:end])
return ep
}

func isDigit(b byte) bool {
if b >= '0' && b <= '9' {
return true
}
return false
}
Loading

0 comments on commit 1f41ee8

Please sign in to comment.