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 }