mirror of
https://github.com/believethehype/nostrdvm.git
synced 2025-11-19 23:46:27 +01:00
noogle: add imagegeneration
This commit is contained in:
28
tests/gui/vuejs/noogle/src/components/Image.vue
Normal file
28
tests/gui/vuejs/noogle/src/components/Image.vue
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<script>
|
||||||
|
import ImageGeneration from "@/components/ImageGeneration.vue";
|
||||||
|
import ResultsTable from "@/components/ImageResultTable.vue";
|
||||||
|
import Nip07 from "@/components/Nip07.vue";
|
||||||
|
import Donate from "@/components/Donate.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Home",
|
||||||
|
components: {Donate, Nip07, ResultsTable, ImageGeneration}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="center">
|
||||||
|
<br>
|
||||||
|
<ImageGeneration/>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
344
tests/gui/vuejs/noogle/src/components/ImageGeneration.vue
Normal file
344
tests/gui/vuejs/noogle/src/components/ImageGeneration.vue
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
<script setup>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import {
|
||||||
|
Client,
|
||||||
|
Filter,
|
||||||
|
Timestamp,
|
||||||
|
Event,
|
||||||
|
Metadata,
|
||||||
|
PublicKey,
|
||||||
|
EventBuilder,
|
||||||
|
Tag,
|
||||||
|
EventId,
|
||||||
|
Nip19Event, Alphabet
|
||||||
|
} from "@rust-nostr/nostr-sdk";
|
||||||
|
import store from '../store';
|
||||||
|
import miniToastr from "mini-toastr";
|
||||||
|
import VueNotifications from "vue-notifications";
|
||||||
|
import searchdvms from './data/searchdvms.json'
|
||||||
|
import {computed, watch} from "vue";
|
||||||
|
import countries from "@/components/data/countries.json";
|
||||||
|
import deadnip89s from "@/components/data/deadnip89s.json";
|
||||||
|
import {data} from "autoprefixer";
|
||||||
|
import {requestProvider} from "webln";
|
||||||
|
|
||||||
|
let dvms =[]
|
||||||
|
let searching = false
|
||||||
|
|
||||||
|
let listener = false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function generate_image(message) {
|
||||||
|
try {
|
||||||
|
if (message === undefined){
|
||||||
|
message = "A purple Ostrich"
|
||||||
|
}
|
||||||
|
|
||||||
|
if(store.state.pubkey === undefined){
|
||||||
|
miniToastr.showMessage("Please login first", "No pubkey set", VueNotifications.types.warn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dvms = []
|
||||||
|
store.commit('set_imagedvm_results', dvms)
|
||||||
|
let client = store.state.client
|
||||||
|
let tags = []
|
||||||
|
console.log(message)
|
||||||
|
tags.push(Tag.parse(["i", message, "text"]))
|
||||||
|
|
||||||
|
let evt = new EventBuilder(5100, "NIP 90 Image Generation request", tags)
|
||||||
|
let res = await client.sendEventBuilder(evt)
|
||||||
|
miniToastr.showMessage("Sent Request to DVMs", "Awaiting results", VueNotifications.types.warn)
|
||||||
|
searching = true
|
||||||
|
if (!store.state.imagehasEventListener){
|
||||||
|
listen()
|
||||||
|
store.commit('set_imagehasEventListener', true)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
console.log("Already has event listener")
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(res)
|
||||||
|
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function listen() {
|
||||||
|
listener = true
|
||||||
|
let client = store.state.client
|
||||||
|
let pubkey = store.state.pubkey
|
||||||
|
|
||||||
|
const filter = new Filter().kinds([7000, 6100]).pubkey(pubkey).since(Timestamp.now());
|
||||||
|
await client.subscribe([filter]);
|
||||||
|
|
||||||
|
const handle = {
|
||||||
|
// Handle event
|
||||||
|
handleEvent: async (relayUrl, event) => {
|
||||||
|
if (store.state.imagehasEventListener === false){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
//const dvmname = getNamefromId(event.author.toHex())
|
||||||
|
console.log("Received new event from", relayUrl);
|
||||||
|
if (event.kind === 7000) {
|
||||||
|
try {
|
||||||
|
console.log("7000: ", event.content);
|
||||||
|
console.log("DVM: " + event.author.toHex())
|
||||||
|
searching = false
|
||||||
|
//miniToastr.showMessage("DVM: " + dvmname, event.content, VueNotifications.types.info)
|
||||||
|
|
||||||
|
let status = "unknown"
|
||||||
|
let jsonentry = {id: event.author.toHex(), kind: "", status: status, result: "", name: event.author.toBech32(), about: "", image: "", amount: 0, bolt11: ""}
|
||||||
|
|
||||||
|
for (const tag in event.tags){
|
||||||
|
if (event.tags[tag].asVec()[0] === "status"){
|
||||||
|
status = event.tags[tag].asVec()[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.tags[tag].asVec()[0] === "amount"){
|
||||||
|
jsonentry.amount = event.tags[tag].asVec()[1]
|
||||||
|
if (event.tags[tag].asVec().length > 2){
|
||||||
|
jsonentry.bolt11 = event.tags[tag].asVec()[2]
|
||||||
|
}
|
||||||
|
// TODO else request invoice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//let dvm = store.state.nip89dvms.find(x => JSON.parse(x.event).pubkey === event.author.toHex())
|
||||||
|
for (const el of store.state.nip89dvms) {
|
||||||
|
if (JSON.parse(el.event).pubkey === event.author.toHex().toString()) {
|
||||||
|
jsonentry.name = el.name
|
||||||
|
jsonentry.about = el.about
|
||||||
|
jsonentry.image = el.image
|
||||||
|
|
||||||
|
console.log(jsonentry)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dvms.filter(i => i.id === jsonentry.id ).length === 0){
|
||||||
|
dvms.push(jsonentry)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dvms.find(i => i.id === jsonentry.id).status = status
|
||||||
|
|
||||||
|
store.commit('set_imagedvm_results', dvms)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error: ", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(event.kind === 6100) {
|
||||||
|
let entries = []
|
||||||
|
console.log("6100:", event.content);
|
||||||
|
|
||||||
|
//miniToastr.showMessage("DVM: " + dvmname, "Received Results", VueNotifications.types.success)
|
||||||
|
dvms.find(i => i.id === event.author.toHex()).result = event.content
|
||||||
|
dvms.find(i => i.id === event.author.toHex()).status = "finished"
|
||||||
|
store.commit('set_imagedvm_results', dvms)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Handle relay message
|
||||||
|
handleMsg: async (relayUrl, message) => {
|
||||||
|
//console.log("Received message from", relayUrl, message.asJson());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
client.handleNotifications(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function nextInput(e) {
|
||||||
|
const next = e.currentTarget.nextElementSibling;
|
||||||
|
if (next) {
|
||||||
|
next.focus();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function zap(invoice) {
|
||||||
|
let webln;
|
||||||
|
|
||||||
|
this.dvmpaymentaddr = `https://chart.googleapis.com/chart?cht=qr&chl=${invoice}&chs=250x250&chld=M|0`;
|
||||||
|
this.dvminvoice = invoice
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
webln = await requestProvider();
|
||||||
|
} catch (err) {
|
||||||
|
await this.copyinvoice(invoice)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (webln) {
|
||||||
|
|
||||||
|
let response = await webln.sendPayment(invoice)
|
||||||
|
console.log(response)
|
||||||
|
for (const dvm of dvms){
|
||||||
|
console.log(dvm.bolt11 + " " + invoice)
|
||||||
|
}
|
||||||
|
|
||||||
|
dvms.find(i => i.bolt11 === invoice).status = "paid"
|
||||||
|
store.commit('set_imagedvm_results', dvms)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createBolt11Lud16(lud16, amount) {
|
||||||
|
let url;
|
||||||
|
if (lud16.includes('@')) { // LNaddress
|
||||||
|
const parts = lud16.split('@');
|
||||||
|
url = `https://${parts[1]}/.well-known/lnurlp/${parts[0]}`;
|
||||||
|
} else { // No lud16 set or format invalid
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(url);
|
||||||
|
const response = await fetch(url);
|
||||||
|
const ob = await response.json();
|
||||||
|
const callback = ob.callback;
|
||||||
|
const amountInSats = parseInt(amount) * 1000;
|
||||||
|
const callbackResponse = await fetch(`${callback}?amount=${amountInSats}`);
|
||||||
|
const obCallback = await callbackResponse.json();
|
||||||
|
return obCallback.pr;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log(`LUD16: ${e}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
msg: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<div class="greetings">
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<h1 class="text-7xl font-black tracking-wide">Noogle</h1>
|
||||||
|
<h1 class="text-7xl font-black tracking-wide">Image Generation</h1>
|
||||||
|
<h2 class="text-base-200-content text-center tracking-wide text-2xl font-thin">
|
||||||
|
Generate Images, the decentralized way</h2>
|
||||||
|
<h3>
|
||||||
|
<br>
|
||||||
|
<input class="c-Input" autofocus placeholder="A purple Ostrich..." v-model="message" @keyup.enter="generate_image(message)" @keydown.enter="nextInput">
|
||||||
|
<button class="v-Button" @click="generate_image(message)">Generate Image</button>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="max-w-5xl relative space-y-3">
|
||||||
|
<div class="grid grid-cols-2 gap-6">
|
||||||
|
<div className="card w-70 bg-base-100 shadow-xl flex flex-col" v-for="dvm in store.state.imagedvmreplies"
|
||||||
|
:key="dvm.id">
|
||||||
|
|
||||||
|
<figure class="w-full">
|
||||||
|
<img v-if="dvm.result" :src="dvm.result" height="200" alt="DVM Picture" />
|
||||||
|
<img v-if="!dvm.result" :src="dvm.image" height="200" alt="DVM Picture" />
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="card-body">
|
||||||
|
<h2 className="card-title">{{ dvm.name }}</h2>
|
||||||
|
<h3 >{{ dvm.about }}</h3>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div className="card-actions justify-end mt-auto" >
|
||||||
|
|
||||||
|
<div className="tooltip mt-auto" :data-tip="dvm.card ">
|
||||||
|
|
||||||
|
|
||||||
|
<button v-if="dvm.status === 'processing'" className="btn">Processing</button>
|
||||||
|
<button v-if="dvm.status === 'finished'" className="btn">Done</button>
|
||||||
|
<button v-if="dvm.status === 'paid'" className="btn">Paid, waiting for DVM..</button>
|
||||||
|
<button v-if="dvm.status === 'error'" className="btn">Error</button>
|
||||||
|
<button v-if="dvm.status === 'payment-required'" className="zap-Button" @click="zap(dvm.bolt11);">{{ dvm.amount/1000 }} Sats</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.zap-Button{
|
||||||
|
@apply btn hover:bg-amber-400;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-Button {
|
||||||
|
@apply bg-nostr hover:bg-nostr2 focus:ring-white mb-2 inline-flex flex-none items-center rounded-lg border border-black px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||||
|
height: 48px;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-Input {
|
||||||
|
@apply bg-black hover:bg-gray-900 focus:ring-white mb-2 inline-flex flex-none items-center rounded-lg border border-transparent px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||||
|
|
||||||
|
width: 350px;
|
||||||
|
height: 48px;
|
||||||
|
color: white;
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
display: flex;
|
||||||
|
width:100%;
|
||||||
|
height:125px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.0rem;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.greetings h1,
|
||||||
|
.greetings h3 {
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
|
||||||
|
.greetings h1,
|
||||||
|
.greetings h3 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
144
tests/gui/vuejs/noogle/src/components/ImageResultTable.vue
Normal file
144
tests/gui/vuejs/noogle/src/components/ImageResultTable.vue
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<template>
|
||||||
|
<EasyDataTable class="customize-table" header-text-direction="left" v-if="store.state.results.length != 0" table-class-name="customize-table"
|
||||||
|
:headers="headers"
|
||||||
|
:items="store.state.results" :sort-by="sortBy"
|
||||||
|
:sort-type="sortType">
|
||||||
|
<template #item-content="{ content, author, authorurl, avatar, indicator, links}">
|
||||||
|
<div class="playeauthor-wrapper">
|
||||||
|
|
||||||
|
<img class="avatar" v-if="avatar" :src="avatar" alt="Avatar" />
|
||||||
|
<img class="avatar" v-else src="@/assets/nostr-purple.svg" />
|
||||||
|
|
||||||
|
<a class="purple" :href="authorurl" target="_blank">{{ author }}</a>
|
||||||
|
<div class="time" :data-tip="indicator.time">
|
||||||
|
{{indicator.time.split("T")[1].split("Z")[0].trim()}}
|
||||||
|
{{indicator.time.split("T")[0].split("-")[2].trim()}}.{{indicator.time.split("T")[0].split("-")[1].trim()}}.{{indicator.time.split("T")[0].split("-")[0].trim().slice(2)}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>{{content.substr(0, 320) + "\u2026"}}</p>
|
||||||
|
<div style="padding: 2px; text-align: left;" >
|
||||||
|
<a class="menusmall" :href="links.uri" target="_blank">Nostr Client</a>
|
||||||
|
<a class="menusmall" :href="links.njump" target="_blank">NJump</a>
|
||||||
|
<a class="menusmall" :href="links.highlighter" target="_blank">Highlighter</a>
|
||||||
|
<!-- <a class="menusmall":href="links.nostrudel" target="_blank">Nostrudel</a> -->
|
||||||
|
</div>
|
||||||
|
<!-- <p>{{content}}</p> -->
|
||||||
|
</template>
|
||||||
|
<!--<template #expand="item">
|
||||||
|
<div style="padding: 15px; text-align: left;" >
|
||||||
|
<a class="menu" :href="item.links.uri" target="_blank">Nostr Client</a>
|
||||||
|
<a class="menu" :href="item.links.njump" target="_blank">NJump</a>
|
||||||
|
<a class="menu" :href="item.links.highlighter" target="_blank">Highlighter</a>
|
||||||
|
<a class="menu":href="item.links.nostrudel" target="_blank">Nostrudel</a>
|
||||||
|
</div>
|
||||||
|
</template> -->
|
||||||
|
|
||||||
|
|
||||||
|
</EasyDataTable>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
|
||||||
|
import type {Header, Item, SortType} from "vue3-easy-data-table";
|
||||||
|
import store from '../store';
|
||||||
|
|
||||||
|
const sortBy = "indicator.time";
|
||||||
|
const sortType: SortType = "desc";
|
||||||
|
|
||||||
|
const headers: Header[] = [
|
||||||
|
{ text: "Results:", value: "content", fixed:true},
|
||||||
|
// { text: "Time", value: "indicator.time", sortable: true, },
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.operation-wrapper .operation-icon {
|
||||||
|
width: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.playeauthor-wrapper {
|
||||||
|
padding: 6px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menusmall {
|
||||||
|
@apply btn text-gray-600 bg-transparent border-transparent tracking-wide;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.vue3-easy-data-table__footer.previous-page__click-button{
|
||||||
|
height:100px
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
padding: 6px;
|
||||||
|
display: flex;
|
||||||
|
font-size: 1em;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
.avatar {
|
||||||
|
margin-right: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
box-shadow: inset 0 4px 4px 0 rgb(0 0 0 / 10%);
|
||||||
|
}
|
||||||
|
.customize-table {
|
||||||
|
|
||||||
|
--easy-table-border: 1px solid #000000;
|
||||||
|
--easy-table-row-border: 1px solid #000000;
|
||||||
|
|
||||||
|
--easy-table-header-font-size: 14px;
|
||||||
|
--easy-table-header-height: 50px;
|
||||||
|
--easy-table-header-font-color: #c1cad4;
|
||||||
|
--easy-table-header-background-color: #242424;
|
||||||
|
|
||||||
|
--easy-table-header-item-padding: 10px 15px;
|
||||||
|
|
||||||
|
--easy-table-body-even-row-font-color: #fff;
|
||||||
|
--easy-table-body-even-row-background-color: #242424;
|
||||||
|
|
||||||
|
--easy-table-body-row-font-color: #c0c7d2;
|
||||||
|
--easy-table-body-row-background-color: #242424;
|
||||||
|
--easy-table-body-row-height: 50px;
|
||||||
|
--easy-table-body-row-font-size: 14px;
|
||||||
|
|
||||||
|
--easy-table-body-row-hover-font-color: #FFFFFF;
|
||||||
|
--easy-table-body-row-hover-background-color: #242424;
|
||||||
|
|
||||||
|
--easy-table-body-item-padding: 10px 15px;
|
||||||
|
|
||||||
|
--easy-table-footer-background-color: #242424;
|
||||||
|
--easy-table-footer-font-color: #c0c7d2;
|
||||||
|
--easy-table-footer-font-size: 14px;
|
||||||
|
--easy-table-footer-padding: 0px 10px;
|
||||||
|
--easy-table-footer-height: 50px;
|
||||||
|
|
||||||
|
--easy-table-rows-per-page-selector-width: 70px;
|
||||||
|
--easy-table-rows-per-page-selector-option-padding: 10px;
|
||||||
|
--easy-table-rows-per-page-selector-z-index: 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--easy-table-scrollbar-track-color: #2d3a4f;
|
||||||
|
--easy-table-scrollbar-color: #2d3a4f;
|
||||||
|
--easy-table-scrollbar-thumb-color: #4c5d7a;;
|
||||||
|
--easy-table-scrollbar-corner-color: #2d3a4f;
|
||||||
|
|
||||||
|
--easy-table-loading-mask-background-color: #2d3a4f;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Nip89></Nip89>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -29,12 +30,14 @@ import {
|
|||||||
Filter,
|
Filter,
|
||||||
initLogger,
|
initLogger,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
Timestamp, Keys, NostrDatabase, ClientBuilder, ClientZapper
|
Timestamp, Keys, NostrDatabase, ClientBuilder, ClientZapper, Alphabet
|
||||||
} from "@rust-nostr/nostr-sdk";
|
} from "@rust-nostr/nostr-sdk";
|
||||||
import VueNotifications from "vue-notifications";
|
import VueNotifications from "vue-notifications";
|
||||||
import store from '../store';
|
import store from '../store';
|
||||||
|
import Nip89 from "@/components/Nip89.vue";
|
||||||
import miniToastr from "mini-toastr";
|
import miniToastr from "mini-toastr";
|
||||||
|
import deadnip89s from "@/components/data/deadnip89s.json";
|
||||||
|
let nip89dvms = []
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -53,6 +56,8 @@ export default {
|
|||||||
else {
|
else {
|
||||||
await this.sign_in_anon()
|
await this.sign_in_anon()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.getnip89s()
|
||||||
}
|
}
|
||||||
catch (error){
|
catch (error){
|
||||||
console.log(error);
|
console.log(error);
|
||||||
@@ -159,6 +164,66 @@ export default {
|
|||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async getnip89s(){
|
||||||
|
|
||||||
|
//let keys = Keys.generate()
|
||||||
|
let keys = Keys.fromSkStr("ece3c0aa759c3e895ecb3c13ab3813c0f98430c6d4bd22160b9c2219efc9cf0e")
|
||||||
|
|
||||||
|
let signer = ClientSigner.keys(keys) //TODO store keys
|
||||||
|
let client = new ClientBuilder().signer(signer).build()
|
||||||
|
//await client.addRelay("wss://nos.lol");
|
||||||
|
await client.addRelay("wss://relay.f7z.io")
|
||||||
|
await client.addRelay("wss://pablof7z.nostr1.com")
|
||||||
|
//await client.addRelay("wss://relay.nostr.net")
|
||||||
|
await client.addRelay("wss://relay.nostr.band");
|
||||||
|
//await client.addRelay("wss://nostr-pub.wellorder.net")
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
let dvmkinds = []
|
||||||
|
for (let i = 5000; i < 6000; i++) {
|
||||||
|
dvmkinds.push((i.toString()))
|
||||||
|
}
|
||||||
|
console.log(dvmkinds)
|
||||||
|
|
||||||
|
const filter = new Filter().kind(31990).customTag(Alphabet.K, dvmkinds)
|
||||||
|
//await client.reconcile(filter);
|
||||||
|
//const filterl = new Filter().kind(31990)
|
||||||
|
//let evts = await client.database.query([filterl])
|
||||||
|
let evts = await client.getEventsOf([filter], 3)
|
||||||
|
for (const entry of evts){
|
||||||
|
for (const tag in entry.tags){
|
||||||
|
if (entry.tags[tag].asVec()[0] === "k")
|
||||||
|
console.log(entry.id.toHex())
|
||||||
|
if(entry.tags[tag].asVec()[1] >= 5000 && entry.tags[tag].asVec()[1] <= 5999 && deadnip89s.filter(i => i.id === entry.id.toHex() ).length === 0) { // blocklist.indexOf(entry.id.toHex()) < 0){
|
||||||
|
|
||||||
|
console.log(entry.tags[tag].asVec()[1])
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
let jsonentry = JSON.parse(entry.content)
|
||||||
|
if (jsonentry.picture){
|
||||||
|
jsonentry.image = jsonentry.picture
|
||||||
|
}
|
||||||
|
jsonentry.event = entry.asJson()
|
||||||
|
jsonentry.kind = entry.tags[tag].asVec()[1]
|
||||||
|
nip89dvms.push(jsonentry);
|
||||||
|
}
|
||||||
|
catch (error){
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
store.commit('set_nip89dvms', nip89dvms)
|
||||||
|
|
||||||
|
return nip89dvms
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async get_user_info(pubkey){
|
async get_user_info(pubkey){
|
||||||
let client = store.state.client
|
let client = store.state.client
|
||||||
const profile_filter = new Filter().kind(0).author(pubkey).limit(1)
|
const profile_filter = new Filter().kind(0).author(pubkey).limit(1)
|
||||||
|
|||||||
@@ -1,42 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div class="max-w-5xl relative space-y-3">
|
|
||||||
<div v-if="store.state.nip89dvms.length === 0">
|
|
||||||
<p>Loading Nip89s.. </p>
|
|
||||||
<span className="loading loading-dots loading-lg" ></span>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-2 gap-6">
|
|
||||||
<div className="card w-70 bg-base-100 shadow-xl" v-for="dvm in store.state.nip89dvms"
|
|
||||||
:key="dvm.name">
|
|
||||||
<figure><img :src="dvm.image" alt="DVM Picture" /></figure>
|
|
||||||
<div className="card-body">
|
|
||||||
<h2 className="card-title">{{ dvm.name }}</h2>
|
|
||||||
<p> {{ dvm.about }}</p>
|
|
||||||
<p>Kind: {{ dvm.kind }}</p>
|
|
||||||
<div className="card-actions justify-end">
|
|
||||||
<div className="tooltip" :data-tip="dvm.event">
|
|
||||||
<button className="btn" @click="copyDoiToClipboard(dvm.event);">Copy Event</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {
|
||||||
import '../app.css'
|
ClientSigner,
|
||||||
import store from "@/store.js";
|
Filter,
|
||||||
import {Alphabet, ClientBuilder, ClientSigner, Filter, Keys, NostrDatabase, Tag} from "@rust-nostr/nostr-sdk";
|
Keys, ClientBuilder, Alphabet
|
||||||
|
} from "@rust-nostr/nostr-sdk";
|
||||||
|
import store from '../store';
|
||||||
import miniToastr from "mini-toastr";
|
import miniToastr from "mini-toastr";
|
||||||
import VueNotifications from "vue-notifications";
|
import deadnip89s from "@/components/data/deadnip89s.json";
|
||||||
|
let nip89dvms = []
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
current_user: "",
|
||||||
|
avatar: "",
|
||||||
|
signer: "",
|
||||||
|
|
||||||
import deadnip89s from './data/deadnip89s.json'
|
};
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
try{
|
||||||
|
await this.getnip89s()
|
||||||
|
}
|
||||||
|
catch (error){
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
async function getnip89s(){
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async getnip89s(){
|
||||||
|
|
||||||
//let keys = Keys.generate()
|
//let keys = Keys.generate()
|
||||||
let keys = Keys.fromSkStr("ece3c0aa759c3e895ecb3c13ab3813c0f98430c6d4bd22160b9c2219efc9cf0e")
|
let keys = Keys.fromSkStr("ece3c0aa759c3e895ecb3c13ab3813c0f98430c6d4bd22160b9c2219efc9cf0e")
|
||||||
@@ -53,7 +48,7 @@ async function getnip89s(){
|
|||||||
|
|
||||||
let dvmkinds = []
|
let dvmkinds = []
|
||||||
for (let i = 5000; i < 6000; i++) {
|
for (let i = 5000; i < 6000; i++) {
|
||||||
dvmkinds.push(i.toString())
|
dvmkinds.push((i.toString()))
|
||||||
}
|
}
|
||||||
console.log(dvmkinds)
|
console.log(dvmkinds)
|
||||||
|
|
||||||
@@ -65,13 +60,9 @@ async function getnip89s(){
|
|||||||
for (const entry of evts){
|
for (const entry of evts){
|
||||||
for (const tag in entry.tags){
|
for (const tag in entry.tags){
|
||||||
if (entry.tags[tag].asVec()[0] === "k")
|
if (entry.tags[tag].asVec()[0] === "k")
|
||||||
console.log(entry.id.toHex())
|
|
||||||
if(entry.tags[tag].asVec()[1] >= 5000 && entry.tags[tag].asVec()[1] <= 5999 && deadnip89s.filter(i => i.id === entry.id.toHex() ).length === 0) { // blocklist.indexOf(entry.id.toHex()) < 0){
|
if(entry.tags[tag].asVec()[1] >= 5000 && entry.tags[tag].asVec()[1] <= 5999 && deadnip89s.filter(i => i.id === entry.id.toHex() ).length === 0) { // blocklist.indexOf(entry.id.toHex()) < 0){
|
||||||
|
|
||||||
console.log(entry.tags[tag].asVec()[1])
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
let jsonentry = JSON.parse(entry.content)
|
let jsonentry = JSON.parse(entry.content)
|
||||||
if (jsonentry.picture){
|
if (jsonentry.picture){
|
||||||
jsonentry.image = jsonentry.picture
|
jsonentry.image = jsonentry.picture
|
||||||
@@ -92,31 +83,12 @@ async function getnip89s(){
|
|||||||
return nip89dvms
|
return nip89dvms
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
let nip89dvms = []
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
|
||||||
computed: {
|
|
||||||
store() {
|
|
||||||
return store
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
copyDoiToClipboard (doi) {
|
|
||||||
navigator.clipboard.writeText(doi)
|
|
||||||
miniToastr.showMessage("", "Copied Nip89 Event to clipboard", VueNotifications.types.info)
|
|
||||||
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
async mounted(){
|
|
||||||
await getnip89s()
|
|
||||||
},
|
},
|
||||||
|
};
|
||||||
setup() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
66
tests/gui/vuejs/noogle/src/components/Nip89view.vue
Normal file
66
tests/gui/vuejs/noogle/src/components/Nip89view.vue
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<div class="max-w-5xl relative space-y-3">
|
||||||
|
<div v-if="store.state.nip89dvms.length === 0">
|
||||||
|
<p>Loading Nip89s.. </p>
|
||||||
|
<span className="loading loading-dots loading-lg" ></span>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-2 gap-6">
|
||||||
|
<div className="card w-70 bg-base-100 shadow-xl" v-for="dvm in store.state.nip89dvms"
|
||||||
|
:key="dvm.name">
|
||||||
|
<figure><img :src="dvm.image" alt="DVM Picture" /></figure>
|
||||||
|
<div className="card-body">
|
||||||
|
<h2 className="card-title">{{ dvm.name }}</h2>
|
||||||
|
<p> {{ dvm.about }}</p>
|
||||||
|
<p>Kind: {{ dvm.kind }}</p>
|
||||||
|
<div className="card-actions justify-end">
|
||||||
|
<div className="tooltip" :data-tip="dvm.event">
|
||||||
|
<button className="btn" @click="copyDoiToClipboard(dvm.event);">Copy Event</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import '../app.css'
|
||||||
|
import store from "@/store.js";
|
||||||
|
import {Alphabet, ClientBuilder, ClientSigner, Filter, Keys, NostrDatabase, Tag} from "@rust-nostr/nostr-sdk";
|
||||||
|
import miniToastr from "mini-toastr";
|
||||||
|
import VueNotifications from "vue-notifications";
|
||||||
|
|
||||||
|
import deadnip89s from './data/deadnip89s.json'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
store() {
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
copyDoiToClipboard (doi) {
|
||||||
|
navigator.clipboard.writeText(doi)
|
||||||
|
miniToastr.showMessage("", "Copied Nip89 Event to clipboard", VueNotifications.types.info)
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
async mounted(){
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -37,7 +37,7 @@ async function send_search_request(message) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
items = []
|
items = []
|
||||||
store.state.results = []
|
store.commit('set_search_results', items)
|
||||||
let client = store.state.client
|
let client = store.state.client
|
||||||
let tags = []
|
let tags = []
|
||||||
let users = [];
|
let users = [];
|
||||||
|
|||||||
@@ -5,7 +5,10 @@
|
|||||||
:sort-type="sortType">
|
:sort-type="sortType">
|
||||||
<template #item-content="{ content, author, authorurl, avatar, indicator, links}">
|
<template #item-content="{ content, author, authorurl, avatar, indicator, links}">
|
||||||
<div class="playeauthor-wrapper">
|
<div class="playeauthor-wrapper">
|
||||||
<img class="avatar" :src="avatar" alt="" />
|
|
||||||
|
<img class="avatar" v-if="avatar" :src="avatar" alt="Avatar" />
|
||||||
|
<img class="avatar" v-else src="@/assets/nostr-purple.svg" />
|
||||||
|
|
||||||
<a class="purple" :href="authorurl" target="_blank">{{ author }}</a>
|
<a class="purple" :href="authorurl" target="_blank">{{ author }}</a>
|
||||||
<div class="time" :data-tip="indicator.time">
|
<div class="time" :data-tip="indicator.time">
|
||||||
{{indicator.time.split("T")[1].split("Z")[0].trim()}}
|
{{indicator.time.split("T")[1].split("Z")[0].trim()}}
|
||||||
|
|||||||
43
tests/gui/vuejs/noogle/src/components/modaltest.vue
Normal file
43
tests/gui/vuejs/noogle/src/components/modaltest.vue
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<script>
|
||||||
|
import store from "@/store.js";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "modaltest",
|
||||||
|
computed: {
|
||||||
|
store() {
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
users: [],
|
||||||
|
isModalVisible: false,
|
||||||
|
userModal: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
openModal(user) {
|
||||||
|
this.userModal = user;
|
||||||
|
this.isModalVisible = true;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-for="user in store.state.nip89dvms" :key="user.id">
|
||||||
|
<button @click="openModal(user)">open modal</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Modal v-show="isModalVisible" @close="closeModal">
|
||||||
|
<p>TEST</p>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -12,6 +12,7 @@ import {isVisible} from "bootstrap/js/src/util/index.js";
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<router-link class="menu" to="/">Noogle</router-link>
|
<router-link class="menu" to="/">Noogle</router-link>
|
||||||
|
<router-link class="menu" to="/image">Image Generation</router-link>
|
||||||
<router-link class="menu" to="/about">About</router-link>
|
<router-link class="menu" to="/about">About</router-link>
|
||||||
<router-link class="menu" to="/nip89">DVMs</router-link>
|
<router-link class="menu" to="/nip89">DVMs</router-link>
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import { createWebHistory, createRouter } from "vue-router";
|
|||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{ path: "/", component: () => import("@/components/Home.vue") },
|
{ path: "/", component: () => import("@/components/Home.vue") },
|
||||||
{ path: "/about", component: () => import("@/components/AboutPage.vue") },
|
{ path: "/about", component: () => import("@/components/modaltest.vue") },
|
||||||
{ path: "/donate", component: () => import("@/components/Donate.vue") },
|
{ path: "/donate", component: () => import("@/components/Donate.vue") },
|
||||||
{ path: "/nip89", component: () => import("@/components/Nip89.vue") },
|
{ path: "/nip89", component: () => import("@/components/Nip89view.vue") },
|
||||||
|
{ path: "/image", component: () => import("@/components/Image.vue") },
|
||||||
{ path: "/article/:id", component: () => import("@/components/Home.vue") },
|
{ path: "/article/:id", component: () => import("@/components/Home.vue") },
|
||||||
{ path: '/:pathMatch(.*)*', component: () => import("@/components/Home.vue") },
|
{ path: '/:pathMatch(.*)*', component: () => import("@/components/Home.vue") },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ const store = createStore({
|
|||||||
client: Client,
|
client: Client,
|
||||||
pubkey: PublicKey,
|
pubkey: PublicKey,
|
||||||
hasEventListener: false,
|
hasEventListener: false,
|
||||||
|
imagehasEventListener: false,
|
||||||
|
imagedvmreplies: [],
|
||||||
nip89dvms: [],
|
nip89dvms: [],
|
||||||
results: [],
|
results: [],
|
||||||
relays: ["wss://relay.damus.io", "wss://nos.lol", "wss://relay.f7z.io", "wss://pablof7z.nostr1.com", "wss://relay.nostr.net", "wss://relay.nostr.net", "wss://relay.nostr.band", "wss://nostr-pub.wellorder.net"],
|
relays: ["wss://relay.damus.io", "wss://nos.lol", "wss://relay.f7z.io", "wss://pablof7z.nostr1.com", "wss://relay.nostr.net", "wss://relay.nostr.net", "wss://relay.nostr.band", "wss://nostr-pub.wellorder.net"],
|
||||||
@@ -27,12 +29,20 @@ const store = createStore({
|
|||||||
set_hasEventListener(state, hasEventListener) {
|
set_hasEventListener(state, hasEventListener) {
|
||||||
state.hasEventListener = hasEventListener
|
state.hasEventListener = hasEventListener
|
||||||
},
|
},
|
||||||
|
set_imagehasEventListener(state, imagehasEventListener) {
|
||||||
|
state.imagehasEventListener = imagehasEventListener
|
||||||
|
},
|
||||||
set_nip89dvms(state, nip89dvms) {
|
set_nip89dvms(state, nip89dvms) {
|
||||||
state.nip89dvms = nip89dvms
|
state.nip89dvms.length = 0
|
||||||
|
state.nip89dvms.push.apply(state.nip89dvms, nip89dvms)
|
||||||
},
|
},
|
||||||
set_search_results(state, results){
|
set_search_results(state, results){
|
||||||
state.results.length = 0
|
state.results.length = 0
|
||||||
state.results.push.apply(state.results, results)
|
state.results.push.apply(state.results, results)
|
||||||
|
},
|
||||||
|
set_imagedvm_results(state, results){
|
||||||
|
state.imagedvmreplies.length = 0
|
||||||
|
state.imagedvmreplies.push.apply(state.imagedvmreplies, results)
|
||||||
//state.results = []
|
//state.results = []
|
||||||
|
|
||||||
//[].push.apply(state.results, results)
|
//[].push.apply(state.results, results)
|
||||||
|
|||||||
Reference in New Issue
Block a user