Problem with interacting with multiple users golang telegram bot - go

My tg bot shows a data about selling car to user. This data is sсraped from a web site. User can set a town from he wants to see cars. I have a problem, that if one user set a town, it changes on all users. I tried to use database to solve this promleb. Now i can insert in db data about user id and town, that he set, but i don't understand how it can help me. I think i need to use a gorutine to detect several connections from users, but i don't know how it use.
package main
import (
"encoding/json"
"fmt"
_ "github.com/go-sql-driver/mysql"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/gocolly/colly"
"io/ioutil"
"log"
"os"
"strings"
"time"
)
var (
currentFile string = "currentCars.json"
newFileName string = "newCars.json"
numericKeyboard = tgbotapi.NewReplyKeyboard(
tgbotapi.NewKeyboardButtonRow(
tgbotapi.NewKeyboardButton("Next Car " + "\u27A1"),
),
)
)
func main() {
bot, err := tgbotapi.NewBotAPI("TOKEN")
if err != nil {
log.Panic(err)
}
var url_town string = "https://auto.drom.ru/region50/all/"
go webScraper(&url_town) //func to scrape data from site
bot.Debug = true
log.Printf("Authorized on account %s", bot.Self.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
i := 0
updates := bot.GetUpdatesChan(u)
for update := range updates {
//mysql_db.InsertUserInfo(int(update.Message.Chat.ID), url_town)
if update.Message != nil { // If we got a message
switch update.Message.Text {
case "Next car \u27A1":
// Do something to show a card
case "/select_area":
// Do something to change url_town
default:
reply := "I don't know this command"
msg := tgbotapi.NewMessage(update.Message.Chat.ID, reply)
msg.ReplyMarkup = numericKeyboard
bot.Send(msg)
}
}
}
}

Related

Access EV Stations Detail for a Route or Geolocation Using Golang and HereApi

I am working on an RND Project to find out the Charging stations around a particular route/geolocation, I am getting credentials not valid error message while trying to access the URL. Meanwhile some of the other services I am able to access with the same API Key but not the EV ones.
How can I access the same using the credentials, Looking forward to valuable feedback from the expert community. Here is what I have tried using Golang.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
var apikey = "XXXXXXXX"
var latitude = 42.36399
var longitude = -71.05493
var address string
func main() {
url = "https://ev-v2.cc.api.here.com/ev/stations.json?prox=" + fmt.Sprint(latitude) + "," + fmt.Sprint(longitude) + ",5000&connectortype=31&apiKey=" + apikey
res, err := http.Get(url)
if err != nil {
log.Fatalln(err)
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Fatalln(err)
}
fmt.Println(string(body))
}
EV routing requires whitelisting. I would suggest please get in touch with your AE, or to get in contact with the respective team out of your region we have here a contact form you need to fill - https://www.here.com/contact

Golang Colly Scraping - Website Captcha Catches My Scrape

I did make Scraping for Amazon Product Titles but Amazon captcha catches my scraper. I tried 10 times- go run main.go(8 times catches me - 2 times I scraped the product title)
I researched this but I did not find any solution for golang(there is just python) is there any solution for me?
package main
import (
"fmt"
"strings"0
"github.com/gocolly/colly"
)
func main() {
// Create a Collector specifically for Shopify
c := colly.NewCollector(
colly.AllowedDomains("www.amazon.com", "amazon.com"),
)
c.OnHTML("div", func(h *colly.HTMLElement) {
capctha := h.Text
title := h.ChildText("span#productTitle")
fmt.Println(strings.TrimSpace(title))
fmt.Println(strings.TrimSpace(capctha))
})
// Start the collector
c.Visit("https://www.amazon.com/Bluetooth-Over-Ear-Headphones-Foldable-Prolonged/dp/B07K5214NZ")
}
Output:
Enter the characters you see below Sorry, we just need to make sure
you're not a robot. For best results, please make sure your browser is
accepting cookies.
If you don't mind a different package, I wrote a package to search HTML
(essentially thin wrapper around github.com/tdewolff/parse):
package main
import (
"github.com/89z/parse/html"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest(
"GET", "https://www.amazon.com/dp/B07K5214NZ", nil,
)
req.Header = http.Header{
"User-Agent": {"Mozilla"},
}
res, err := new(http.Transport).RoundTrip(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
lex := html.NewLexer(res.Body)
lex.NextAttr("id", "productTitle")
os.Stdout.Write(lex.Bytes())
}
Result:
Bluetooth Headphones Over-Ear, Zihnic Foldable Wireless and Wired Stereo
Headset Micro SD/TF, FM for Cell Phone,PC,Soft Earmuffs &Light Weight for
Prolonged Waring(Rose Gold)
https://github.com/89z/parse

How to validate API key with function in Martini?

So I currently have a function that will take in a string APIKey to check it against my Mongo collection. If nothing is found (not authenticated), it returns false - if a user is found, it returns true. My problem, however, is I'm unsure how to integrate this with a Martini POST route. Here is my code:
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/go-martini/martini"
_ "github.com/joho/godotenv/autoload"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type User struct {
Name string
APIKey string
}
func validateAPIKey(users *mongo.Collection, APIKey string) bool {
var user User
filter := bson.D{{"APIKey", APIKey}}
if err := users.FindOne(context.TODO(), filter).Decode(&user); err != nil {
fmt.Printf("Found 0 results for API Key: %s\n", APIKey)
return false
}
fmt.Printf("Found: %s\n", user.Name)
return true
}
func uploadHandler() {
}
func main() {
mongoURI := os.Getenv("MONGO_URI")
mongoOptions := options.Client().ApplyURI(mongoURI)
client, _ := mongo.Connect(context.TODO(), mongoOptions)
defer client.Disconnect(context.TODO())
if err := client.Ping(context.TODO(), nil); err != nil {
log.Fatal(err, "Unable to access MongoDB server, exiting...")
}
// users := client.Database("sharex_api").Collection("authorized_users") // commented out when testing to ignore unused warnings
m := martini.Classic()
m.Post("/api/v1/upload", uploadHandler)
m.RunOnAddr(":8085")
}
The validateAPIKey function works exactly as intended if tested alone, I am just unsure how I would run this function for a specific endpoint (in this case, /api/v1/upload).

Retrieve the latest comment from a github issue

I am wondering what would be the most efficient way to retrieve the latest comment from a github issue using Go.
I actually know how to do this already but I am not satisfied with the performance so I would love to get some suggestions
package main
import (
"context"
"fmt"
"github.com/google/go-github/github"
"golang.org/x/oauth2"
"net/url"
"os"
)
func main() {
owner, repo := "owner", "repo"
token := oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")}
ts := oauth2.StaticTokenSource(&token)
ctx := context.Background()
tc := oauth2.NewClient(ctx, ts)
gc := github.NewClient(tc)
gc.BaseURL, _ = url.Parse("https://api.github.com/")
opts := github.IssueListByRepoOptions{}
issues, _, _ := gc.Issues.ListByRepo(ctx, owner, repo, &opts)
// Implement Here: get latest comment for issues[0]
return
}
Thanks in advance :)
You can use Rest API v3 or GraphQL v4. If you plan to loop through a lot of issues, graphQL definitly worth it
Using Rest API v3
Using go-github as you suggested, you can use :
ListComments(ctx context.Context, owner string, repo string, number int, opts *IssueListCommentsOptions)
For example from this test
For example to get the last comment for the last 20 opened issues (from your code).
package main
import (
"context"
"github.com/google/go-github/github"
"golang.org/x/oauth2"
"net/url"
"os"
"log"
)
func main() {
owner, repo := "google", "gson"
token := oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")}
ts := oauth2.StaticTokenSource(&token)
ctx := context.Background()
tc := oauth2.NewClient(ctx, ts)
gc := github.NewClient(tc)
gc.BaseURL, _ = url.Parse("https://api.github.com/")
opts := github.IssueListByRepoOptions{}
issues, _, _ := gc.Issues.ListByRepo(ctx, owner, repo, &opts)
for i := 0; i < len(issues); i++ {
opt := &github.IssueListCommentsOptions{}
comments, _, err := gc.Issues.ListComments(ctx, owner, repo, *issues[i].Number, opt)
if err != nil {
log.Println(err)
} else if len(comments) > 0 {
log.Println(*comments[0].Body)
} else {
log.Println("no comment for this issue")
}
}
}
It will perform :
one request to get the last 20 opened issues
one request for each issue to get the last comments
So a total of 21 requests
Using GraphQL v4
You can use githubv4 library to use Github GraphQL v4.
The same as previous example in GraphQL would be :
package main
import (
"context"
"github.com/shurcooL/githubv4"
"golang.org/x/oauth2"
"os"
"encoding/json"
"log"
)
func main() {
owner, repo := "google", "gson"
token := oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")}
ts := oauth2.StaticTokenSource(&token)
httpClient := oauth2.NewClient(context.Background(), ts)
client := githubv4.NewClient(httpClient)
{
var q struct {
Repository struct {
Issues struct {
Nodes []struct {
Number int
Comments struct {
Nodes []struct {
Body githubv4.String
}
} `graphql:"comments(last:$commentsLast)"`
}
PageInfo struct {
EndCursor githubv4.String
HasNextPage githubv4.Boolean
}
} `graphql:"issues(last:$issuesLast,states:OPEN)"`
} `graphql:"repository(owner:$repositoryOwner,name:$repositoryName)"`
}
variables := map[string]interface{}{
"repositoryOwner": githubv4.String(owner),
"repositoryName": githubv4.String(repo),
"issuesLast": githubv4.NewInt(20),
"commentsLast": githubv4.NewInt(1),
}
err := client.Query(context.Background(), &q, variables)
if err != nil {
log.Println(err)
return
}
printJSON(q)
}
}
func printJSON(v interface{}) {
w := json.NewEncoder(os.Stdout)
w.SetIndent("", "\t")
err := w.Encode(v)
if err != nil {
panic(err)
}
}
This is modification of the example from the github repo
The code above will perform exactly 1 request

generate otp code same like authy desktop

I try to generate totp code using this library same like authy.com desktop application. this is my current code :
package main
import (
"time"
"github.com/pquerna/otp/totp"
"bufio"
"fmt"
"os"
)
func promptForPasscode() string {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter Passcode: ")
text, _ := reader.ReadString('\n')
return text
}
func main() {
keySecret := "NK4KFDHUGRGMFKFEWRJ5EEOV6FT2IAKE"
coded, _ := totp.GenerateCode(keySecret, time.Now().UTC())
fmt.Println("code :", coded)
fmt.Println("Validating TOTP...")
// Now Validate that the user's successfully added the passcode.
passcode := promptForPasscode()
valid := totp.Validate(passcode, keySecret)
if valid {
println("Valid passcode!")
os.Exit(0)
} else {
println("Invalid passocde!")
os.Exit(1)
}
}
The code is working, my problem is, the code generated by golang application is not the same like authy desktop application, what is wrong ?

Resources