feat: Initial commit
This commit is contained in:
commit
1ac8367a50
5 changed files with 307 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
uber-tracker
|
5
go.mod
Normal file
5
go.mod
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module uber-tracker
|
||||||
|
|
||||||
|
go 1.15
|
||||||
|
|
||||||
|
require git.ddd.rip/ptrcnull/telegram v0.0.4
|
2
go.sum
Normal file
2
go.sum
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
git.ddd.rip/ptrcnull/telegram v0.0.4 h1:b4VaLAdIUuEFG5DRM+JzfLEVoe4tdHhrgxtmoF2UJOQ=
|
||||||
|
git.ddd.rip/ptrcnull/telegram v0.0.4/go.mod h1:SSSKvfhw7mDx/8UPoLdtP9J74z2/pXccHnKzdi16nLA=
|
145
main.go
Normal file
145
main.go
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"git.ddd.rip/ptrcnull/telegram"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetUberData(uuid string) (*UberDataOrder, error) {
|
||||||
|
requestBody := []byte(fmt.Sprintf("{\"orderUuid\":\"%s\"}", uuid))
|
||||||
|
req, err := http.NewRequest("POST", "https://www.ubereats.com/api/getActiveOrdersV1", bytes.NewBuffer(requestBody))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("x-csrf-token", "x")
|
||||||
|
|
||||||
|
res, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.StatusCode != 200 {
|
||||||
|
body, err := ioutil.ReadAll(res.Body)
|
||||||
|
log.Println(string(body), err)
|
||||||
|
return nil, fmt.Errorf("unexpected status code: %d", res.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var data UberResponse
|
||||||
|
err = json.NewDecoder(res.Body).Decode(&data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, order := range data.Data.Orders {
|
||||||
|
if order.UUID == uuid {
|
||||||
|
return &order, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("order not found: %s", uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Order struct {
|
||||||
|
ChatID string
|
||||||
|
UberData *UberDataOrder
|
||||||
|
MessageID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c := telegram.Client{
|
||||||
|
Token: os.Getenv("TELEGRAM_TOKEN"),
|
||||||
|
}
|
||||||
|
sendMessage := func(chatId, body string) *telegram.SendMessageResponse {
|
||||||
|
res, err := c.SendMessage(chatId, body)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error sending message:", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
var orders []*Order
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
for i, order := range orders {
|
||||||
|
log.Println("Getting data for order", order.UberData.UUID)
|
||||||
|
newData, err := GetUberData(order.UberData.UUID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
sendMessage(order.ChatID, "order completed: "+order.UberData.UUID)
|
||||||
|
orders = append(orders[:i], orders[i+1:]...)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
oldStatus := order.UberData.Status()
|
||||||
|
newStatus := newData.Status()
|
||||||
|
if oldStatus != newStatus {
|
||||||
|
_, err := c.EditMessageText(order.ChatID, order.MessageID, newStatus)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
order.UberData = newData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
log.Println("Getting updates...")
|
||||||
|
upd, err := c.GetUpdates()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("updates:", len(upd.Result))
|
||||||
|
for _, update := range upd.Result {
|
||||||
|
if update.Message != nil && strings.HasPrefix(update.Message.Text, "/add") {
|
||||||
|
chatId := strconv.FormatInt(update.Message.Chat.ID, 10)
|
||||||
|
|
||||||
|
orderId := strings.Split(update.Message.Text, " ")[1]
|
||||||
|
data, err := GetUberData(orderId)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
sendMessage(chatId, "error: "+err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Printf("%#v\n", data)
|
||||||
|
sendMessage(chatId, "added new order: "+data.OrderInfo.StoreInfo.Name)
|
||||||
|
status := data.Status()
|
||||||
|
res := sendMessage(chatId, status)
|
||||||
|
if res != nil {
|
||||||
|
orders = append(orders, &Order{
|
||||||
|
ChatID: chatId,
|
||||||
|
UberData: data,
|
||||||
|
MessageID: strconv.FormatInt(res.Result.MessageID, 10),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if update.Message != nil && strings.HasPrefix(update.Message.Text, "/contact") {
|
||||||
|
chatId := strconv.FormatInt(update.Message.Chat.ID, 10)
|
||||||
|
|
||||||
|
orderId := strings.Split(update.Message.Text, " ")[1]
|
||||||
|
data, err := GetUberData(orderId)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
sendMessage(chatId, "error: "+err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, contact := range data.Contacts {
|
||||||
|
sendMessage(chatId, contact.Title + ": " + contact.FormattedPhoneNumber)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
154
types.go
Normal file
154
types.go
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
type UberResponse struct {
|
||||||
|
Status string `json:"status"`
|
||||||
|
Data UberData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UberData struct {
|
||||||
|
Orders []UberDataOrder `json:"orders"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Contact struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
PhoneNumber string `json:"phoneNumber"`
|
||||||
|
FormattedPhoneNumber string `json:"formattedPhoneNumber"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActiveOrderOverview struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Subtitle string `json:"subtitle"`
|
||||||
|
BackgroundImageURL string `json:"backgroundImageUrl"`
|
||||||
|
Items []struct {
|
||||||
|
ShoppingCartItemUUID string `json:"shoppingCartItemUUID"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Quantity int `json:"quantity"`
|
||||||
|
Subtitle string `json:"subtitle"`
|
||||||
|
} `json:"items"`
|
||||||
|
Actions interface{} `json:"actions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type InAppNotification struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Subtitle string `json:"subtitle"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FeedCardStatus struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Subtitle string `json:"subtitle"`
|
||||||
|
TimelineSummary string `json:"timelineSummary"`
|
||||||
|
StatusSummary struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
InfoText string `json:"infoText"`
|
||||||
|
InfoBody string `json:"infoBody"`
|
||||||
|
} `json:"statusSummary"`
|
||||||
|
CurrentProgress int `json:"currentProgress"`
|
||||||
|
TotalProgressSegments int `json:"totalProgressSegments"`
|
||||||
|
AnimateCurrentProgressSegment bool `json:"animateCurrentProgressSegment"`
|
||||||
|
Actions interface{} `json:"actions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FeedCard struct {
|
||||||
|
Status FeedCardStatus `json:"status,omitempty"`
|
||||||
|
MapEntity interface{} `json:"mapEntity"`
|
||||||
|
Courier interface{} `json:"courier"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Savings struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
IconImageURL string `json:"iconImageUrl"`
|
||||||
|
} `json:"savings,omitempty"`
|
||||||
|
Delivery struct {
|
||||||
|
FormattedAddress string `json:"formattedAddress"`
|
||||||
|
DeliveryTypeDescription string `json:"deliveryTypeDescription"`
|
||||||
|
SpecialInstructions string `json:"specialInstructions"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Paragraphs []struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Subtitle string `json:"subtitle,omitempty"`
|
||||||
|
} `json:"paragraphs"`
|
||||||
|
} `json:"delivery,omitempty"`
|
||||||
|
OrderSummary struct {
|
||||||
|
RestaurantName string `json:"restaurantName"`
|
||||||
|
Items []struct {
|
||||||
|
ShoppingCartItemUUID string `json:"shoppingCartItemUUID"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Quantity int `json:"quantity"`
|
||||||
|
Subtitle string `json:"subtitle"`
|
||||||
|
} `json:"items"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Sections []interface{} `json:"sections"`
|
||||||
|
TotalLabel string `json:"totalLabel"`
|
||||||
|
} `json:"orderSummary,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BackgroundFeedCard struct {
|
||||||
|
MapEntity []struct {
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Latitude float64 `json:"latitude"`
|
||||||
|
Longitude float64 `json:"longitude"`
|
||||||
|
Course float64 `json:"course,omitempty"`
|
||||||
|
Subtitle interface{} `json:"subtitle"`
|
||||||
|
PathPoints []struct {
|
||||||
|
Epoch int64 `json:"epoch"`
|
||||||
|
Latitude float64 `json:"latitude"`
|
||||||
|
Longitude float64 `json:"longitude"`
|
||||||
|
Course float64 `json:"course"`
|
||||||
|
} `json:"pathPoints"`
|
||||||
|
IconURL string `json:"iconUrl,omitempty"`
|
||||||
|
SpriteCount int `json:"spriteCount,omitempty"`
|
||||||
|
SpriteSize int `json:"spriteSize,omitempty"`
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
|
} `json:"mapEntity"`
|
||||||
|
Courier interface{} `json:"courier"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UberDataOrder struct {
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
Contacts []Contact `json:"contacts"`
|
||||||
|
Actions interface{} `json:"actions"`
|
||||||
|
BottomSheets interface{} `json:"bottomSheets"`
|
||||||
|
OrderInfo OrderInfo `json:"orderInfo"`
|
||||||
|
ActiveOrderOverview ActiveOrderOverview `json:"activeOrderOverview"`
|
||||||
|
InAppNotification InAppNotification `json:"inAppNotification"`
|
||||||
|
FeedCards []FeedCard `json:"feedCards"`
|
||||||
|
BackgroundFeedCards []BackgroundFeedCard `json:"backgroundFeedCards"`
|
||||||
|
Layout string `json:"layout"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *UberDataOrder) Status() string {
|
||||||
|
for _, feedCard := range o.FeedCards {
|
||||||
|
if feedCard.Type == "status" {
|
||||||
|
c := feedCard.Status
|
||||||
|
return c.Subtitle + " " + c.Title + "\n" + c.TimelineSummary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderInfo struct {
|
||||||
|
OrderPhase string `json:"orderPhase"`
|
||||||
|
StoreInfo struct {
|
||||||
|
StoreUUID string `json:"storeUUID"`
|
||||||
|
TerritoryUUID string `json:"territoryUUID"`
|
||||||
|
Location struct {
|
||||||
|
Address struct {
|
||||||
|
Address1 string `json:"address1"`
|
||||||
|
City string `json:"city"`
|
||||||
|
Country string `json:"country"`
|
||||||
|
PostalCode string `json:"postalCode"`
|
||||||
|
Region string `json:"region"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
} `json:"address"`
|
||||||
|
Latitude float64 `json:"latitude"`
|
||||||
|
Longitude float64 `json:"longitude"`
|
||||||
|
} `json:"location"`
|
||||||
|
WebURL string `json:"webURL"`
|
||||||
|
HeroImageURL string `json:"heroImageURL"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"storeInfo"`
|
||||||
|
OrderCategory string `json:"orderCategory"`
|
||||||
|
CustomerInfos interface{} `json:"customerInfos"`
|
||||||
|
}
|
Loading…
Reference in a new issue