1
+ import { IAgentRuntime } from "@ai16z/eliza" ;
2
+
3
+ // Types and Interfaces
4
+ interface Address {
5
+ Street : string ;
6
+ City : string ;
7
+ Region : string ;
8
+ PostalCode : string ;
9
+ }
10
+
11
+ interface CustomerInfo {
12
+ FirstName : string ;
13
+ LastName : string ;
14
+ Email : string ;
15
+ Phone : string ;
16
+ }
17
+
18
+ interface PizzaOption {
19
+ [ key : string ] : {
20
+ [ key : string ] : string ;
21
+ } ;
22
+ }
23
+
24
+ interface Product {
25
+ Code : string ;
26
+ Options : PizzaOption ;
27
+ }
28
+
29
+ interface Payment {
30
+ Type : string ;
31
+ Amount : number ;
32
+ CardType : string ;
33
+ Number : string ;
34
+ Expiration : string ;
35
+ SecurityCode : string ;
36
+ PostalCode : string ;
37
+ TipAmount : number ;
38
+ }
39
+
40
+ interface OrderRequest {
41
+ Address : Address ;
42
+ StoreID : string ;
43
+ Products : Product [ ] ;
44
+ OrderChannel : string ;
45
+ OrderMethod : string ;
46
+ LanguageCode : string ;
47
+ ServiceMethod : string ;
48
+ Payments ?: Payment [ ] ;
49
+ FirstName ?: string ;
50
+ LastName ?: string ;
51
+ Email ?: string ;
52
+ Phone ?: string ;
53
+ }
54
+
55
+ export class PizzaAPI {
56
+ private readonly BASE_URL : string ;
57
+ private readonly TRACKER_URL : string ;
58
+
59
+ private readonly headers = {
60
+ 'Accept' : 'application/json' ,
61
+ 'Content-Type' : 'application/json' ,
62
+ 'Referer' : 'order.dominos.com'
63
+ } ;
64
+
65
+ private readonly trackerHeaders = {
66
+ 'dpz-language' : 'en' ,
67
+ 'dpz-market' : 'UNITED_STATES' ,
68
+ 'Accept' : 'application/json' ,
69
+ 'Content-Type' : 'application/json; charset=utf-8'
70
+ } ;
71
+
72
+ constructor ( private runtime : IAgentRuntime ) {
73
+ this . BASE_URL = this . runtime . getSetting ( 'API_BASE_URL' ) || 'https://order.dominos.com/power' ;
74
+ this . TRACKER_URL = this . runtime . getSetting ( 'API_TRACKER_URL' ) || 'https://tracker.dominos.com/tracker-presentation-service/v2' ;
75
+ }
76
+
77
+ // Helper function to get required setting
78
+ private getRequiredSetting ( name : string ) : string {
79
+ const value = this . runtime . getSetting ( name ) ;
80
+ if ( ! value ) {
81
+ throw new Error ( `Required setting ${ name } is not configured` ) ;
82
+ }
83
+ return value ;
84
+ }
85
+
86
+ // Function to get customer info from settings
87
+ private getCustomerInfo ( ) : CustomerInfo {
88
+ return {
89
+ FirstName : this . getRequiredSetting ( 'CUSTOMER_FIRST_NAME' ) ,
90
+ LastName : this . getRequiredSetting ( 'CUSTOMER_LAST_NAME' ) ,
91
+ Email : this . getRequiredSetting ( 'CUSTOMER_EMAIL' ) ,
92
+ Phone : this . getRequiredSetting ( 'CUSTOMER_PHONE' )
93
+ } ;
94
+ }
95
+
96
+ // Function to get address from settings
97
+ private getAddress ( ) : Address {
98
+ return {
99
+ Street : this . getRequiredSetting ( 'CUSTOMER_STREET' ) ,
100
+ City : this . getRequiredSetting ( 'CUSTOMER_CITY' ) ,
101
+ Region : this . getRequiredSetting ( 'CUSTOMER_REGION' ) ,
102
+ PostalCode : this . getRequiredSetting ( 'CUSTOMER_POSTAL_CODE' )
103
+ } ;
104
+ }
105
+
106
+ // Function to get payment info from settings
107
+ private getPayment ( amount : number ) : Payment {
108
+ return {
109
+ Type : 'CreditCard' ,
110
+ Amount : amount ,
111
+ CardType : this . detectCardType ( this . getRequiredSetting ( 'PAYMENT_CARD_NUMBER' ) ) ,
112
+ Number : this . getRequiredSetting ( 'PAYMENT_CARD_NUMBER' ) ,
113
+ Expiration : this . getRequiredSetting ( 'PAYMENT_EXPIRATION' ) ,
114
+ SecurityCode : this . getRequiredSetting ( 'PAYMENT_CVV' ) ,
115
+ PostalCode : this . getRequiredSetting ( 'PAYMENT_POSTAL_CODE' ) ,
116
+ TipAmount : parseFloat ( this . getRequiredSetting ( 'PAYMENT_TIP_AMOUNT' ) )
117
+ } ;
118
+ }
119
+
120
+ private detectCardType ( cardNumber : string ) : string {
121
+ if ( cardNumber . startsWith ( '4' ) ) return 'VISA' ;
122
+ if ( cardNumber . startsWith ( '5' ) ) return 'MASTERCARD' ;
123
+ if ( cardNumber . startsWith ( '34' ) || cardNumber . startsWith ( '37' ) ) return 'AMEX' ;
124
+ if ( cardNumber . startsWith ( '6' ) ) return 'DISCOVER' ;
125
+ return 'UNKNOWN' ;
126
+ }
127
+
128
+ async findNearestStore ( ) : Promise < any > {
129
+ const address = this . getAddress ( ) ;
130
+ const encodedAddress = encodeURIComponent ( address . Street ) ;
131
+ const encodedCityState = encodeURIComponent ( `${ address . City } , ${ address . Region } ` ) ;
132
+ const url = `${ this . BASE_URL } /store-locator?s=${ encodedAddress } &c=${ encodedCityState } &type=Delivery` ;
133
+
134
+ const response = await fetch ( url , {
135
+ method : 'GET' ,
136
+ headers : this . headers
137
+ } ) ;
138
+ return response . json ( ) ;
139
+ }
140
+
141
+ async getStoreInfo ( storeId : string ) : Promise < any > {
142
+ const url = `${ this . BASE_URL } /store/${ storeId } /profile` ;
143
+ const response = await fetch ( url , {
144
+ method : 'GET' ,
145
+ headers : this . headers
146
+ } ) ;
147
+ return response . json ( ) ;
148
+ }
149
+
150
+ async validateOrder ( orderData : OrderRequest ) : Promise < any > {
151
+ const url = `${ this . BASE_URL } /validate-order` ;
152
+ const response = await fetch ( url , {
153
+ method : 'POST' ,
154
+ headers : this . headers ,
155
+ body : JSON . stringify ( { Order : orderData } )
156
+ } ) ;
157
+ return response . json ( ) ;
158
+ }
159
+
160
+ async priceOrder ( orderData : OrderRequest ) : Promise < any > {
161
+ const url = `${ this . BASE_URL } /price-order` ;
162
+ const response = await fetch ( url , {
163
+ method : 'POST' ,
164
+ headers : this . headers ,
165
+ body : JSON . stringify ( { Order : orderData } )
166
+ } ) ;
167
+ return response . json ( ) ;
168
+ }
169
+
170
+ async placeOrder ( orderData : OrderRequest ) : Promise < any > {
171
+ const url = `${ this . BASE_URL } /place-order` ;
172
+ const response = await fetch ( url , {
173
+ method : 'POST' ,
174
+ headers : this . headers ,
175
+ body : JSON . stringify ( { Order : orderData } )
176
+ } ) ;
177
+ return response . json ( ) ;
178
+ }
179
+
180
+ async trackOrder ( ) : Promise < any > {
181
+ const customerPhone = this . getRequiredSetting ( 'CUSTOMER_PHONE' ) ;
182
+ const url = `${ this . TRACKER_URL } /orders?phonenumber=${ customerPhone . replace ( / \D / g, '' ) } ` ;
183
+ const response = await fetch ( url , {
184
+ method : 'GET' ,
185
+ headers : this . trackerHeaders
186
+ } ) ;
187
+ return response . json ( ) ;
188
+ }
189
+
190
+ async orderPizza ( ) {
191
+ try {
192
+ // 1. Find nearest store using settings address
193
+ const storeResponse = await this . findNearestStore ( ) ;
194
+ console . log ( 'Store Response:' , JSON . stringify ( storeResponse , null , 2 ) ) ;
195
+ const storeId = storeResponse . Stores [ 0 ] . StoreID ;
196
+
197
+ // 2. Get store info
198
+ const storeInfo = await this . getStoreInfo ( storeId ) ;
199
+ console . log ( 'Store Info:' , JSON . stringify ( storeInfo , null , 2 ) ) ;
200
+
201
+ // 3. Create order request
202
+ const address = this . getAddress ( ) ;
203
+ const orderRequest : OrderRequest = {
204
+ Address : address ,
205
+ StoreID : storeId ,
206
+ Products : [ {
207
+ Code : '14SCREEN' ,
208
+ Options : {
209
+ X : { '1/1' : '1' } ,
210
+ C : { '1/1' : '1' } ,
211
+ }
212
+ } ] ,
213
+ OrderChannel : 'OLO' ,
214
+ OrderMethod : 'Web' ,
215
+ LanguageCode : 'en' ,
216
+ ServiceMethod : 'Delivery'
217
+ } ;
218
+
219
+ // 4. Validate order
220
+ const validatedOrder = await this . validateOrder ( orderRequest ) ;
221
+ console . log ( 'Validated Order:' , JSON . stringify ( validatedOrder , null , 2 ) ) ;
222
+
223
+ // 5. Price order
224
+ const pricedOrder = await this . priceOrder ( orderRequest ) ;
225
+ console . log ( 'Priced Order:' , JSON . stringify ( pricedOrder , null , 2 ) ) ;
226
+
227
+ // 6. Add payment and customer info for final order
228
+ const customerInfo = this . getCustomerInfo ( ) ;
229
+ const finalOrder : OrderRequest = {
230
+ ...orderRequest ,
231
+ FirstName : customerInfo . FirstName ,
232
+ LastName : customerInfo . LastName ,
233
+ Email : customerInfo . Email ,
234
+ Phone : customerInfo . Phone ,
235
+ Payments : [ this . getPayment ( pricedOrder . Order . Amounts . Customer ) ]
236
+ } ;
237
+
238
+ // 7. Place order
239
+ const placedOrder = await this . placeOrder ( finalOrder ) ;
240
+ console . log ( 'Placed Order:' , JSON . stringify ( placedOrder , null , 2 ) ) ;
241
+
242
+ // 8. Track order
243
+ const trackingInfo = await this . trackOrder ( ) ;
244
+ console . log ( 'Tracking Info:' , JSON . stringify ( trackingInfo , null , 2 ) ) ;
245
+
246
+ return {
247
+ storeInfo,
248
+ orderDetails : placedOrder ,
249
+ tracking : trackingInfo
250
+ } ;
251
+ } catch ( error ) {
252
+ console . error ( 'Error ordering pizza:' , error ) ;
253
+ throw error ;
254
+ }
255
+ }
256
+ }
0 commit comments