ccocot icon

botlike.go

ccocot | PRO | 01/22/18 06:32:37 AM UTC | 0 ⭐ | 327 👁️ | Never ⏰ | []
Go |

4.97 KB

|

None

|

0 👍

/

0 👎

package main
 
import (
    "database/sql"
    "flag"
    "github.com/ahmdrz/goinsta"
    "github.com/ahmdrz/goinsta/response"
    _ "github.com/lib/pq"
    "log"
    "os"
    "regexp"
    "strings"
    "sync"
    "time"
)
 
var (
    username string
    password string
    email    string
    sleep    int64
    add      bool
    show     bool
    remove   bool
    connStr  string = "user=postgres dbname=db_instagram sslmode=disable password=ccocot123"
)
 
func panicOnError(err error) {
    if err != nil {
        log.Panic(err)
    }
}
 
func addAccount(db *sql.DB) {
    isUsernameEmpty := !(len(username) > 0)
    isPasswordEmpty := !(len(password) > 0)
    isEmailEmpty := !(len(email) > 0)
    if isUsernameEmpty || isPasswordEmpty || isEmailEmpty {
        log.Panic("Username, Password or Email Empty\n")
    }
    insta := goinsta.New(username, password)
    log.Print("Login Instagram ...\n")
    err := insta.Login()
    defer insta.Logout()
    panicOnError(err)
    _, err = db.Exec(`INSERT INTO account_info VALUES($1, $2, $3)`, username, password, email)
    panicOnError(err)
    log.Printf("User Added ! \n")
}
 
func showAccount(db *sql.DB) {
    rows, err := db.Query(`SELECT username,password FROM account_info`)
    panicOnError(err)
    index := 0
    for rows.Next() {
        index++
        var usernameTmp string
        var passwordTmp string
        err := rows.Scan(&usernameTmp, &passwordTmp)
        panicOnError(err)
        log.Printf("%d. Username: %s Password: %s \n", index, usernameTmp, passwordTmp)
    }
}
 
func deleteAccount(db *sql.DB) {
    isUsernameEmpty := !(len(username) > 0)
    if isUsernameEmpty {
        log.Panic("Username to delete Empty\n")
    }
    _, err := db.Exec(`DELETE FROM account_info WHERE username = $1`, username)
    panicOnError(err)
    log.Printf("User Deleted !\n")
}
 
func init() {
    // flag
    flag.StringVar(&username, "username", "", "instagram account username")
    flag.StringVar(&password, "password", "", "instagram account password")
    flag.StringVar(&email, "email", "", "instagram account email")
    flag.Int64Var(&sleep, "sleep", 2, "sleep in minute")
    flag.BoolVar(&add, "add", false, "add account instagram")
    flag.BoolVar(&show, "show", false, "to show instagram account list")
    flag.BoolVar(&remove, "remove", false, "remove instagram account")
    flag.Parse()
 
    //db connection
    db, err := sql.Open("postgres", connStr)
    panicOnError(err)
    defer db.Close()
 
    switch {
    case add: //if flag add true
        addAccount(db)
        os.Exit(0)
    case show: // if flag show true
        showAccount(db)
        os.Exit(0)
    case remove: //if flag remove true
        deleteAccount(db)
        os.Exit(0)
    }
}
 
func main() {
 
    //db connection
    db, err := sql.Open("postgres", connStr)
    panicOnError(err)
    defer db.Close()
 
    // get account
    rows, err := db.Query(`SELECT username, password FROM account_info`)
    panicOnError(err)
    accounts := [][]string{}
    for rows.Next() {
        var usernameTmp string
        var passwordTmp string
        rows.Scan(&usernameTmp, &passwordTmp)
        itemToAppend := [][]string{{usernameTmp, passwordTmp}}
        accounts = append(accounts, itemToAppend...)
    }
 
    log.Printf("Get All Worker [Total: %d account] \n", len(accounts))
    // setup channel and waitgroup and worker login
    var wg sync.WaitGroup
    ch := make(chan *goinsta.Instagram, len(accounts))
    for _, account := range accounts {
        wg.Add(1)
        go login(&wg, account, ch)
    }
    wg.Wait()
    close(ch)
    log.Printf("All worker Logged In, close channel and start to Work !!!\n")
 
    //getTimeLine
    for account := range ch {
        wg.Add(1)
        go getTimeLine(&wg, account, db)
    }
 
    wg.Wait()
    log.Printf("All done")
}
 
func login(wg *sync.WaitGroup, account []string, ch chan *goinsta.Instagram) {
    defer wg.Done()
    log.Printf("worker %s try Login ... \n", account[0])
    insta := goinsta.New(account[0], account[1])
    err := insta.Login()
    panicOnError(err)
    log.Printf("worker %s Login Success ... \n", account[0])
    ch <- insta
}
 
func getTimeLine(wg *sync.WaitGroup, account *goinsta.Instagram, db *sql.DB) {
    defer wg.Done()
    accountInfo, err := account.GetProfileData()
    worker := accountInfo.User.Username
    panicOnError(err)
    maxID := ""
    for {
        feed, err := account.Timeline(maxID)
        feed.AutoLoadMore = true
        panicOnError(err)
        for index, item := range feed.Items {
            if mod := index % 3; index > 0 && mod == 0 {
                time.Sleep(time.Duration(sleep) * time.Minute)
            }
            re := regexp.MustCompile(`(\#[a-zA-Z]+\b)`)
            match := re.FindAllString(item.Caption.Text, -1)
            result := doLike(account, &item, worker)
            _, err := db.Exec(`INSERT INTO event VALUES(NOW(), $1, $2, $3, $4, $5);`,
                worker,
                result,
                strings.Join(match, " "),
                item.User.Username,
                item.ID)
            panicOnError(err)
        }
        if feed.MoreAvailable {
            maxID = feed.NextMaxID
        } else {
            break
        }
    }
}
 
func doLike(insta *goinsta.Instagram, item *response.MediaItemResponse, worker string) bool {
    liked := true
    if !item.HasLiked {
        _, err := insta.Like(item.ID)
        if err != nil {
            liked = false
        }
    }
 
    log.Printf("[%s] %s => %s [%t]", worker, item.User.Username, item.ID, liked)
    return liked
}

Comments