import Urbit from "@urbit/http-api" ; import { useStore } from "./store" ; import { EncryptedShipCredentials , PermissionRequest } from "./types" ; export async function fetchShipname ( url ) { return new Promise ( async ( resolve , reject ) => { try { const res = await fetch ( url . replace ( /\/$/g , '' ) + "/who.json" ) ; const json = await res . json ( ) ; resolve ( json . who ) ; } catch { reject ( "OTA outdated" ) ; } } ) ; } export async function scrapeShipname ( url ) { return new Promise ( async ( resolve , reject ) => { try { const res = await fetch ( url . replace ( /\/$/g , '' ) + "/~/login" ) ; const html = await res . text ( ) ; const parser = new DOMParser ( ) ; const doc = parser . parseFromString ( html , "text/html" ) ; const ship = doc . querySelector ( 'input' ) . value . replace ( "~" , "" ) ; resolve ( ship ) ; } catch { reject ( "OTA outdated" ) ; } } ) ; } export async function connectToShip ( url , ship ) { const { connectShip , activeSubscriptions } = useStore . getState ( ) ; const airlock = new Urbit ( url , "" ) ; airlock . ship = ship . shipName ; airlock . onError = async ( err ) => { airlock . reset ( ) ; console . log ( err , "error" ) ; await connectShip ( url , ship ) ; } ; airlock . onRetry = ( ) => console . log ( "" ) ; airlock . onOpen = ( ) => console . log ( "" ) ; await airlock . poke ( { app : 'hood' , mark : 'helm-hi' , json : 'opening airlock' } ) ; for ( let sub of activeSubscriptions ) await airlock . subscribe ( sub . subscription ) ; return airlock ; } export async function loginToShip ( url , code ) { const controller = new AbortController ( ) ; setTimeout ( ( ) => { controller . abort ( ) ; } , 5000 ) ; const res = await fetch ( url . replace ( /\/$/g , '' ) + "/~/login" , { body : `password=${ code }` , method : "POST" , credentials : "include" , redirect : "follow" , signal : controller . signal } ) ; return res ; } export async function savePermission ( permission ) { } export async function initPerms ( shipName , url ) { const airlock = new Urbit ( url , "" ) ; airlock . ship = shipName ; try { const res = await fetchAllPerms ( url ) ; return "exist" ; } catch { return setPerms ( airlock ) ; } } export async function setPerms ( airlock ) { const json = { "put-bucket" : { "desk" : "landscape" , "bucket-key" : "urbit-visor-permissions" , "bucket" : { } , } } ; return await airlock . poke ( { app : "settings-store" , mark : "settings-event" , json : json } ) ; } export interface NewPermissionRequest { key : string ; name ? : string ; permissions : string [ ] ; existing ? : string [ ] ; } export async function grantPerms ( airlock , perms ) { let value ; const existing = await checkPerms ( airlock . url , perms . key ) ; const set = new Set ( existing ) ; if ( existing ) { for ( let p of perms . permissions ) set . add ( p ) ; value = Array . from ( set ) ; } else { value = perms . permissions ; if ( perms . name ) value . push ( JSON . stringify ( { extName : perms . name } ) ) ; } const json = { "put-entry" : { "desk" : "landscape" , "bucket-key" : "urbit-visor-permissions" , "entry-key" : perms . key , "value" : value } } ; return await airlock . poke ( { app : "settings-store" , mark : "settings-event" , json : json } ) ; } export async function revokePerms ( url , shipName , perms ) { const airlock = new Urbit ( url , "" ) ; airlock . ship = shipName ; let value ; const existing = await checkPerms ( url , perms . key ) ; const set = new Set ( existing ) ; if ( existing ) { for ( let p of perms . permissions ) set . delete ( p ) ; value = Array . from ( set ) ; } else value = perms . permissions ; const json = { "put-entry" : { "desk" : "landscape" , "bucket-key" : "urbit-visor-permissions" , "entry-key" : perms . key , "value" : value } } ; const poke = await airlock . poke ( { app : "settings-store" , mark : "settings-event" , json : json } ) ; airlock . reset ( ) ; return poke ; } export async function deleteDomain ( url , ship , domain ) { const airlock = new Urbit ( url , "" ) ; airlock . ship = ship ; const json = { "del-entry" : { "desk" : "landscape" , "bucket-key" : "urbit-visor-permissions" , "entry-key" : domain , } } ; return await airlock . poke ( { app : "settings-store" , mark : "settings-event" , json : json } ) ; } export async function checkPerms ( url , domain ) { const perms = await fetchAllPerms ( url ) ; const domainPerms = perms . bucket [ domain ] ; return await domainPerms ; } export async function fetchAllPerms ( url ) { const airlock = new Urbit ( url , "" ) ; const payload = { app : "settings-store" , path : "/bucket/landscape/urbit-visor-permissions" } ; const res = await airlock . scry ( payload ) ; airlock . reset ( ) ; return res ; } export async function wipeAllPerms ( ship , url ) { const airlock = new Urbit ( url , "" ) ; airlock . ship = ship ; const json = { "del-bucket" : { "desk" : "landscape" , "bucket-key" : "urbit-visor-permissions" , } } ; return await airlock . poke ( { app : "settings-store" , mark : "settings-event" , json : json } ) ; } ; export async function openChannel ( airlock ) { await airlock . poke ( { app : 'hood' , mark : 'helm-hi' , json : 'opening airlock' } ) ; } ;