123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- import { Component } from "@angular/core";
- import {
- IonicPage,
- NavController,
- NavParams,
- LoadingController,
- AlertController
- } from "ionic-angular";
- import {
- FormBuilder,
- Validators,
- FormGroup,
- ValidatorFn,
- AbstractControl
- } from "@angular/forms";
- import { TwitterApiProvider } from "../../providers/twitter-api/twitter-api";
- import { Storage } from "@ionic/storage";
- import { P2pStorageIpfsProvider } from "../../providers/p2p-storage-ipfs/p2p-storage-ipfs";
- import { P2pDatabaseGunProvider } from "../../providers/p2p-database-gun/p2p-database-gun";
- import twittertext from "twitter-text";
- import { CryptoProvider } from "../../providers/crypto/crypto";
- import * as openpgp from 'openpgp';
- @IonicPage()
- @Component({
- selector: "page-write-tweet",
- templateUrl: "write-tweet.html"
- })
- export class WriteTweetPage {
- tweet: FormGroup;
- retweetId: string;
- replyToStatusId: string;
- retweet;
- replyTweet;
- openpgp;
- privateKey;
- publicKey;
- pk: any[]=[];
- passp = 'super long and hard to guess secret';
- hkp = new openpgp.HKP();
-
- constructor(
- public navCtrl: NavController,
- public navParams: NavParams,
- private formBuilder: FormBuilder,
- private twitter: TwitterApiProvider,
- private loadingCtrl: LoadingController,
- private storage: Storage,
- private ipfs: P2pStorageIpfsProvider,
- private gun: P2pDatabaseGunProvider,
- private cryptoUtils: CryptoProvider,
- private alertCtrl: AlertController
- ) {
- this.retweetId = this.navParams.get("tweetId");
- this.replyToStatusId = this.navParams.get("replyToStatus");
- this.tweet = this.formBuilder.group({
- text: [""],
- p2p: [false]
- });
- this.addValidators();
- // this.encryptDecryptFunction();
- }
- // public async encryptDecryptFunction () {
- // await openpgp.initWorker({path:'assets/scripts/openpgp.worker.js'});
- // let a = await this.generateKeys();
- // console.log('a is:',a.publicKeyArmored);
- // let b = await this.generateKeys();
- // console.log('b is:',b.publicKeyArmored);
- // let c = await this.generateKeys();
- // this.privateKey =c.privateKeyArmored;
- // this.publicKey = c.publicKeyArmored;
- // this.pk.push(a.publicKeyArmored);
- // this.pk.push(b.publicKeyArmored);
- // // this.pk = [`----BEGIN PGP PUBLIC KEY BLOCK-----
- // // Version: OpenPGP.js v4.7.1
- // // Comment: https://openpgpjs.org
- // // xjMEXfAn1xYJKwYBBAHaRw8BAQdAAMVNOABw8MBtrtYR8KC3tSro3wITyApT
- // // TVjKVCppD+DNG0pvbiBTbWl0aCA8am9uQGV4YW1wbGUuY29tPsJ3BBAWCgAf
- // // BQJd8CfXBgsJBwgDAgQVCAoCAxYCAQIZAQIbAwIeAQAKCRD+efBRXzuMsfA7
- // // AQCEgoToFzv2hT9BREdiQp531/AHSyoZWmWvSZSvmga40gD8C+zwbCySnkhQ
- // // pb4L0DCKtSDa7pLg2g0OcxJlbSZWHQ3OOARd8CfXEgorBgEEAZdVAQUBAQdA
- // // p4mVY17dPWf6VCBqW10Ybk5JgUO6FK0OsETWw3gG2zcDAQgHwmEEGBYIAAkF
- // // Al3wJ9cCGwwACgkQ/nnwUV87jLFHbAD9GyoL7dcTDGQoqtrhKozdgnzfugTb
- // // er0bwU15WNMjefkA/jEqK9YUNcRrFKIuac9PVibGgutL8ak7ukysw6iTcCsM
- // // =fmhE
- // // -----END PGP PUBLIC KEY BLOCK-----`,
- // // `-----BEGIN PGP PUBLIC KEY BLOCK-----
- // // Version: OpenPGP.js v4.7.1
- // // Comment: https://openpgpjs.org
- // // xjMEXfAn1hYJKwYBBAHaRw8BAQdAsF1ivpd0HU8ogj02LDv6BTOxNMWGZaEc
- // // OyZBwqoYJPrNG0pvbiBTbWl0aCA8am9uQGV4YW1wbGUuY29tPsJ3BBAWCgAf
- // // BQJd8CfWBgsJBwgDAgQVCAoCAxYCAQIZAQIbAwIeAQAKCRDEruv77flRJ32B
- // // AP93GIBcUW2okROoZZhdPVeqjRD72Ft64imXpdZ0jx4ohgEA5Kv9vs2kV73q
- // // k6fcdf7qD/i5gMExU0+vV05c9VxBYwfOOARd8CfWEgorBgEEAZdVAQUBAQdA
- // // 1J7E03ZopUnsIeNzeiZvba6qxhhUbpmBZ1aN1HhWUlEDAQgHwmEEGBYIAAkF
- // // Al3wJ9YCGwwACgkQxK7r++35USdTqQD/ZEg8X5tMx75nQe4mGlyiRjmmtWLw
- // // n9bslTdjBIszs/EA/R1WIm6ji4Ru1dJWc3ISisz78xTM2H8U7fnP8yjFcWcD
- // // =hgnW
- // // -----END PGP PUBLIC KEY BLOCK-----`];
- // console.log('array of pub keys is :',this.pk);
- // this.pk = this.pk.map(async (key) => {
- // return (await openpgp.key.readArmored(key)).keys[0]
- // });
- // console.log('priv key: ',this.privateKey,'this.pubkey',this.pk);
- // let encrypted;
- // const privKeyObj = (await openpgp.key.readArmored(this.privateKey)).keys[0];
- // console.log('privKeyObj',privKeyObj);
- // const bla = await privKeyObj.decrypt(this.passp);
- // // const options = {
- // // message: openpgp.message.fromText('Hello, World!'), // input as Message object
- // // publicKeys: (await openpgp.key.readArmored(this.publicKey)).keys, // for encryption
- // // privateKeys: [privKeyObj] // for signing (optional)
- // // }
- // const options = {
- // message: openpgp.message.fromText('Hello, World!'), // input as Message object
- // publicKeys: await Promise.all(this.pk), // for encryption
- // privateKeys: [privKeyObj] // for signing (optional)
- // }
- // const ciphertext = await openpgp.encrypt(options);
- // encrypted = ciphertext.data; // '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----'
- // console.log('encrypted is:',encrypted);
-
- // let aprivKeyObj = (await openpgp.key.readArmored(a.privateKeyArmored)).keys[0];
- // await aprivKeyObj.decrypt(this.passp);
- // const options2 = {
- // message: await openpgp.message.readArmored(encrypted), // parse armored message
- // privateKeys: [aprivKeyObj] // for decryption
- // }
- // console.log('options2 is: ',options2);
- // let plaintext = await openpgp.decrypt(options2);
- // console.log('decrypted text is:',plaintext,plaintext.data);
- // return plaintext.data // 'Hello, World!'
- // }
- // public async generateKeys(){
- // let options = {
- // userIds: [{ name:'Jon Smith', email:'jon@example.com' }], // multiple user IDs
- // curve: "ed25519", // ECC curve name
- // passphrase: this.passp // protects the private key
- // };
-
- // let a = await openpgp.generateKey(options);
- // return a;
- // // console.log('resolved a = ',a);
- // // this.privateKey =a.privateKeyArmored;
- // // this.publicKey = a.publicKeyArmored;
- // // this.encryptDecryptFunction();
- // }
- private async addValidators() {
- const triggerWords = await this.storage.get("keywords");
- const validators = [
- Validators.maxLength(140),
- this.containsTriggerWord(triggerWords)
- ];
- this.tweet.controls["text"].setValidators(validators);
- }
- private containsTriggerWord(triggerWords: string): ValidatorFn {
- return (control: AbstractControl): { [key: string]: any } | null => {
- if (triggerWords) {
- const regexList = triggerWords
- .toLowerCase()
- .split(", ")
- .join("|");
- const regex = new RegExp(regexList);
- const containsTriggerWord = regex.test(control.value.toLowerCase());
- return containsTriggerWord
- ? { containsTriggerWord: { value: control.value } }
- : null;
- } else {
- return null;
- }
- };
- }
- async ionViewDidLoad() {
- if (this.retweetId) {
- this.retweet = await this.twitter.fetchTweet(this.retweetId);
- }
- if (this.replyToStatusId) {
- this.replyTweet = await this.twitter.fetchTweet(this.replyToStatusId);
- }
- }
- get tweetCharProgress() {
- const progress = 1 - this.tweet.value["text"].length / 140;
- const radius = 8;
- const circumference = Math.PI * radius * 2;
- return progress * circumference;
- }
- get showTrigger(): boolean {
- return (
- this.tweet &&
- this.tweet.controls &&
- this.tweet.controls.text &&
- this.tweet.controls.text.errors &&
- this.tweet.controls.text.errors["containsTriggerWord"] &&
- !this.tweet.controls.p2p.value
- );
- }
- showTriggerInfo() {
- this.alertCtrl
- .create({
- title: "Watch Out!",
- message:
- "Your tweet contains words you have previously defined to only share securely via P2P. Currently P2P mode is not selected.",
- buttons: ["OK"]
- })
- .present();
- }
- async submitTweet() {
- console.log('Submitting tweet')
- const loading = this.loadingCtrl.create();
- loading.present();
- if (this.tweet.value.p2p) {
- loading.setContent("Validate keys...");
- if (
- (await this.cryptoUtils.isPrivateKeySet()) &&
- (await this.cryptoUtils.isPublicKeyPublished())
- ) {
- loading.setContent("Publish private tweet...");
- await this.tweetPrivate();
- } else {
- loading.dismiss();
- const alert = this.alertCtrl.create({
- title: "Oooops...",
- message:
- "Please verify that you have set a private and public key in the settings and that your latest public key was published."
- });
- alert.present();
- return;
- }
- } else {
- loading.setContent("Publish on Twitter...");
- await this.twitter.tweet(
- this.tweet.value["text"],
- this.retweet,
- this.replyToStatusId
- );
- }
- loading.dismiss();
- this.navCtrl.pop();
- }
- public async lookupKeys(email:string){
- var options = {
- query: email
- };
- let armoredPubkey = await this.hkp.lookup(options);
- console.log('armord pubkey',armoredPubkey);
- let pubkey = (await openpgp.key.readArmored(armoredPubkey));
- // console.log('array of opubkes returened from server',pubkey);
- pubkey = (await openpgp.key.readArmored(armoredPubkey)).keys[0];
- // console.log('latest pubkey is:',pubkey);
- // console.log('Found public key:',pubkey);
-
- this.pk.push(pubkey);
- }
- private async tweetPrivate() {
- const tweet = await this.buildPrivateTweet();
- console.log('tweet is:',tweet.full_text);
- const privateKey = await this.storage.get("privateKey");
- //fetch followers and their public keys
- //assuming the email id of rohit.shiva.gowda
- await this.lookupKeys('rohit.hosn@gmail.com');
- console.log('array of pub keys is :', this.pk);
- this.pk = this.pk.map(async (key) => {
- console.log('key is:',key);
- return (await openpgp.key.readArmored(key)).keys[0]
- });
- console.log("after mapping", this.pk);
- const options = {
- message: openpgp.message.fromText(tweet), // input as Message object
- publicKeys: await Promise.all(this.pk), // for encryption
- // privateKeys: [privKeyObj] // for signing (optional)
- }
- const ciphertext = await openpgp.encrypt(options);
- const encryptedTweet = ciphertext.data;
- console.log('encrypted tweet is:',encryptedTweet);
- // const encryptedTweet = this.cryptoUtils.encrypt(
- // JSON.stringify(tweet),
- // privateKey
- // );
- const res = await this.ipfs.storeTweet(encryptedTweet);
- this.gun.storeLastTweetHashForUser(
- tweet.user_id,
- res["Hash"],
- tweet.created_at
- );
- this.gun.publishHashtags(tweet.entities.hashtags);
- }
- private async buildPrivateTweet() {
- const status = this.tweet.value["text"].trim();
- const entities = await this.getEntities(status);
- return {
- full_text: status,
- user_id: await this.storage.get("userId"),
- created_at: Date.now(),
- private_tweet: true,
- in_reply_to_status_id: this.replyToStatusId,
- quoted_status_id: this.retweetId,
- display_text_range: [0, status.length],
- entities: entities
- };
- }
- private async getEntities(status: string) {
- return {
- hashtags: twittertext.extractHashtagsWithIndices(status),
- urls: twittertext.extractUrlsWithIndices(status),
- user_mentions: await this.getMentions(status)
- };
- }
- private async getMentions(status: string) {
- // extract mentions
- const entities = twittertext.extractMentionsWithIndices(status);
- // add user_id
- const entitiesWithPromises = entities.map(async mention => {
- try {
- const user = await this.twitter.fetchUserFromScreenName(
- mention.screenName
- );
- mention["id_str"] = user[0]["id_str"];
- mention["screen_name"] = mention.screenName;
- delete mention.screenName;
- } catch (err) {
- console.error(
- "There is no user signed up to twitter with username: " +
- mention.screenName
- );
- }
- return mention;
- });
- // filter for valid users and return
- return (await Promise.all(entitiesWithPromises)).filter(el =>
- el.hasOwnProperty("id_str")
- );
- }
- }
|