简体   繁体   English

有什么更好的方法来实现在社交网络中验证和执行帖子的例程?

[英]What better way to implement a routine that verifies and performs posts in social networks?

I'm writing a small application to perform automatic postings on social networks.我正在编写一个小应用程序来在社交网络上执行自动发布。

My intention is that the user can via the web interface create the post at a specific time and the bot can be checking for new posts scheduled and execute them.我的意图是用户可以通过 Web 界面在特定时间创建帖子,机器人可以检查安排的新帖子并执行它们。

I'm having trouble working with routines and channels on Go.我在使用 Go 上的例程和频道时遇到问题。

I will leave below an example that reflects the reality of my code.我将在下面留下一个反映我的代码实际情况的示例。 It contains some comments to make it easier to understand.它包含一些注释以使其更易于理解。

What is the best way to implement a routine that checks for new posts at any time?实现随时检查新帖子的例程的最佳方法是什么? Remembering:记住:

  1. User can enter new posts at any time.用户可以随时输入新帖子。
  2. The bot can manage hundreds/thousands of accounts at the same time.机器人可以同时管理数百/数千个帐户。 It would be essential to consume as little processing as possible.尽可能少地消耗处理量是必不可少的。

play.golang.org (here) play.golang.org(这里)


    package main

    import (
        "fmt"
        "sync"
        "time"
    )

    var botRunning = true
    var wg = &sync.WaitGroup{}

    func main() {
        // I start the routine of checking for and posting scheduled appointments.
        wg.Add(1)
        go postingScheduled()

        // Later the user passes the command to stop the post.
        // At that moment I would like to stop the routine immediately without getting stuck in a loop.
        // What is the best way to do this?
        time.Sleep(3 * time.Second)
        botRunning = false

        // ignore down
        time.Sleep(2 * time.Second)
        panic("")

        wg.Wait()
    }

    // Function that keeps checking whether the routine should continue or not.
    // Check every 2 seconds.
    // I think this is very wrong because it consumes unnecessary resources.
    // -> Is there another way to do this?
    func checkRunning() {
        for {
            fmt.Println("Pause/Running? - ", botRunning)
            if botRunning {
                break
            }
            time.Sleep(2 * time.Second)
        }
    }

    // Routine that looks for the scheduled posts in the database.
    // It inserts the date of the posts in the Ticker and when the time comes the posting takes place.
    // This application will have hundreds of social network accounts and each will have its own function running in parallel.
    // -> What better way to check constantly if there are scheduled items in the database consuming the least resources on the machine?
    // -> Another important question. User can schedule posts to the database at any time. How do I check for new posts schedule while the Ticker is waiting for the time the last posting loaded?
    func postingScheduled() {
        fmt.Println("Init bot posting routine")
        defer wg.Done()
        for {
            checkRunning()
            <-time.NewTicker(2 * time.Second).C
            fmt.Println("posted success")
        }

    }

With Peter's response I was able to adapt all the needs to put together a sketch.根据彼得的回应,我能够适应所有需要来制作草图。

I do not know if this would be the best way to do it, maybe some function will consume processing resources unnecessarily.我不知道这是否是最好的方法,也许某些功能会不必要地消耗处理资源。 If anyone has better ideas for refactoring, I'll be very grateful to hear.如果有人对重构有更好的想法,我将不胜感激。


    package main

    import (
        "fmt"
        "log"
        "net/http"
        "sort"
        "time"
    )

    type posting struct {
        caption string
        scheduledTo time.Time
    }

    const dateLayoutFormat  = "02-01-2006 15:04:05"

    var botStatus = true
    var indexPosting int
    var tickerSchedule = time.NewTicker(1)
    var posts = []posting{
        {caption: "item 1", scheduledTo: time.Now().Add(5 * time.Second)},
        {caption: "item 2", scheduledTo: time.Now().Add(25 * time.Second)},
    }

    func init() {
        indexPosting = len(posts)
    }

    func main() {
        http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
            fmt.Fprint(w, "Bem vindo ao bot")
        })

        http.HandleFunc("/stop", func (w http.ResponseWriter, r *http.Request) {
            fmt.Fprint(w, "Parando o bot!")
            stopBot()
        })

        http.HandleFunc("/start", func (w http.ResponseWriter, r *http.Request) {
            fmt.Fprint(w, "Iniciando o bot!")
            startBot()
        })

        http.HandleFunc("/add", func (w http.ResponseWriter, r *http.Request) {
            t := time.Now().Add(5 * time.Second)
            indexPosting++

            addItemDB(posting{
                caption: fmt.Sprint("item ", indexPosting),
                scheduledTo: t,
            })

            fmt.Fprint(w, "Adicionando nova postagem \nPróximo post será: ", t.Format(dateLayoutFormat))
        })

        if botStatus {
            go workerScheduled()
        }

        log.Print("Inicnando server...")
        if err := http.ListenAndServe(":9090", nil); err != nil {
            log.Print("erro ao iniciar servidor => ", err)
        }

    }

    func workerScheduled() {
        for {
            log.Print("listando as próximas postagens")

            pts := getNextPostsDB()
            if len(pts) == 0 {
                log.Print("sem postagem agendada")
                botStatus = false
                return
            }

            p1 := pts[0]

            log.Printf("Próxima postagem será: %s \n\n", string(p1.scheduledTo.Format(dateLayoutFormat)))
            <- updateTimer(p1.scheduledTo).C

            if !botStatus {
                log.Print("postagem cancelado, bot status = parado")
                return
            }

            if time.Until(p1.scheduledTo) > 1 * time.Second {
                updateTimer(p1.scheduledTo)
                log.Print("timer resetado")
                continue
            }

            post(p1)
            if len(pts) > 1 {
                p2 := pts[1]
                updateTimer(p2.scheduledTo)
            }
            updatePostedDB()
        }
    }

    func updateTimer(t time.Time) *time.Ticker {
        tickerSchedule = time.NewTicker(t.Sub(time.Now()))
        return tickerSchedule
    }

    func post(p posting) {
        log.Printf("'%s' postado com sucesso", p.caption)
    }

    func addItemDB(p posting) {
        posts = append(posts, p)
        if botStatus {
            next := getNextPostDB()
            updateTimer(next.scheduledTo)
        } else {
            botStatus = true
            go workerScheduled()
        }
    }

    func getNextPostDB() posting {
        return getNextPostsDB()[0]
    }

    func getNextPostsDB() []posting {
        orderPostsList()
        removePostExpired()
        return posts
    }

    func removePostExpired() {
        for _, p := range posts {
            if p.scheduledTo.Before(time.Now()) {
                log.Printf("removendo postagem expirada")
                removePostByIndex(getIndexOf(p))
            }
        }
    }

    func removePostByIndex(i int) {
        copy(posts[i:], posts[i+1:])
        posts = posts[:len(posts)-1]
    }

    func getIndexOf(post posting) int {
        for i, p := range posts {
            if p.caption == post.caption {
                return i
            }
        }
        return -1
    }

    func updatePostedDB() {
        removePostByIndex(0)
    }

    func orderPostsList() {
        sort.Slice(posts, func(i, j int) bool {
            return posts[i].scheduledTo.Before(posts[j].scheduledTo)
        })
    }

    func startBot() {
        if !botStatus {
            log.Printf("comando 'iniciar bot'")
            botStatus = true
            go workerScheduled()
        } else {
            log.Printf("comando 'iniciar bot' (já iniciado)")
        }
    }

    func stopBot() {
        if botStatus {
            log.Printf("comando 'pausar bot'")
            botStatus = false
            tickerSchedule.Stop()
        } else {
            log.Printf("comando 'pausar bot' (já pausado)")
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM