Skip to content

Commit

Permalink
fix: apple api not available
Browse files Browse the repository at this point in the history
feat: notification merge

Signed-off-by: seazhang <[email protected]>
  • Loading branch information
seazhang committed Feb 3, 2023
1 parent d8abcea commit 765a7e4
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 29 deletions.
3 changes: 3 additions & 0 deletions app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ modals: ["MLDW3CH/A","MLDV3CH/A"]

#推送url 需要下载Bark app 在ios可得到 https://api.day.app/xxx
notifyUrl: ["https://api.day.app/xxx"]

#消息是否根据取货地点合并通知
notifyMergedByStore: false
82 changes: 61 additions & 21 deletions apple.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,13 @@ func (apple *Apple) Serve() {
timer = time.NewTimer(time.Duration(apple.configOption.SearchInterval) * time.Second)
}
}
func (apple *Apple) ReqSearch() {
func (apple *Apple) ReqSearch() error {
log.Printf("[I] 开始查询苹果接口. 查询位置:%v", apple.configOption.Location)
appleUrl := apple.makeUrl()
appleUrl, err := apple.makeUrl()
if err != nil {
log.Printf("[E] make url failed. err:%v", err)
return err
}

ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
Expand All @@ -61,49 +65,76 @@ func (apple *Apple) ReqSearch() {
if err != nil {
log.Printf("[E] new request failed. err:%v", err)
}
req.Header.Add("sec-fetch-site", "same-origin")

resp, err := apple.cli.Do(req)
if err != nil {
log.Printf("[E] do request failed. url:%v, err:%v", appleUrl, err)
return
return nil
}

defer resp.Body.Close()

searchResponse, err := apple.unMarshalResp(resp)
if err != nil {
log.Printf("[E] unMarshalResp failed. err:%v", err)
return
return nil
}

messages := make([]*Message, 0, 10)
pickupQuote2IphoneModels := make(map[string][]string)
stores := searchResponse.Body.Content.PickupMessage.Stores
for _, store := range stores {

for _, info := range store.PartsAvailability {
iphoneModal := info.StorePickupProductTitle
pickTime := info.PickupSearchQuote
msgTypes := info.MessageTypes
pickupQuote := info.PickupSearchQuote
pickStore := store.StoreName
iphoneModal := msgTypes.Expanded.StorePickupProductTitle
if iphoneModal == "" {
iphoneModal = msgTypes.Regular.StorePickupProductTitle
}

log.Printf("[I] 型号:%+v 地点:%v %v", iphoneModal, pickStore, pickupQuote)
if !apple.hasStockOffline(info.PickupSearchQuote) {
log.Printf("[E] 型号:%v 地点:%v %v", iphoneModal, pickStore, pickTime)
continue
}

msg := &Message{
Title: iphoneModal,
Content: fmt.Sprintf("取货时间:%v 地点:%v", pickTime, pickStore),
pickupContent := fmt.Sprintf("%v %v", pickStore, pickupQuote)

iphoneModals, ok := pickupQuote2IphoneModels[pickupContent]
if !ok {
iphoneModals = make([]string, 0)
}
iphoneModals = append(iphoneModals, iphoneModal)
pickupQuote2IphoneModels[pickupContent] = iphoneModals
}
}

messages = append(messages, msg)
messages := make([]*Message, 0, 10)
for pickupStore, iphoneModels := range pickupQuote2IphoneModels {
if apple.configOption.NotifyMergedByStore {
messages = append(messages, &Message{
Title: pickupStore,
Content: strings.Join(iphoneModels, ","),
})
continue
}

for _, iphoneModel := range iphoneModels {
messages = append(messages, &Message{
Title: iphoneModel,
Content: pickupStore,
})
}
}

apple.sendNotificationToBarkApp(messages)
apple.sendNotificationToBarkApp(messages...)
return nil
}

func (apple *Apple) sendNotificationToBarkApp(messages []*Message) {
func (apple *Apple) sendNotificationToBarkApp(messages ...*Message) {

for _, msg := range messages {

for _, notifyUrl := range apple.configOption.NotifyUrl {
url := fmt.Sprintf("%v/%v/%v", notifyUrl, msg.Title, msg.Content)
_, err := apple.cli.Get(url)
Expand Down Expand Up @@ -136,18 +167,27 @@ func (apple *Apple) unMarshalResp(resp *http.Response) (*SearchResponse, error)
return searchResponse, nil
}

func (apple *Apple) makeUrl() string {
func (apple *Apple) makeUrl() (string, error) {
values := make(url.Values)
values.Add("mt", "regular")
values.Add("little", "false")
values.Add("pl", "true")
values.Add("location", apple.configOption.Location)

state, city, district, err := apple.configOption.Location.GetParts()
if err != nil {
return "", err
}
values.Add("state", state)
values.Add("city", city)
values.Add("district", district)
values.Add("geoLocated", "true")

// values.Add("mt", "regular")
// values.Add("little", "false")
// values.Add("pl", "true")

for i, modal := range apple.configOption.Modals {
key := fmt.Sprintf("parts.%d", i)
values.Add(key, modal)
}

query := values.Encode()
return fmt.Sprintf("%v?%v", SearchUrl, query)
return fmt.Sprintf("%v?%v", SearchUrl, query), nil
}
46 changes: 38 additions & 8 deletions proto.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,40 @@
package main

import (
"fmt"
"strings"
)

type Message struct {
Title string
Content string
}

type Location string

func (l Location) GetParts() (state, city, district string, err error) {
parts := strings.Split(string(l), " ")
if len(parts) != 3 {
err = fmt.Errorf("location %v format not supported, it should be like '广东 深圳 南山区'", l)
return
}

state = parts[0]
city = parts[0]
district = parts[0]
return
}

type ConfigOption struct {
Modals []string `yaml:"modals"`
NotifyUrl []string `yaml:"notifyUrl"`
Location string `yaml:"location"`
SearchInterval int `yaml:"searchInterval"`
Modals []string `yaml:"modals"`
NotifyUrl []string `yaml:"notifyUrl"`
Location Location `yaml:"location"`
SearchInterval int `yaml:"searchInterval"`
NotifyMergedByStore bool `yaml:"notifyMergedByStore"`
}

type SearchResponse struct {
// Head SearchRespHead `json:"head"`
// Head SearchRespHead `json:"head,omitempty"`
Body SearchRespBody `json:"body"`
}

Expand All @@ -31,7 +52,7 @@ type Content struct {
}

type PickupMessage1 struct {
Stores []Store `json:"stores"`
Stores []*Store `json:"stores"`
}

type Store struct {
Expand All @@ -42,8 +63,17 @@ type Store struct {
type PartsAvailability map[string]PartsAvailabilityValue //型号 => info

type PartsAvailabilityValue struct {
PickupSearchQuote string `json:"pickupSearchQuote"` //可取货
StorePickupProductTitle string `json:"storePickupProductTitle"` //iPhone 13 512GB 粉色
PickupSearchQuote string `json:"pickupSearchQuote"` //可取货
MessageTypes *MessageTypes `json:"messageTypes"`
}

type MessageTypes struct {
Expanded Expanded `json:"expanded,omitempty"`
Regular Expanded `json:"regular,omitempty"`
}

type Expanded struct {
StorePickupProductTitle string `json:"storePickupProductTitle"` //iPhone 14 Pro 128GB 暗紫色
}

//有货
Expand Down
27 changes: 27 additions & 0 deletions proto_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package main

import (
"encoding/json"
"testing"
)

func TestProto(t *testing.T) {
str := `{"head":{"status":"200","data":{}},"body":{"content":{"pickupMessage":{"stores":[{"storeEmail":"[email protected]","storeName":"深圳益田假日广场","reservationUrl":"http://www.apple.com.cn/retail/holidayplazashenzhen","makeReservationUrl":"http://www.apple.com.cn/retail/holidayplazashenzhen","state":"广东","storeImageUrl":"https://rtlimages.apple.com/cmc/dieter/store/4_3/R484.png?resize=828:*&output-format=jpg","country":"CN","city":"深圳","storeNumber":"R484","partsAvailability":{"MQ0D3CH/A":{"storePickEligible":true,"pickupSearchQuote":"今天可取货","partNumber":"MQ0D3CH/A","purchaseOption":"","ctoOptions":"","pickupDisplay":"available","pickupType":"店内取货","messageTypes":{"expanded":{"storeSearchEnabled":true,"storePickupLabel":"立即订购。取货 (店内):","storeSelectionEnabled":true,"storePickupQuote":"今天可取货","storePickupLinkText":"查看其他零售店","storePickupProductTitle":"iPhone 14 Pro 128GB 暗紫色"}}}},"phoneNumber":"4006171254","pickupTypeAvailabilityText":"此地点提供店内取货服务。","address":{"address":"Apple 深圳益田假日广场","address3":null,"address2":"深圳市南山区深南大道 9028 号益田假日广场","postalCode":"518000"},"hoursUrl":"http://www.apple.com.cn/retail/holidayplazashenzhen","storeHours":{"storeHoursText":"Store Hours","bopisPickupDays":"Days","bopisPickupHours":"Hours","hours":[{"storeTimings":"10:00 - 22:30","storeDays":"周五-周六:"},{"storeTimings":"10:00 - 22:00","storeDays":"周一-周四, 周日:"}]},"pickupEncodedUpperDateString":"20230203","storelatitude":22.53986,"storelongitude":113.97079,"storedistance":0.0,"storeDistanceVoText":"null from 518000","retailStore":{"storeNumber":"R484","storeUniqueId":"R484","name":"深圳益田假日广场","storeTypeKey":"1","storeSubTypeKey":"0","storeType":"APPLESTORE_DEFAULT","phoneNumber":"4006171254","email":"[email protected]","carrierCode":null,"locationType":null,"latitude":22.53986,"longitude":113.97079,"address":{"city":"深圳","companyName":"Apple 深圳益田假日广场","countryCode":"CN","county":null,"district":"南山区","geoCode":null,"label":null,"languageCode":"zh-cn","mailStop":null,"postalCode":"518000","province":null,"state":"广东","street":"深圳市南山区深南大道 9028 号益田假日广场","street2":null,"street3":null,"suburb":null,"type":"SHIPPING","addrSourceType":null,"outsideCityFlag":null,"daytimePhoneAreaCode":null,"eveningPhoneAreaCode":null,"daytimePhone":"4006171254","fullPhoneNumber":null,"eveningPhone":null,"emailAddress":null,"firstName":null,"lastName":null,"suffix":null,"lastNamePhonetic":null,"firstNamePhonetic":null,"title":null,"businessAddress":false,"uuid":"4a9fd61c-4cc4-4fa5-896b-e18cf2142089","mobilePhone":null,"mobilePhoneAreaCode":null,"cityStateZip":null,"daytimePhoneSelected":false,"middleName":null,"residenceStatus":null,"moveInDate":null,"subscriberId":null,"locationType":null,"carrierCode":null,"metadata":{},"verificationState":"UN_VERIFIED","expiration":null,"markForDeletion":false,"correctionResult":null,"fullDaytimePhone":"4006171254","fullEveningPhone":null,"twoLineAddress":"深圳市南山区深南大道 9028 号益田假日广场,\n深圳, 广东, 518000","addressVerified":false,"primaryAddress":false},"urlKey":null,"directionsUrl":null,"storeImageUrl":"http://rtlimages.apple.com/cmc/dieter/store/4_3/R484.png?resize=828:*&output-format=jpg","makeReservationUrl":"http://www.apple.com.cn/retail/holidayplazashenzhen","hoursAndInfoUrl":"http://www.apple.com.cn/retail/holidayplazashenzhen","storeHours":[{"storeDays":"周五-周六","voStoreDays":null,"storeTimings":"10:00 - 22:30 "},{"storeDays":"周一-周四, 周日","voStoreDays":null,"storeTimings":"10:00 - 22:00 "}],"storeHolidays":[],"secureStoreImageUrl":"https://rtlimages.apple.com/cmc/dieter/store/4_3/R484.png?resize=828:*&output-format=jpg","distance":0.0,"distanceUnit":"KM","distanceWithUnit":null,"timezone":"Asia/Shanghai","storeIsActive":true,"lastUpdated":0.0,"lastFetched":1675417836438,"dateStamp":"03-Feb-2023","distanceSeparator":".","nextAvailableDate":null,"storeHolidayLookAheadWindow":0,"driveDistanceWithUnit":null,"driveDistanceInMeters":null,"dynamicAttributes":{},"storePickupMethodByType":{"INSTORE":{"type":"INSTORE","typeDirection":{"directionByLocale":null},"typeMeetupLocation":{"meetingLocationByLocale":null},"typeCoordinate":{"lat":22.53986,"lon":113.97079},"services":["APU"]}},"storeTimings":null,"availableNow":true},"storelistnumber":1,"storeListNumber":1,"pickupOptionsDetails":{"whatToExpectAtPickup":"<h4 class=\"as-pickupmethods-intro-header\">取货须知</h4><br />当你的订单准备就绪后,我们会向你发送详细的取货说明电子邮件。有关新设备设置,你可以预约免费在线辅导,让 Specialist 专家为你提供指导。","comparePickupOptionsLink":"<a href=\"https://www.apple.com.cn/shop/shipping-pickup\" data-feature-name=\"Astro Link\" data-display-name=\"AOS: shop/shipping-pickup\" target=\"_blank\">进一步了解送货<br />和取货<span class=\"icon icon-after icon-chevronright\"></span><span class=\"visuallyhidden\">(在新窗口中打开)</span></a>","pickupOptions":[{"pickupOptionTitle":"店内","pickupOptionDescription":"提取你的在线订单商品。你可以获得设置帮助,还能选购配件。可能需要测量体温并佩戴口罩。","index":1}]},"rank":1}],"overlayInitiatedFromWarmStart":true,"viewMoreHoursLinkText":"查看更多时段","storesCount":"1","little":false,"pickupLocationLabel":"你的 Apple Store 零售店:","pickupLocation":"Apple 深圳益田假日广场","notAvailableNearby":"距离最近的 [X] 家零售店今日无货。","notAvailableNearOneStore":"距离最近的零售店今天不可取货。","warmDudeWithAPU":false,"viewMoreHoursVoText":"(在新窗口中打开)","availability":{"isComingSoon":false},"viewDetailsText":"查看详情","availabilityStores":"R484,R577,R639","legendLabelText":"门店","filteredTopStore":false},"deliveryMessage":{"geoLocated":true,"availableOptionsText":"Available Options","MQ0D3CH/A":{"expanded":{"orderByDeliveryBy":"下午 8:00 前订购。","orderByDeliveryBySuffix":"送货至<button class=\"rf-dude-quote-overlay-trigger as-delivery-overlay-trigger as-purchaseinfo-dudetrigger as-buttonlink\" data-autom=\"deliveryDateChecker\" data-ase-overlay=\"dude-overlay\" data-ase-click=\"show\">南山区†† </button>,预计送达日期:","deliveryOptionMessages":[{"displayName":"最快今天 3 小时内 — RMB 45","inHomeSetup":"false","encodedUpperDateStringForIDL":"20230203"},{"displayName":"明天 — 免费","inHomeSetup":"false","encodedUpperDateString":"20230204"}],"deliveryOptions":[{"displayName":"标准送货","date":"明天","shippingCost":"免费","additionalContent":null},{"displayName":"预定时间快递送货","date":"最快今天 3 小时内","shippingCost":"RMB 45","additionalContent":"你可以在结账时选择日期和时间。"}],"deliveryOptionsLink":{"text":"南山区 的可用送货选项†† ","dataVar":{},"newTab":false},"address":{"state":"广东","city":"深圳","district":"南山区"},"showDeliveryOptionsLink":false,"messageType":"Delivery","basePartNumber":"MQ0D3","commitCodeId":"0","dudeAttributes":{"source":{"cutoffFormat":"actualTime","leadByPickup":"true","templateId":"DUDE_APU_N","deliveryOrderSortBy":"speed"},"deliveryHeader":null,"templateID":"DUDE_APU_N","resolvedLabel":"下午 8:00 前订购。","shipMethodsDisplayOrder":["S2","A8"],"fastestShipMethodPriceLabel":null,"leadByPickup":"true"},"subHeader":"适用于 iPhone 14 Pro 128GB 暗紫色","inHomeSetup":false,"defaultLocationEnabled":false,"idl":true,"isBuyable":true,"isElectronic":false}},"geoEnabled":true,"dudeCookieSet":false,"processing":"","contentloaded":"","dudeLocated":false,"locationCookieValueFoundForThisCountry":false,"accessibilityDeliveryOptions":"送货选项"}}}}`

resp := &SearchResponse{}
err := json.Unmarshal([]byte(str), resp)
if err != nil {
t.Fatalf("unmarshal failed. err:%v", err)
}

d, _ := json.Marshal(resp)
t.Logf("data:%s", d)

for _, store := range resp.Body.Content.PickupMessage.Stores {
for _, part := range store.PartsAvailability {
msgTypes := part.MessageTypes
t.Logf("product:%v", msgTypes.Expanded.StorePickupProductTitle)
}

}
}

0 comments on commit 765a7e4

Please sign in to comment.