refactor mod stuff
This commit is contained in:
parent
e8fa40c0ca
commit
e87d739392
@ -8,7 +8,7 @@ import (
|
||||
type CacheInterface interface {
|
||||
RegenAll()
|
||||
RegenFrontPage()
|
||||
RegenOnModEvent(string, string, string, int)
|
||||
RegenOnModEvent(newsgroup, msgid, root string, page int)
|
||||
RegenerateBoard(group string)
|
||||
Regen(msg ArticleEntry)
|
||||
|
||||
|
@ -535,28 +535,6 @@ func (self *NNTPDaemon) Run() {
|
||||
self.allow_anon_attachments = self.conf.daemon["allow_anon_attachments"] == "1"
|
||||
self.allow_attachments = self.conf.daemon["allow_attachments"] == "1"
|
||||
|
||||
// do we enable the frontend?
|
||||
if self.conf.frontend["enable"] == "1" {
|
||||
log.Printf("frontend %s enabled", self.conf.frontend["name"])
|
||||
|
||||
cache_host := self.conf.cache["host"]
|
||||
cache_port := self.conf.cache["port"]
|
||||
cache_user := self.conf.cache["user"]
|
||||
cache_passwd := self.conf.cache["password"]
|
||||
self.cache = NewCache(self.conf.cache["type"], cache_host, cache_port, cache_user, cache_passwd, self.conf.cache, self.conf.frontend, self.database, self.store)
|
||||
|
||||
script, ok := self.conf.frontend["markup_script"]
|
||||
if ok {
|
||||
err = SetMarkupScriptFile(script)
|
||||
if err != nil {
|
||||
log.Println("failed to load markup script", err)
|
||||
}
|
||||
}
|
||||
|
||||
self.frontend = NewHTTPFrontend(self, self.cache, self.conf.frontend, self.conf.worker["url"])
|
||||
go self.frontend.Mainloop()
|
||||
}
|
||||
|
||||
// set up admin user if it's specified in the config
|
||||
pubkey, ok := self.conf.frontend["admin_key"]
|
||||
if ok {
|
||||
@ -572,6 +550,9 @@ func (self *NNTPDaemon) Run() {
|
||||
}
|
||||
}
|
||||
|
||||
// start frontend
|
||||
go self.frontend.Mainloop()
|
||||
|
||||
log.Println("we have", len(self.conf.feeds), "feeds")
|
||||
|
||||
defer self.listener.Close()
|
||||
@ -647,7 +628,6 @@ func (self *NNTPDaemon) Run() {
|
||||
log.Println("started worker", threads)
|
||||
threads--
|
||||
}
|
||||
|
||||
// start accepting incoming connections
|
||||
self.acceptloop()
|
||||
<-self.done
|
||||
@ -838,7 +818,6 @@ func (self *NNTPDaemon) pump_article_requests() {
|
||||
}
|
||||
|
||||
func (self *NNTPDaemon) poll(worker int) {
|
||||
modchnl := self.mod.MessageChan()
|
||||
for {
|
||||
select {
|
||||
case msgid := <-self.infeed_load:
|
||||
@ -863,7 +842,7 @@ func (self *NNTPDaemon) poll(worker int) {
|
||||
}
|
||||
// send to mod panel
|
||||
if group == "ctl" {
|
||||
modchnl <- msgid
|
||||
self.mod.HandleMessage(msgid)
|
||||
}
|
||||
// inform callback hooks
|
||||
self.informHooks(group, msgid, ref)
|
||||
@ -1081,11 +1060,36 @@ func (self *NNTPDaemon) Setup() {
|
||||
log.Println("set up article store...")
|
||||
self.store = createArticleStore(self.conf.store, self.database)
|
||||
|
||||
self.mod = modEngine{
|
||||
// do we enable the frontend?
|
||||
if self.conf.frontend["enable"] == "1" {
|
||||
log.Printf("frontend %s enabled", self.conf.frontend["name"])
|
||||
|
||||
cache_host := self.conf.cache["host"]
|
||||
cache_port := self.conf.cache["port"]
|
||||
cache_user := self.conf.cache["user"]
|
||||
cache_passwd := self.conf.cache["password"]
|
||||
self.cache = NewCache(self.conf.cache["type"], cache_host, cache_port, cache_user, cache_passwd, self.conf.cache, self.conf.frontend, self.database, self.store)
|
||||
|
||||
script, ok := self.conf.frontend["markup_script"]
|
||||
if ok {
|
||||
err = SetMarkupScriptFile(script)
|
||||
if err != nil {
|
||||
log.Println("failed to load markup script", err)
|
||||
}
|
||||
}
|
||||
|
||||
self.frontend = NewHTTPFrontend(self, self.cache, self.conf.frontend, self.conf.worker["url"])
|
||||
}
|
||||
|
||||
self.mod = &modEngine{
|
||||
store: self.store,
|
||||
database: self.database,
|
||||
chnl: make(chan string),
|
||||
regen: self.frontend.RegenOnModEvent,
|
||||
}
|
||||
// inject DB into template engine
|
||||
template.DB = self.database
|
||||
}
|
||||
|
||||
func (daemon *NNTPDaemon) ModEngine() ModEngine {
|
||||
return daemon.mod
|
||||
}
|
||||
|
@ -63,7 +63,6 @@ func (self expire) ExpirePost(messageID string) {
|
||||
}
|
||||
|
||||
func (self expire) ExpireGroup(newsgroup string, keep int) {
|
||||
log.Println("Expire group", newsgroup, keep)
|
||||
threads := self.database.GetRootPostsForExpiration(newsgroup, keep)
|
||||
for _, root := range threads {
|
||||
self.ExpireThread(newsgroup, root)
|
||||
@ -127,7 +126,6 @@ func (self expire) ExpireOrphans() {
|
||||
}
|
||||
|
||||
func (self expire) handleEvent(ev deleteEvent) {
|
||||
log.Println("expire", ev.MessageID())
|
||||
atts := self.database.GetPostAttachments(ev.MessageID())
|
||||
// remove all attachments
|
||||
if atts != nil {
|
||||
@ -147,5 +145,5 @@ func (self expire) handleEvent(ev deleteEvent) {
|
||||
log.Println("failed to delete article", err)
|
||||
}
|
||||
// remove article
|
||||
os.Remove(ev.Path())
|
||||
self.store.Remove(ev.MessageID())
|
||||
}
|
||||
|
@ -36,4 +36,6 @@ type Frontend interface {
|
||||
|
||||
// trigger a manual regen of indexes for a root post
|
||||
Regen(msg ArticleEntry)
|
||||
// regenerate on mod event
|
||||
RegenOnModEvent(newsgroup, msgid, root string, page int)
|
||||
}
|
||||
|
@ -1483,7 +1483,7 @@ func (self *httpFrontend) Mainloop() {
|
||||
var err error
|
||||
|
||||
// run daemon's mod engine with our frontend
|
||||
go RunModEngine(self.daemon.mod, self.cache.RegenOnModEvent)
|
||||
// go RunModEngine(self.daemon.mod, self.cache.RegenOnModEvent)
|
||||
|
||||
// start cache
|
||||
self.cache.Start()
|
||||
@ -1517,6 +1517,10 @@ func (self *httpFrontend) endLiveUI() {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *httpFrontend) RegenOnModEvent(newsgroup, msgid, root string, page int) {
|
||||
self.cache.RegenOnModEvent(newsgroup, msgid, root, page)
|
||||
}
|
||||
|
||||
// create a new http based frontend
|
||||
func NewHTTPFrontend(daemon *NNTPDaemon, cache CacheInterface, config map[string]string, url string) Frontend {
|
||||
template.Minimize = config["minimize_html"] == "1"
|
||||
|
@ -46,6 +46,12 @@ func (self multiFrontend) PostsChan() chan frontendPost {
|
||||
return self.muxedpostchan
|
||||
}
|
||||
|
||||
func (self multiFrontend) RegenOnModEvent(newsgroup, msgid, root string, page int) {
|
||||
for idx := range self.frontends {
|
||||
self.frontends[idx].RegenOnModEvent(newsgroup, msgid, root, page)
|
||||
}
|
||||
}
|
||||
|
||||
func MuxFrontends(fronts ...Frontend) Frontend {
|
||||
var front multiFrontend
|
||||
front.muxedpostchan = make(chan frontendPost, 64)
|
||||
|
@ -23,14 +23,9 @@ type AdminFunc func(param map[string]interface{}) (interface{}, error)
|
||||
|
||||
// interface for moderation ui
|
||||
type ModUI interface {
|
||||
|
||||
// channel for daemon to poll for nntp articles from the mod ui
|
||||
MessageChan() chan NNTPMessage
|
||||
|
||||
// check if this key is allowed to access
|
||||
// return true if it can otherwise false
|
||||
CheckKey(privkey, scope string) (bool, error)
|
||||
|
||||
// serve the base page
|
||||
ServeModPage(wr http.ResponseWriter, r *http.Request)
|
||||
// handle a login POST request
|
||||
@ -49,6 +44,8 @@ type ModUI interface {
|
||||
HandleKeyGen(wr http.ResponseWriter, r *http.Request)
|
||||
// handle admin command
|
||||
HandleAdminCommand(wr http.ResponseWriter, r *http.Request)
|
||||
// get outbound message channel
|
||||
MessageChan() chan NNTPMessage
|
||||
}
|
||||
|
||||
type ModEvent interface {
|
||||
@ -149,10 +146,10 @@ func wrapModMessage(mm ModMessage) NNTPMessage {
|
||||
}
|
||||
|
||||
type ModEngine interface {
|
||||
// chan to send the mod engine posts given message_id
|
||||
MessageChan() chan string
|
||||
// load and handle a mod message from ctl after it's verified
|
||||
HandleMessage(msgid string)
|
||||
// delete post of a poster
|
||||
DeletePost(msgid string, regen RegenFunc) error
|
||||
DeletePost(msgid string) error
|
||||
// ban a cidr
|
||||
BanAddress(cidr string) error
|
||||
// do we allow this public key to delete this message-id ?
|
||||
@ -161,28 +158,28 @@ type ModEngine interface {
|
||||
AllowBan(pubkey string) bool
|
||||
// load a mod message
|
||||
LoadMessage(msgid string) NNTPMessage
|
||||
// execute 1 mod action line by a mod with pubkey
|
||||
Execute(ev ModEvent, pubkey string)
|
||||
// do a mod event unconditionally
|
||||
Do(ev ModEvent)
|
||||
}
|
||||
|
||||
type modEngine struct {
|
||||
database Database
|
||||
store ArticleStore
|
||||
chnl chan string
|
||||
regen RegenFunc
|
||||
}
|
||||
|
||||
func (self modEngine) LoadMessage(msgid string) NNTPMessage {
|
||||
func (self *modEngine) LoadMessage(msgid string) NNTPMessage {
|
||||
return self.store.GetMessage(msgid)
|
||||
}
|
||||
|
||||
func (self modEngine) MessageChan() chan string {
|
||||
return self.chnl
|
||||
}
|
||||
|
||||
func (self modEngine) BanAddress(cidr string) (err error) {
|
||||
func (self *modEngine) BanAddress(cidr string) (err error) {
|
||||
return self.database.BanAddr(cidr)
|
||||
}
|
||||
|
||||
func (self modEngine) DeletePost(msgid string, regen RegenFunc) (err error) {
|
||||
hdr, err := self.database.GetHeadersForMessage(msgid)
|
||||
func (self *modEngine) DeletePost(msgid string) (err error) {
|
||||
hdr := self.store.GetHeaders(msgid)
|
||||
var delposts []string
|
||||
var page int64
|
||||
var ref, group string
|
||||
@ -231,10 +228,6 @@ func (self modEngine) DeletePost(msgid string, regen RegenFunc) (err error) {
|
||||
os.Remove(f)
|
||||
}
|
||||
|
||||
if rootmsgid != "" {
|
||||
self.database.DeleteThread(rootmsgid)
|
||||
}
|
||||
|
||||
for _, delmsg := range delposts {
|
||||
// delete article from post database
|
||||
err = self.database.DeleteArticle(delmsg)
|
||||
@ -243,12 +236,17 @@ func (self modEngine) DeletePost(msgid string, regen RegenFunc) (err error) {
|
||||
}
|
||||
// ban article
|
||||
self.database.BanArticle(delmsg, "deleted by moderator")
|
||||
self.store.Remove(delmsg)
|
||||
}
|
||||
regen(group, msgid, ref, int(page))
|
||||
|
||||
if rootmsgid != "" {
|
||||
self.database.DeleteThread(rootmsgid)
|
||||
}
|
||||
self.regen(group, msgid, ref, int(page))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self modEngine) AllowBan(pubkey string) bool {
|
||||
func (self *modEngine) AllowBan(pubkey string) bool {
|
||||
is_admin, _ := self.database.CheckAdminPubkey(pubkey)
|
||||
if is_admin {
|
||||
// admins can do whatever
|
||||
@ -257,7 +255,7 @@ func (self modEngine) AllowBan(pubkey string) bool {
|
||||
return self.database.CheckModPubkeyGlobal(pubkey)
|
||||
}
|
||||
|
||||
func (self modEngine) AllowDelete(pubkey, msgid string) (allow bool) {
|
||||
func (self *modEngine) AllowDelete(pubkey, msgid string) (allow bool) {
|
||||
is_admin, _ := self.database.CheckAdminPubkey(pubkey)
|
||||
if is_admin {
|
||||
// admins can do whatever
|
||||
@ -277,88 +275,166 @@ func (self modEngine) AllowDelete(pubkey, msgid string) (allow bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// run a mod engine logic mainloop
|
||||
func RunModEngine(mod ModEngine, regen RegenFunc) {
|
||||
|
||||
chnl := mod.MessageChan()
|
||||
for {
|
||||
msgid := <-chnl
|
||||
nntp := mod.LoadMessage(msgid)
|
||||
if nntp == nil {
|
||||
log.Println("failed to load mod message", msgid)
|
||||
continue
|
||||
}
|
||||
// sanity check
|
||||
if nntp.Newsgroup() == "ctl" {
|
||||
pubkey := nntp.Pubkey()
|
||||
for _, line := range strings.Split(nntp.Message(), "\n") {
|
||||
line = strings.Trim(line, "\r\t\n ")
|
||||
ev := ParseModEvent(line)
|
||||
action := ev.Action()
|
||||
if action == "delete" {
|
||||
msgid := ev.Target()
|
||||
if !ValidMessageID(msgid) {
|
||||
// invalid message-id
|
||||
log.Println("invalid message-id for mod delete", msgid, "from", pubkey)
|
||||
continue
|
||||
}
|
||||
// this is a delete action
|
||||
if mod.AllowDelete(pubkey, msgid) {
|
||||
err := mod.DeletePost(msgid, regen)
|
||||
if err != nil {
|
||||
log.Println(msgid, err)
|
||||
}
|
||||
} else {
|
||||
log.Printf("pubkey=%s will not delete %s not trusted", pubkey, msgid)
|
||||
}
|
||||
} else if action == "overchan-inet-ban" {
|
||||
// ban action
|
||||
target := ev.Target()
|
||||
if target[0] == '[' {
|
||||
// probably a literal ipv6 rangeban
|
||||
if mod.AllowBan(pubkey) {
|
||||
err := mod.BanAddress(target)
|
||||
if err != nil {
|
||||
log.Println("failed to do literal ipv6 range ban on", target, err)
|
||||
}
|
||||
} else {
|
||||
log.Println("ignoring literal ipv6 rangeban from", pubkey, "as they are not allowed to ban")
|
||||
}
|
||||
continue
|
||||
}
|
||||
parts := strings.Split(target, ":")
|
||||
if len(parts) == 3 {
|
||||
// encrypted ip
|
||||
encaddr, key := parts[0], parts[1]
|
||||
cidr := decAddr(encaddr, key)
|
||||
if cidr == "" {
|
||||
log.Println("failed to decrypt inet ban")
|
||||
} else if mod.AllowBan(pubkey) {
|
||||
err := mod.BanAddress(cidr)
|
||||
if err != nil {
|
||||
log.Println("failed to do range ban on", cidr, err)
|
||||
}
|
||||
} else {
|
||||
log.Println("ingoring encrypted-ip inet ban from", pubkey, "as they are not allowed to ban")
|
||||
}
|
||||
} else if len(parts) == 1 {
|
||||
// literal cidr
|
||||
cidr := parts[0]
|
||||
if mod.AllowBan(pubkey) {
|
||||
err := mod.BanAddress(cidr)
|
||||
if err != nil {
|
||||
log.Println("failed to do literal range ban on", cidr, err)
|
||||
}
|
||||
} else {
|
||||
log.Println("ingoring literal cidr range ban from", pubkey, "as they are not allowed to ban")
|
||||
}
|
||||
} else {
|
||||
log.Printf("invalid overchan-inet-ban: target=%s", target)
|
||||
}
|
||||
} else {
|
||||
log.Println("invalid mod action", action, "from", pubkey)
|
||||
}
|
||||
}
|
||||
func (mod *modEngine) HandleMessage(msgid string) {
|
||||
nntp := mod.store.GetMessage(msgid)
|
||||
if nntp == nil {
|
||||
log.Println("failed to load", msgid, "in mod engine, missing message")
|
||||
return
|
||||
}
|
||||
// sanity check
|
||||
if nntp.Newsgroup() == "ctl" {
|
||||
pubkey := nntp.Pubkey()
|
||||
for _, line := range strings.Split(nntp.Message(), "\n") {
|
||||
line = strings.Trim(line, "\r\t\n ")
|
||||
ev := ParseModEvent(line)
|
||||
mod.Execute(ev, pubkey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *modEngine) Do(ev ModEvent) {
|
||||
action := ev.Action()
|
||||
if action == "delete" {
|
||||
msgid := ev.Target()
|
||||
if !ValidMessageID(msgid) {
|
||||
// invalid message-id
|
||||
log.Println("invalid message-id", msgid)
|
||||
return
|
||||
}
|
||||
err := mod.DeletePost(msgid)
|
||||
if err != nil {
|
||||
log.Println(msgid, err)
|
||||
} else {
|
||||
log.Println("deleted", msgid)
|
||||
}
|
||||
|
||||
} else if action == "overchan-inet-ban" {
|
||||
// ban action
|
||||
target := ev.Target()
|
||||
if target[0] == '[' {
|
||||
err := mod.BanAddress(target)
|
||||
if err != nil {
|
||||
log.Println("failed to do literal ipv6 range ban on", target, err)
|
||||
} else {
|
||||
log.Println("banned", target)
|
||||
}
|
||||
return
|
||||
}
|
||||
parts := strings.Split(target, ":")
|
||||
if len(parts) == 3 {
|
||||
// encrypted ip
|
||||
encaddr, key := parts[0], parts[1]
|
||||
cidr := decAddr(encaddr, key)
|
||||
if cidr == "" {
|
||||
log.Println("failed to decrypt inet ban")
|
||||
} else {
|
||||
err := mod.BanAddress(cidr)
|
||||
if err != nil {
|
||||
log.Println("failed to do range ban on", cidr, err)
|
||||
} else {
|
||||
log.Println("banned", cidr)
|
||||
}
|
||||
}
|
||||
} else if len(parts) == 2 {
|
||||
// x-encrypted-ip ban without pad
|
||||
err := mod.database.BanEncAddr(parts[0])
|
||||
if err != nil {
|
||||
log.Println("failed to ban encrypted ip", err)
|
||||
} else {
|
||||
log.Println("banned poster", parts[0])
|
||||
}
|
||||
|
||||
} else if len(parts) == 1 {
|
||||
// literal cidr
|
||||
cidr := parts[0]
|
||||
err := mod.BanAddress(cidr)
|
||||
if err != nil {
|
||||
log.Println("failed to do literal range ban on", cidr, err)
|
||||
} else {
|
||||
log.Println("banned cidr", cidr)
|
||||
}
|
||||
|
||||
} else {
|
||||
log.Printf("invalid overchan-inet-ban: target=%s", target)
|
||||
}
|
||||
} else {
|
||||
log.Println("invalid mod action", action)
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *modEngine) Execute(ev ModEvent, pubkey string) {
|
||||
action := ev.Action()
|
||||
if action == "delete" {
|
||||
msgid := ev.Target()
|
||||
if !ValidMessageID(msgid) {
|
||||
// invalid message-id
|
||||
log.Println("invalid message-id for mod delete from", pubkey)
|
||||
return
|
||||
}
|
||||
// this is a delete action
|
||||
if mod.AllowDelete(pubkey, msgid) {
|
||||
err := mod.DeletePost(msgid)
|
||||
if err != nil {
|
||||
log.Println(msgid, err)
|
||||
}
|
||||
} else {
|
||||
log.Printf("pubkey=%s will not delete %s not trusted", pubkey, msgid)
|
||||
}
|
||||
} else if action == "overchan-inet-ban" {
|
||||
// ban action
|
||||
target := ev.Target()
|
||||
if target[0] == '[' {
|
||||
// probably a literal ipv6 rangeban
|
||||
if mod.AllowBan(pubkey) {
|
||||
err := mod.BanAddress(target)
|
||||
if err != nil {
|
||||
log.Println("failed to do literal ipv6 range ban on", target, err)
|
||||
}
|
||||
} else {
|
||||
log.Println("ignoring literal ipv6 rangeban from", pubkey, "as they are not allowed to ban")
|
||||
}
|
||||
return
|
||||
}
|
||||
parts := strings.Split(target, ":")
|
||||
if len(parts) == 3 {
|
||||
// encrypted ip
|
||||
encaddr, key := parts[0], parts[1]
|
||||
cidr := decAddr(encaddr, key)
|
||||
if cidr == "" {
|
||||
log.Println("failed to decrypt inet ban")
|
||||
} else if mod.AllowBan(pubkey) {
|
||||
err := mod.BanAddress(cidr)
|
||||
if err != nil {
|
||||
log.Println("failed to do range ban on", cidr, err)
|
||||
}
|
||||
} else {
|
||||
log.Println("ingoring encrypted-ip inet ban from", pubkey, "as they are not allowed to ban")
|
||||
}
|
||||
} else if len(parts) == 2 {
|
||||
// x-encrypted-ip ban without pad
|
||||
if mod.AllowBan(pubkey) {
|
||||
err := mod.database.BanEncAddr(parts[0])
|
||||
if err != nil {
|
||||
log.Println("failed to ban encrypted ip", err)
|
||||
}
|
||||
} else {
|
||||
log.Println("ignoring encrypted-ip ban from", pubkey, "as they are not allowed to ban")
|
||||
}
|
||||
} else if len(parts) == 1 {
|
||||
// literal cidr
|
||||
cidr := parts[0]
|
||||
if mod.AllowBan(pubkey) {
|
||||
err := mod.BanAddress(cidr)
|
||||
if err != nil {
|
||||
log.Println("failed to do literal range ban on", cidr, err)
|
||||
}
|
||||
} else {
|
||||
log.Println("ingoring literal cidr range ban from", pubkey, "as they are not allowed to ban")
|
||||
}
|
||||
} else {
|
||||
log.Printf("invalid overchan-inet-ban: target=%s", target)
|
||||
}
|
||||
} else {
|
||||
log.Println("invalid mod action", action, "from", pubkey)
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,9 @@ type ArticleStore interface {
|
||||
|
||||
// get thumbnail info of file by path
|
||||
ThumbInfo(fpath string) (ThumbInfo, error)
|
||||
|
||||
// delete message by message-id
|
||||
Remove(msgid string) error
|
||||
}
|
||||
type articleStore struct {
|
||||
directory string
|
||||
@ -140,6 +143,16 @@ func (self *articleStore) Init() {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *articleStore) Remove(msgid string) (err error) {
|
||||
if ValidMessageID(msgid) {
|
||||
fpath := self.GetFilename(msgid)
|
||||
err = os.Remove(fpath)
|
||||
} else {
|
||||
err = errors.New("invalid message-id: " + msgid)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (self *articleStore) RegisterSigned(msgid, pk string) (err error) {
|
||||
err = self.database.RegisterSigned(msgid, pk)
|
||||
return
|
||||
|
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@ -44,7 +45,32 @@ func main() {
|
||||
if len(os.Args) > 2 {
|
||||
tool := os.Args[2]
|
||||
if tool == "mod" {
|
||||
if len(os.Args) >= 5 {
|
||||
if len(os.Args) == 4 && os.Args[3] == "do" {
|
||||
daemon.Setup()
|
||||
eng := daemon.ModEngine()
|
||||
r := bufio.NewReader(os.Stdin)
|
||||
var err error
|
||||
for err == nil {
|
||||
var line string
|
||||
fmt.Print("\nmod> ")
|
||||
line, err = r.ReadString(10)
|
||||
if err == nil {
|
||||
line = strings.Trim(line, "\n")
|
||||
if line == "help" {
|
||||
fmt.Println("usage:")
|
||||
fmt.Println("delete <message-id>")
|
||||
fmt.Println("overchan-inet-ban 1.1.1.1/32")
|
||||
fmt.Println("exit")
|
||||
} else if line == "quit" || line == "exit" {
|
||||
fmt.Println("bai")
|
||||
return
|
||||
} else {
|
||||
ev := srnd.ParseModEvent(line)
|
||||
eng.Do(ev)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if len(os.Args) >= 5 {
|
||||
action := os.Args[3]
|
||||
if action == "add" {
|
||||
pk := os.Args[4]
|
||||
@ -62,9 +88,11 @@ func main() {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stdout, "usage: %s tool mod [[add|del] pubkey]|[do modactiongoeshere]\n", os.Args[0])
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stdout, "usage: %s tool mod [add|del] pubkey\n", os.Args[0])
|
||||
fmt.Fprintf(os.Stdout, "usage: %s tool mod [[add|del] pubkey]|[do modactiongoeshere]\n", os.Args[0])
|
||||
}
|
||||
} else if tool == "rethumb" {
|
||||
if len(os.Args) >= 4 {
|
||||
|
Reference in New Issue
Block a user