| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  | import * as mangrove from 'mangrove-reviews' | 
					
						
							|  |  |  | import {UIEventSource} from "../UIEventSource"; | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  | import {Review} from "./Review"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class MangroveIdentity { | 
					
						
							|  |  |  |     private readonly _mangroveIdentity: UIEventSource<string>; | 
					
						
							|  |  |  |     public keypair: any = undefined; | 
					
						
							| 
									
										
										
										
											2020-12-11 16:29:51 +01:00
										 |  |  |     public readonly kid: UIEventSource<string> = new UIEventSource<string>(undefined); | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     constructor(mangroveIdentity: UIEventSource<string>) { | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         this._mangroveIdentity = mangroveIdentity; | 
					
						
							|  |  |  |         mangroveIdentity.addCallbackAndRun(str => { | 
					
						
							|  |  |  |             if (str === undefined || str === "") { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             mangrove.jwkToKeypair(JSON.parse(str)).then(keypair => { | 
					
						
							|  |  |  |                 self.keypair = keypair; | 
					
						
							| 
									
										
										
										
											2020-12-11 16:29:51 +01:00
										 |  |  |                 mangrove.publicToPem(keypair.publicKey).then(pem => { | 
					
						
							|  |  |  |                     console.log("Identity loaded") | 
					
						
							|  |  |  |                     self.kid.setData(pem); | 
					
						
							|  |  |  |                 }) | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |             }) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-01-07 04:50:12 +01:00
										 |  |  |         try { | 
					
						
							|  |  |  |             if ((mangroveIdentity.data ?? "") === "") { | 
					
						
							|  |  |  |                 this.CreateIdentity(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }catch(e){ | 
					
						
							|  |  |  |             console.error("Could not create identity: ", e) | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Creates an identity if none exists already. | 
					
						
							|  |  |  |      * Is written into the UIEventsource, which was passed into the constructor | 
					
						
							|  |  |  |      * @constructor | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private CreateIdentity() { | 
					
						
							|  |  |  |         if ("" !== (this._mangroveIdentity.data ?? "")) { | 
					
						
							|  |  |  |             throw "Identity already defined - not creating a new one" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         mangrove.generateKeypair().then( | 
					
						
							|  |  |  |             keypair => { | 
					
						
							|  |  |  |                 self.keypair = keypair; | 
					
						
							|  |  |  |                 mangrove.keypairToJwk(keypair).then(jwk => { | 
					
						
							|  |  |  |                     self._mangroveIdentity.setData(JSON.stringify(jwk)); | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | export default class MangroveReviews { | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |     private readonly _lon: number; | 
					
						
							|  |  |  |     private readonly _lat: number; | 
					
						
							|  |  |  |     private readonly _name: string; | 
					
						
							|  |  |  |     private readonly _reviews: UIEventSource<Review[]> = new UIEventSource<Review[]>([]); | 
					
						
							|  |  |  |     private _dryRun: boolean; | 
					
						
							|  |  |  |     private _mangroveIdentity: MangroveIdentity; | 
					
						
							|  |  |  |     private _lastUpdate : Date = undefined; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static _reviewsCache = {}; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     public static Get(lon: number, lat: number, name: string, | 
					
						
							|  |  |  |                       identity: MangroveIdentity, | 
					
						
							|  |  |  |                       dryRun?: boolean){ | 
					
						
							|  |  |  |         const newReviews = new MangroveReviews(lon, lat, name, identity, dryRun); | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         const uri = newReviews.GetSubjectUri(); | 
					
						
							|  |  |  |         const cached = MangroveReviews._reviewsCache[uri]; | 
					
						
							|  |  |  |         if(cached !== undefined){ | 
					
						
							|  |  |  |             return cached; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         MangroveReviews._reviewsCache[uri] = newReviews; | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         return newReviews; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |    private constructor(lon: number, lat: number, name: string, | 
					
						
							|  |  |  |                 identity: MangroveIdentity, | 
					
						
							|  |  |  |                 dryRun?: boolean) { | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |         this._lon = lon; | 
					
						
							|  |  |  |         this._lat = lat; | 
					
						
							|  |  |  |         this._name = name; | 
					
						
							|  |  |  |         this._mangroveIdentity = identity; | 
					
						
							|  |  |  |         this._dryRun = dryRun; | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Gets an URI which represents the item in a mangrove-compatible way | 
					
						
							|  |  |  |      * @constructor | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public GetSubjectUri() { | 
					
						
							|  |  |  |         let uri = `geo:${this._lat},${this._lon}?u=50`; | 
					
						
							|  |  |  |         if (this._name !== undefined && this._name !== null) { | 
					
						
							|  |  |  |             uri += "&q=" + this._name; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return uri; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Gives a UIEVentsource with all reviews. | 
					
						
							|  |  |  |      * Note: rating is between 1 and 100 | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |     public GetReviews(): UIEventSource<Review[]> { | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         if(this._lastUpdate !== undefined && this._reviews.data !== undefined && | 
					
						
							|  |  |  |             (new Date().getTime() - this._lastUpdate.getTime()) < 15000 | 
					
						
							|  |  |  |         ){ | 
					
						
							|  |  |  |             // Last update was pretty recent
 | 
					
						
							|  |  |  |             return this._reviews; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         this._lastUpdate = new Date(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         mangrove.getReviews({sub: this.GetSubjectUri()}).then( | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  |             (data) => { | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |                 const reviews = []; | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |                 const reviewsByUser = []; | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  |                 for (const review of data.reviews) { | 
					
						
							|  |  |  |                     const r = review.payload; | 
					
						
							| 
									
										
										
										
											2020-12-11 16:29:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     console.log("PublicKey is ", self._mangroveIdentity.kid.data, "reviews.kid is", review.kid); | 
					
						
							|  |  |  |                     const byUser = self._mangroveIdentity.kid.map(data => data === review.signature); | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |                     const rev: Review = { | 
					
						
							|  |  |  |                         made_by_user: byUser, | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  |                         date: new Date(r.iat * 1000), | 
					
						
							|  |  |  |                         comment: r.opinion, | 
					
						
							|  |  |  |                         author: r.metadata.nickname, | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |                         affiliated: r.metadata.is_affiliated, | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  |                         rating: r.rating // percentage points
 | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |                     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     (rev.made_by_user ? reviewsByUser : reviews).push(rev); | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-12-11 16:29:51 +01:00
										 |  |  |                 self._reviews.setData(reviewsByUser.concat(reviews)) | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         return this._reviews; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     AddReview(r: Review, callback?: (() => void)) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         callback = callback ?? (() => { | 
					
						
							|  |  |  |             return undefined; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const payload = { | 
					
						
							|  |  |  |             sub: this.GetSubjectUri(), | 
					
						
							|  |  |  |             rating: r.rating, | 
					
						
							|  |  |  |             opinion: r.comment, | 
					
						
							|  |  |  |             metadata: { | 
					
						
							|  |  |  |                 nickname: r.author, | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |         if (r.affiliated) { | 
					
						
							|  |  |  |             // @ts-ignore
 | 
					
						
							|  |  |  |             payload.metadata.is_affiliated = true; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         if (this._dryRun) { | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |             console.warn("DRYRUNNING mangrove reviews: ", payload); | 
					
						
							|  |  |  |             if (callback) { | 
					
						
							|  |  |  |                 if (callback) { | 
					
						
							|  |  |  |                     console.log("Calling callback") | 
					
						
							|  |  |  |                     callback(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 this._reviews.data.push(r); | 
					
						
							|  |  |  |                 this._reviews.ping(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |             mangrove.signAndSubmitReview(this._mangroveIdentity.keypair, payload).then(() => { | 
					
						
							|  |  |  |                 if (callback) { | 
					
						
							|  |  |  |                     console.log("Calling callback") | 
					
						
							|  |  |  |                     callback(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 this._reviews.data.push(r); | 
					
						
							|  |  |  |                 this._reviews.ping(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |