| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import * as mangrove from "mangrove-reviews" | 
					
						
							|  |  |  | import { UIEventSource } from "../UIEventSource" | 
					
						
							|  |  |  | import { Review } from "./Review" | 
					
						
							|  |  |  | import { Utils } from "../../Utils" | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class MangroveIdentity { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public keypair: any = undefined | 
					
						
							|  |  |  |     public readonly kid: UIEventSource<string> = new UIEventSource<string>(undefined) | 
					
						
							|  |  |  |     private readonly _mangroveIdentity: UIEventSource<string> | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     constructor(mangroveIdentity: UIEventSource<string>) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const self = this | 
					
						
							|  |  |  |         this._mangroveIdentity = mangroveIdentity | 
					
						
							|  |  |  |         mangroveIdentity.addCallbackAndRunD((str) => { | 
					
						
							| 
									
										
										
										
											2021-06-30 15:42:12 +02:00
										 |  |  |             if (str === "") { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             mangrove.jwkToKeypair(JSON.parse(str)).then((keypair) => { | 
					
						
							|  |  |  |                 self.keypair = keypair | 
					
						
							|  |  |  |                 mangrove.publicToPem(keypair.publicKey).then((pem) => { | 
					
						
							| 
									
										
										
										
											2020-12-11 16:29:51 +01:00
										 |  |  |                     console.log("Identity loaded") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     self.kid.setData(pem) | 
					
						
							| 
									
										
										
										
											2020-12-11 16:29:51 +01:00
										 |  |  |                 }) | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |             }) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-01-07 04:50:12 +01:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2021-12-30 20:41:45 +01:00
										 |  |  |             if (!Utils.runningFromConsole && (mangroveIdentity.data ?? "") === "") { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 this.CreateIdentity() | 
					
						
							| 
									
										
										
										
											2021-01-07 04:50:12 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-04-23 17:22:01 +02:00
										 |  |  |         } catch (e) { | 
					
						
							| 
									
										
										
										
											2021-01-07 04:50:12 +01:00
										 |  |  |             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" | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const self = this | 
					
						
							|  |  |  |         mangrove.generateKeypair().then((keypair) => { | 
					
						
							|  |  |  |             self.keypair = keypair | 
					
						
							|  |  |  |             mangrove.keypairToJwk(keypair).then((jwk) => { | 
					
						
							|  |  |  |                 self._mangroveIdentity.setData(JSON.stringify(jwk)) | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | export default class MangroveReviews { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private static _reviewsCache = {} | 
					
						
							|  |  |  |     private static didWarn = false | 
					
						
							|  |  |  |     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 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 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:22:01 +02:00
										 |  |  |         if (dryRun && !MangroveReviews.didWarn) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             MangroveReviews.didWarn = true | 
					
						
							| 
									
										
										
										
											2021-04-23 17:22:01 +02:00
										 |  |  |             console.warn("Mangrove reviews will _not_ be saved as dryrun is specified") | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     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] | 
					
						
							| 
									
										
										
										
											2021-04-23 17:22:01 +02:00
										 |  |  |         if (cached !== undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return cached | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         MangroveReviews._reviewsCache[uri] = newReviews | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return newReviews | 
					
						
							| 
									
										
										
										
											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() { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         let uri = `geo:${this._lat},${this._lon}?u=50` | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         if (this._name !== undefined && this._name !== null) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             uri += "&q=" + this._name | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return uri | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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[]> { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         if ( | 
					
						
							|  |  |  |             this._lastUpdate !== undefined && | 
					
						
							|  |  |  |             this._reviews.data !== undefined && | 
					
						
							|  |  |  |             new Date().getTime() - this._lastUpdate.getTime() < 15000 | 
					
						
							| 
									
										
										
										
											2021-04-23 17:22:01 +02:00
										 |  |  |         ) { | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |             // Last update was pretty recent
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return this._reviews | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this._lastUpdate = new Date() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2022-12-16 13:45:07 +01:00
										 |  |  |         mangrove | 
					
						
							|  |  |  |             .getReviews({ sub: this.GetSubjectUri() }) | 
					
						
							| 
									
										
										
										
											2022-12-09 13:58:41 +01:00
										 |  |  |             .then((data) => { | 
					
						
							| 
									
										
										
										
											2022-12-16 13:45:07 +01:00
										 |  |  |                 const reviews = [] | 
					
						
							|  |  |  |                 const reviewsByUser = [] | 
					
						
							|  |  |  |                 for (const review of data.reviews) { | 
					
						
							|  |  |  |                     const r = review.payload | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-16 13:45:07 +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 | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                     const rev: Review = { | 
					
						
							|  |  |  |                         made_by_user: byUser, | 
					
						
							|  |  |  |                         date: new Date(r.iat * 1000), | 
					
						
							|  |  |  |                         comment: r.opinion, | 
					
						
							|  |  |  |                         author: r.metadata.nickname, | 
					
						
							|  |  |  |                         affiliated: r.metadata.is_affiliated, | 
					
						
							|  |  |  |                         rating: r.rating, // percentage points
 | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-16 13:45:07 +01:00
										 |  |  |                     ;(rev.made_by_user ? reviewsByUser : reviews).push(rev) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 self._reviews.setData(reviewsByUser.concat(reviews)) | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             .catch((e) => { | 
					
						
							|  |  |  |                 console.error("Could not download review for ", e) | 
					
						
							| 
									
										
										
										
											2022-12-09 13:58:41 +01:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return this._reviews | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     AddReview(r: Review, callback?: () => void) { | 
					
						
							|  |  |  |         callback = | 
					
						
							|  |  |  |             callback ?? | 
					
						
							|  |  |  |             (() => { | 
					
						
							|  |  |  |                 return undefined | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const payload = { | 
					
						
							|  |  |  |             sub: this.GetSubjectUri(), | 
					
						
							|  |  |  |             rating: r.rating, | 
					
						
							|  |  |  |             opinion: r.comment, | 
					
						
							|  |  |  |             metadata: { | 
					
						
							|  |  |  |                 nickname: r.author, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |         if (r.affiliated) { | 
					
						
							|  |  |  |             // @ts-ignore
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             payload.metadata.is_affiliated = true | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         if (this._dryRun) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             console.warn("DRYRUNNING mangrove reviews: ", payload) | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |             if (callback) { | 
					
						
							|  |  |  |                 if (callback) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     callback() | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 this._reviews.data.push(r) | 
					
						
							|  |  |  |                 this._reviews.ping() | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     callback() | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 this._reviews.data.push(r) | 
					
						
							|  |  |  |                 this._reviews.ping() | 
					
						
							| 
									
										
										
										
											2020-12-11 15:27:52 +01:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2020-12-08 23:44:34 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-07 03:02:50 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |