Skip to content

Commit b1dec23

Browse files
authored
Merge pull request #10 from NullpointerW/v0.07
V0.07
2 parents 8b7bc23 + f283c5f commit b1dec23

File tree

6 files changed

+318
-152
lines changed

6 files changed

+318
-152
lines changed

net/cmd/command.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package cmd
22

3-
import "encoding/json"
3+
import (
4+
"encoding/json"
5+
"github.com/NullpointerW/anicat/net/cmd/view"
6+
)
47

58
type cTyp int
69

@@ -12,6 +15,7 @@ const (
1215
LsItems
1316
Status
1417
Stop
18+
Rename
1519
)
1620

1721
type Cmd struct {
@@ -32,3 +36,31 @@ type AddFlag struct {
3236
type LsiFlag struct {
3337
SearchList bool `json:"searchList"`
3438
}
39+
40+
type CommandCase struct {
41+
invoke func(Cmd, view.Render) (string, error)
42+
flag cTyp
43+
}
44+
45+
func NewCommandCase(flag cTyp, invokeFunc func(Cmd, view.Render) (string, error)) CommandCase {
46+
return CommandCase{invokeFunc, flag}
47+
}
48+
49+
type Selector struct {
50+
cases []CommandCase
51+
}
52+
53+
func (sl *Selector) Select(c Cmd, r view.Render) (string, error) {
54+
for _, _case := range sl.cases {
55+
if c.Cmd == _case.flag {
56+
return _case.invoke(c, r)
57+
}
58+
}
59+
return "", nil
60+
}
61+
62+
func NewSelector(cases ...CommandCase) *Selector {
63+
return &Selector{
64+
cases: cases,
65+
}
66+
}

net/server/router.go

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@ import (
1313
"github.com/NullpointerW/anicat/subject"
1414
)
1515

16-
func route(c cmd.Cmd, r view.Render) (resp string, err error) {
17-
switch c.Cmd {
18-
case cmd.Add:
16+
var CmdSelector *cmd.Selector
17+
18+
func init() {
19+
add := cmd.NewCommandCase(cmd.Add, func(c cmd.Cmd, r view.Render) (resp string, err error) {
1920
return addSubjProcess(c, false)
20-
case cmd.AddFeed:
21+
})
22+
addFeed := cmd.NewCommandCase(cmd.AddFeed, func(c cmd.Cmd, r view.Render) (resp string, err error) {
2123
return addSubjProcess(c, true)
22-
case cmd.Remove:
24+
})
25+
remove := cmd.NewCommandCase(cmd.Remove, func(c cmd.Cmd, r view.Render) (resp string, err error) {
2326
i, er := strconv.Atoi(c.Arg)
2427
if er != nil && c.Arg != "*" {
2528
err = er
@@ -33,11 +36,13 @@ func route(c cmd.Cmd, r view.Render) (resp string, err error) {
3336
}
3437
subject.Delete <- pip
3538
return "ok", pip.Error()
36-
case cmd.Ls:
39+
})
40+
list := cmd.NewCommandCase(cmd.Ls, func(c cmd.Cmd, r view.Render) (resp string, err error) {
3741
ls := subject.Mgr.List()
3842
resp = r.Ls(ls)
3943
return
40-
case cmd.LsItems:
44+
})
45+
listItem := cmd.NewCommandCase(cmd.LsItems, func(c cmd.Cmd, r view.Render) (resp string, err error) {
4146
flag := new(cmd.LsiFlag)
4247
err = json.Unmarshal(c.Raw, &flag)
4348
if err != nil {
@@ -64,7 +69,8 @@ func route(c cmd.Cmd, r view.Render) (resp string, err error) {
6469
}
6570
resp = ls
6671
return
67-
case cmd.Status:
72+
})
73+
status := cmd.NewCommandCase(cmd.Status, func(c cmd.Cmd, r view.Render) (resp string, err error) {
6874
i, er := strconv.Atoi(c.Arg)
6975
if er != nil {
7076
err = er
@@ -92,7 +98,8 @@ func route(c cmd.Cmd, r view.Render) (resp string, err error) {
9298
resp = r.Status(subj, hs...)
9399
}
94100
return
95-
case cmd.Stop:
101+
})
102+
stop := cmd.NewCommandCase(cmd.Stop, func(c cmd.Cmd, r view.Render) (resp string, err error) {
96103
for _, s := range subject.Mgr.List() {
97104
if !s.Terminate {
98105
s.Exit()
@@ -101,9 +108,41 @@ func route(c cmd.Cmd, r view.Render) (resp string, err error) {
101108
subject.Mgr.Exit()
102109
resp = "exited."
103110
return
104-
default:
105-
return
106-
}
111+
})
112+
113+
rename := cmd.NewCommandCase(cmd.Rename, func(c cmd.Cmd, r view.Render) (resp string, err error) {
114+
i, err := strconv.Atoi(c.Arg)
115+
if err != nil {
116+
return
117+
}
118+
s := subject.Mgr.Get(i)
119+
if s == nil {
120+
err = errs.ErrSubjectNotFound
121+
return
122+
}
123+
newName := new(string)
124+
err = json.Unmarshal(c.Raw, newName)
125+
if err != nil {
126+
return "", err
127+
}
128+
op := subject.NewOperate(subject.Rename, *newName)
129+
if s.Terminate {
130+
<-s.Exited
131+
err = s.Rename(*newName)
132+
} else {
133+
select {
134+
case <-s.Exited:
135+
err = s.Rename(*newName)
136+
case s.OperationChan <- op:
137+
}
138+
}
139+
return "ok", err
140+
})
141+
CmdSelector = cmd.NewSelector(add, addFeed, remove, list, listItem, status, stop, rename)
142+
}
143+
144+
func route(c cmd.Cmd, r view.Render) (resp string, err error) {
145+
return CmdSelector.Select(c, r)
107146
}
108147

109148
func addSubjProcess(c cmd.Cmd, isFeed bool) (resp string, err error) {

subject/filter.go

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package subject
2+
3+
import (
4+
"fmt"
5+
"github.com/NullpointerW/anicat/log"
6+
"regexp"
7+
"strings"
8+
)
9+
10+
func BuildFilterPerlReg(vbs []string) string {
11+
var reg string
12+
const tmp = `(?=.*?%s)`
13+
if len(vbs) != 0 {
14+
reg += "(?i)"
15+
for _, ct := range vbs {
16+
vb := strings.ReplaceAll(ct, ",", "|")
17+
vb = "(" + vb + ")"
18+
reg += fmt.Sprintf(tmp, vb)
19+
}
20+
return reg
21+
} else {
22+
return ""
23+
}
24+
}
25+
26+
func BuildFilterRegs(vbs []string) []string {
27+
if len(vbs) != 0 {
28+
regs := make([]string, 0, len(vbs))
29+
for _, ct := range vbs {
30+
vb := strings.ReplaceAll(ct, ",", "|")
31+
vb = "(?i)" + vb
32+
regs = append(regs, vb)
33+
}
34+
return regs
35+
} else {
36+
return nil
37+
}
38+
}
39+
40+
func FilterWithRegs(s string, contains, exclusions []string) bool {
41+
var (
42+
containOk, exclusionOk bool
43+
)
44+
if len(contains) == 0 {
45+
containOk = true
46+
}
47+
if len(exclusions) == 0 {
48+
exclusionOk = true
49+
}
50+
if !containOk {
51+
//containOks := make([]bool, 0, len(contains))
52+
for _, reg := range contains {
53+
var ok bool
54+
csre, err := regexp.Compile(reg)
55+
if err != nil {
56+
log.Error(log.Struct{"err", err}, "globalFilter: contains regexp compile failed")
57+
ok = true
58+
} else {
59+
ok = csre.MatchString(s)
60+
log.Debug(log.Struct{"containRegexp", csre.String(), "matchingString", s, "matched", ok})
61+
//improve: break immediately
62+
if !ok {
63+
return false
64+
}
65+
}
66+
//containOks = append(containOks, ok)
67+
}
68+
containOk = true
69+
//for _, ok := range containOks {
70+
// if !ok {
71+
// containOk = false
72+
// break
73+
// }
74+
//}
75+
}
76+
77+
if !exclusionOk {
78+
//exclusionOks := make([]bool, 0, len(exclusions))
79+
for _, reg := range exclusions {
80+
var ok bool
81+
clsre, err := regexp.Compile(reg)
82+
if err != nil {
83+
log.Error(log.Struct{"err", err}, "globalFilter: exclusions regexp compile failed")
84+
ok = true
85+
} else {
86+
ok = !clsre.MatchString(s)
87+
log.Debug(log.Struct{"exclusionRegexp", clsre.String(), "matchingString", s, "matched", ok})
88+
if !ok {
89+
return false
90+
}
91+
}
92+
//exclusionOks = append(exclusionOks, ok)
93+
}
94+
exclusionOk = true
95+
//for _, ok := range exclusionOks {
96+
// if !ok {
97+
// exclusionOk = false
98+
// break
99+
// }
100+
//}
101+
}
102+
return containOk && exclusionOk
103+
}
104+
105+
func FilterWithCustomReg(s string, e Extra) bool {
106+
clsOk, exlOk := true, true
107+
if cls := e.RssOption.MustContain; cls != "" {
108+
clsReg, err := regexp.Compile(cls)
109+
if err != nil {
110+
log.Error(log.Struct{"err", err}, "customFilter: contains regexp compile failed")
111+
} else {
112+
clsOk = clsReg.MatchString(s)
113+
}
114+
}
115+
if exl := e.RssOption.MustNotContain; exl != "" {
116+
exlReg, err := regexp.Compile(exl)
117+
if err != nil {
118+
log.Error(log.Struct{"err", err}, "customFilter: contains regexp compile failed")
119+
} else {
120+
exlOk = !exlReg.MatchString(s)
121+
}
122+
}
123+
return clsOk && exlOk
124+
}
125+
126+
func FilterWithCustom(s string, e Extra) bool {
127+
cls, ext := strings.Fields(e.RssOption.MustContain), strings.Fields(e.RssOption.MustNotContain)
128+
return FilterWithRegs(s, cls, ext)
129+
}

subject/manager.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,26 @@ func (m *Manager) clear() {
106106
}
107107

108108
func (m *Manager) Exit() {
109+
m.mu.Lock()
110+
defer m.mu.Unlock()
111+
for _, s := range m.sto {
112+
if !s.Terminate {
113+
s.Exit()
114+
}
115+
}
109116
m.wg.Wait()
110117
}
111118

119+
func (m *Manager) Range(f func(int, *Subject) bool) {
120+
m.mu.Lock()
121+
defer m.mu.Unlock()
122+
for i, s := range m.sto {
123+
if !f(i, s) {
124+
return
125+
}
126+
}
127+
}
128+
112129
func StartManagement() {
113130
for {
114131
select {

subject/runner.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
func (s *Subject) runtimeInit(reload bool) {
2222
s.Exited = make(chan struct{})
2323
if s.Terminate {
24+
close(s.Exited)
2425
Mgr.Add(s)
2526
return
2627
}
@@ -31,6 +32,7 @@ func (s *Subject) runtimeInit(reload bool) {
3132
if s.Pushed == nil {
3233
s.Pushed = make(map[string]string)
3334
}
35+
s.OperationChan = make(chan Operate)
3436
Mgr.Add(s)
3537
go s.run(ctx, reload)
3638
go JellyfinMetaDataHelper(s.Path, s.FolderName, s.Exited)
@@ -46,6 +48,14 @@ func (s *Subject) run(ctx context.Context, reload bool) {
4648
t := time.NewTicker(30 * time.Minute)
4749
for {
4850
select {
51+
case o := <-s.OperationChan:
52+
switch o.op {
53+
case Rename:
54+
err := s.Rename(o.arg.(string))
55+
if err != nil {
56+
log.Error(log.Struct{"sid", s.SubjId, "err", err}, "rename failed")
57+
}
58+
}
4959
case torr := <-s.PushChan:
5060
err := s.push(torr, email.Poster)
5161
if err != nil {
@@ -87,6 +97,7 @@ func exit(s *Subject) {
8797
}
8898
close(s.Exited)
8999
close(s.PushChan)
100+
close(s.OperationChan)
90101
Mgr.Sync()
91102
}
92103

0 commit comments

Comments
 (0)