noogle: reformat code

This commit is contained in:
Believethehype
2024-11-04 08:16:44 +01:00
parent f7d62edf59
commit 61134622a6
44 changed files with 5974 additions and 5802 deletions

View File

@@ -1,14 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/favicon.ico" rel="icon">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<title>Nostr decentralized search and other stuff</title>
<meta name="theme-color" content="#ffffff">
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
<meta content="#ffffff" name="theme-color">
</head>
<body>
<div id="app"></div>
<script src="/src/main.js" type="module"></script>
</body>
</html>

View File

@@ -1,8 +1,13 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
"@/*": [
"./src/*"
]
}
},
"exclude": ["node_modules", "dist"]
"exclude": [
"node_modules",
"dist"
]
}

View File

@@ -12,14 +12,14 @@
},
"dependencies": {
"@getalby/sdk": "^3.4.0",
"@rust-nostr/nostr-sdk": "^0.14.0",
"@rust-nostr/nostr-sdk": "^0.14.1",
"@vuepic/vue-datepicker": "^7.4.1",
"@vueuse/core": "^10.7.2",
"bech32": "^2.0.0",
"bootstrap": "^5.3.2",
"daisyui": "^4.6.0",
"mini-toastr": "^0.8.1",
"nostr-login": "^1.6.6",
"nostr-login": "^1.6.7",
"nostr-tools": "^2.4.0",
"vue": "^3.4.15",
"vue-notifications": "^1.0.2",

View File

@@ -1,6 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@@ -1,11 +1,12 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<ShortName>Noogle</ShortName>
<Description>Search the Nostr</Description>
<Url type="text/html" method="get" template="https://noogle.lol?search={searchTerms}"/>
<Image height="16" width="16" type="image/vnd.microsoft.icon">
https://noogle.lol/favicon.ico
</Image>
<moz:SearchForm>http://my-site/search</moz:SearchForm>
<Url type="application/opensearchdescription+xml" rel="self" template="https://noogle.lol/opensearch.xml"/>
<OpenSearchDescription xmlns:moz="http://www.mozilla.org/2006/browser/search/"
xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Noogle</ShortName>
<Description>Search the Nostr</Description>
<Url type="text/html" method="get" template="https://noogle.lol?search={searchTerms}"/>
<Image height="16" width="16" type="image/vnd.microsoft.icon">
https://noogle.lol/favicon.ico
</Image>
<moz:SearchForm>http://my-site/search</moz:SearchForm>
<Url type="application/opensearchdescription+xml" rel="self" template="https://noogle.lol/opensearch.xml"/>
</OpenSearchDescription>

View File

@@ -1,22 +1,18 @@
<script setup>
import ThreeColumnLayout from "./layouts/ThreeColumnLayout.vue";
import ProfileResultsTable from "@/components/ProfileResultTable.vue";
import router from "@/router/index.js";
</script>
<template>
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="Noogle Search" />
<link href="/opensearch.xml" rel="search" title="Noogle Search" type="application/opensearchdescription+xml"/>
<main>
<ThreeColumnLayout>
<template #aside>
<template #aside>
<ProfileResultsTable style="margin-top: 450px"/>
</template>
<ProfileResultsTable style="margin-top: 450px"/>
</template>
</ThreeColumnLayout>
@@ -30,7 +26,6 @@ header {
}
@media (min-width: 768px) {
header {
display: flex;

View File

@@ -3,43 +3,45 @@
@tailwind utilities;
:root {
color-scheme: light;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
color-scheme: light;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
:root {
color: #213547;
background-color: #ffffff;
}
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
padding: 3px;
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
padding: 3px;
}
.purple {
@apply text-nostr hover:text-orange-400;
text-decoration: none;
transition: 0.4s;
padding: 3px;
@apply text-nostr hover:text-orange-400;
text-decoration: none;
transition: 0.4s;
padding: 3px;
}
.white {
@apply text-white;
text-decoration: none;
transition: 0.4s;
padding: 3px;
@apply text-white;
text-decoration: none;
transition: 0.4s;
padding: 3px;
}
.menu {
color: white;
color: white;
@apply btn bg-transparent border-transparent tracking-wide;
}
}

View File

@@ -1,73 +1,71 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition:
color 0.5s,
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition: color 0.5s,
background-color 0.5s;
line-height: 1.6;
font-family:
Inter,
line-height: 1.6;
font-family: Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
@@ -79,8 +77,8 @@ body {
'Droid Sans',
'Helvetica Neue',
sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

View File

@@ -1,35 +1,35 @@
@import './base.css';
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
padding: 3px;
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
padding: 3px;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
}

View File

@@ -1,10 +1,12 @@
<svg width="225" height="224" viewBox="0 0 225 224" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="224.047" height="224" rx="64" fill="url(#paint0_radial_855_5166)"/>
<path d="M162.441 135.941V88.0593C170.359 85.1674 176 77.5348 176 68.6696C176 57.2919 166.708 48 155.33 48C143.953 48 134.661 57.2444 134.661 68.6696C134.661 77.5822 140.302 85.1674 148.219 88.0593V135.941C147.698 136.13 147.176 136.367 146.655 136.604L87.3956 77.3452C88.6282 74.6904 89.2919 71.7511 89.2919 68.6696C89.2919 57.2444 80.0474 48 68.6696 48C57.2919 48 48 57.2444 48 68.6696C48 77.5822 53.6415 85.1674 61.5585 88.0593V135.941C53.6415 138.833 48 146.465 48 155.33C48 166.708 57.2444 176 68.6696 176C80.0948 176 89.3393 166.708 89.3393 155.33C89.3393 146.418 83.6978 138.833 75.7807 135.941V88.0593C76.3022 87.8696 76.8237 87.6326 77.3452 87.3956L136.604 146.655C135.372 149.31 134.708 152.249 134.708 155.33C134.708 166.708 143.953 176 155.378 176C166.803 176 176.047 166.708 176.047 155.33C176.047 146.418 170.406 138.833 162.489 135.941H162.441Z" fill="white"/>
<defs>
<radialGradient id="paint0_radial_855_5166" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(224.047 224) rotate(-135.006) scale(316.817 473.813)">
<stop stop-color="#6951FA"/>
<stop offset="1" stop-color="#9151FA"/>
</radialGradient>
</defs>
<rect width="224.047" height="224" rx="64" fill="url(#paint0_radial_855_5166)"/>
<path d="M162.441 135.941V88.0593C170.359 85.1674 176 77.5348 176 68.6696C176 57.2919 166.708 48 155.33 48C143.953 48 134.661 57.2444 134.661 68.6696C134.661 77.5822 140.302 85.1674 148.219 88.0593V135.941C147.698 136.13 147.176 136.367 146.655 136.604L87.3956 77.3452C88.6282 74.6904 89.2919 71.7511 89.2919 68.6696C89.2919 57.2444 80.0474 48 68.6696 48C57.2919 48 48 57.2444 48 68.6696C48 77.5822 53.6415 85.1674 61.5585 88.0593V135.941C53.6415 138.833 48 146.465 48 155.33C48 166.708 57.2444 176 68.6696 176C80.0948 176 89.3393 166.708 89.3393 155.33C89.3393 146.418 83.6978 138.833 75.7807 135.941V88.0593C76.3022 87.8696 76.8237 87.6326 77.3452 87.3956L136.604 146.655C135.372 149.31 134.708 152.249 134.708 155.33C134.708 166.708 143.953 176 155.378 176C166.803 176 176.047 166.708 176.047 155.33C176.047 146.418 170.406 138.833 162.489 135.941H162.441Z"
fill="white"/>
<defs>
<radialGradient id="paint0_radial_855_5166" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
gradientTransform="translate(224.047 224) rotate(-135.006) scale(316.817 473.813)">
<stop stop-color="#6951FA"/>
<stop offset="1" stop-color="#9151FA"/>
</radialGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,15 +1,15 @@
<template>
<div class="max-w-5xl mx-auto flex flex-col gap-8">
<div class="flex flex-row gap-6 items-center">
<Logo />
<div class="flex flex-col gap-2">
<h1 class="text-7xl font-black tracking-wide">About</h1>
<!-- <div class="text-lg text-nostr">
There are many things that make using and working with DVMs a bit of a magical experience.
</div> -->
</div>
<Logo/>
<div class="flex flex-col gap-2">
<h1 class="text-7xl font-black tracking-wide">About</h1>
<!-- <div class="text-lg text-nostr">
There are many things that make using and working with DVMs a bit of a magical experience.
</div> -->
</div>
</div>
<br><br>
<br><br>
<!-- <div class="grid grid-cols-2 gap-6">
<div class="card card-compact rounded-box bg-black">
<div class="card-body !text-base">
@@ -71,84 +71,97 @@
</div>
</div>
</div>-->
</div>
</div>
<div className="chat chat-start">
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component"
src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg"/>
</div>
</div>
<div className="chat-bubble">NIP 90 Data Vending Machines can perform multiple tasks leveraging the Nostr
Protocol.
</div>
</div>
<div className="chat-bubble">NIP 90 Data Vending Machines can perform multiple tasks leveraging the Nostr Protocol.</div>
</div>
<div className="chat chat-start">
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
<div className="chat chat-start">
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component"
src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg"/>
</div>
</div>
<div className="chat-bubble">This Demo Application uses a Kind 5302 event to ask DVMs to search for content on the
Nostr.
</div>
</div>
<div className="chat-bubble">This Demo Application uses a Kind 5302 event to ask DVMs to search for content on the Nostr.</div>
</div>
<div className="chat chat-start">
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component"
src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg"/>
</div>
</div>
<div className="chat-bubble">You can add from:npub.... to your search to filter content for a specific user.</div>
</div>
<div className="chat-bubble">You can add from:npub.... to your search to filter content for a specific user.</div>
</div>
<div className="chat chat-start">
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
</div>
</div>
<div className="chat-bubble">When you're logged in (via getalby or nos2x extension) you can add from:me to search content from yourself</div>
</div>
<div className="chat chat-start">
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component"
src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg"/>
</div>
</div>
<div className="chat-bubble">When you're logged in (via getalby or nos2x extension) you can add from:me to search
content from yourself
</div>
</div>
<div className="chat-bubble">This page then combines all the results from available search dvms.</div>
</div>
<div className="chat chat-start">
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
<div className="chat chat-start">
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component"
src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg"/>
</div>
</div>
<div className="chat-bubble">This page then combines all the results from available search dvms.</div>
</div>
<div className="chat chat-start">
<div className="chat-image avatar">
<div className="w-10 rounded-full">
<img alt="Tailwind CSS chat bubble component"
src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg"/>
</div>
</div>
<div className="chat-bubble">This way we will be able to decentralize the most centralized thing on the internet.
Search.
</div>
</div>
<div className="chat-bubble">This way we will be able to decentralize the most centralized thing on the internet. Search.</div>
</div>
</template>
<script>
<script>
export default {
name: 'dailyUIdemo',
name: 'dailyUIdemo',
}
</script>
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@@ -1,6 +1,5 @@
<script>
import ImageGeneration from "@/components/ChatGeneration.vue";
import Donate from "@/components/Donate.vue";
export default {
name: "Image",

File diff suppressed because it is too large Load Diff

View File

@@ -1,59 +1,58 @@
<script>
import { requestProvider } from "webln";
import {requestProvider} from "webln";
import miniToastr from "mini-toastr";
import VueNotifications from "vue-notifications";
import {PublicKey, ZapDetails, ZapEntity, ZapType} from "@rust-nostr/nostr-sdk";
import store from "@/store.js";
import {data} from "autoprefixer";
export default {
data() {
data() {
return {
dvmlnaddress: "hype@bitcoinfixesthis.org",
dvmpaymentaddr: "",
dvmlnaddress: "hype@bitcoinfixesthis.org",
dvmpaymentaddr: "",
dvminvoice: "",
nostrsdklnaddress: "yuki@getalby.com",
nostrsdkpaymentaddr: "",
nostrsdkinvoice: "",
amount: 1000
}},
methods: {
async handleZap(){
try {
let pk = PublicKey.fromBech32("npub1nxa4tywfz9nqp7z9zp7nr7d4nchhclsf58lcqt5y782rmf2hefjquaa6q8");
let entity = ZapEntity.publicKey(pk);
let details = new ZapDetails(ZapType.Private).message("Zap for Rust Nostr!");
await store.state.client.zap(entity, 1000, details);
} catch (error) {
console.log(error)
}
},
async copyinvoice(invoice){
await navigator.clipboard.writeText(invoice)
window.open("lightning:" + invoice,"_blank")
miniToastr.showMessage("", "Copied Invoice to clipboard", VueNotifications.types.info)
methods: {
async handleZap() {
try {
let pk = PublicKey.fromBech32("npub1nxa4tywfz9nqp7z9zp7nr7d4nchhclsf58lcqt5y782rmf2hefjquaa6q8");
let entity = ZapEntity.publicKey(pk);
let details = new ZapDetails(ZapType.Private).message("Zap for Rust Nostr!");
await store.state.client.zap(entity, 1000, details);
} catch (error) {
console.log(error)
}
},
async copyinvoice(invoice) {
await navigator.clipboard.writeText(invoice)
window.open("lightning:" + invoice, "_blank")
miniToastr.showMessage("", "Copied Invoice to clipboard", VueNotifications.types.info)
},
async zap(lnaddress, amount) {
let webln;
let invoice = await this.createBolt11Lud16(lnaddress, amount)
if (lnaddress === this.nostrsdklnaddress){
this.nostrsdkpaymentaddr = `https://chart.googleapis.com/chart?cht=qr&chl=${invoice}&chs=250x250&chld=M|0`;
this.nostrsdkinvoice = invoice
}
else{
this.dvmpaymentaddr = `https://chart.googleapis.com/chart?cht=qr&chl=${invoice}&chs=250x250&chld=M|0`;
if (lnaddress === this.nostrsdklnaddress) {
this.nostrsdkpaymentaddr = `https://chart.googleapis.com/chart?cht=qr&chl=${invoice}&chs=250x250&chld=M|0`;
this.nostrsdkinvoice = invoice
} else {
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)
await this.copyinvoice(invoice)
}
if (webln) {
@@ -64,15 +63,15 @@ export default {
},
async createBolt11Lud16(lud16, amount) {
let url;
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
} else { // No lud16 set or format invalid
return null;
}
}
try {
try {
console.log(url);
const response = await fetch(url);
const ob = await response.json();
@@ -81,10 +80,9 @@ export default {
const callbackResponse = await fetch(`${callback}?amount=${amountInSats}`);
const obCallback = await callbackResponse.json();
return obCallback.pr;
}
catch (e) {
console.log(`LUD16: ${e}`);
return null;
} catch (e) {
console.log(`LUD16: ${e}`);
return null;
}
}
}
@@ -94,21 +92,42 @@ export default {
<template>
<div className="dropdown dropdown-top">
<div tabIndex={0} role="button" class="v-Button"><svg class="relative w-5 h-5 mr-2 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>Donate</div>
<div tabIndex={0} className="dropdown-content z-[1] -start-20 card card-compact w-64 p-2 shadow bg-primary text-primary-content">
<div className="card-body">
<div>
<p>Sats:</p><input class="c-Input" v-model="amount" placeholder="1000">
</div>
<h3 className="card-title">Donate to Noogle</h3>
<button class="v-Button2" @click="zap(this.dvmlnaddress, amount)"><svg class="relative w-5 h-5 mr-2 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>Donate</button>
<img v-if="this.dvmpaymentaddr" alt="Invoice" width="250" :src=this.dvmpaymentaddr @click="this.copyinvoice(this.dvminvoice)" />
<h3 className="card-title">Donate to NostrSDK</h3>
<button class="v-Button2" @click="zap(this.nostrsdklnaddress, amount)"><svg class="relative w-5 h-5 mr-2 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>Donate</button>
<img v-if="this.nostrsdkpaymentaddr" alt="Invoice" width="250" :src=this.nostrsdkpaymentaddr @click="this.copyinvoice(this.nostrsdkinvoice)" />
<div class="v-Button" role="button" tabIndex={0}>
<svg class="relative w-5 h-5 mr-2 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path d="M13 10V3L4 14h7v7l9-11h-7z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
</svg>
Donate
</div>
<div className="dropdown-content z-[1] -start-20 card card-compact w-64 p-2 shadow bg-primary text-primary-content"
tabIndex={0}>
<div className="card-body">
<div>
<p>Sats:</p><input v-model="amount" class="c-Input" placeholder="1000">
</div>
<h3 className="card-title">Donate to Noogle</h3>
<button class="v-Button2" @click="zap(this.dvmlnaddress, amount)">
<svg class="relative w-5 h-5 mr-2 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path d="M13 10V3L4 14h7v7l9-11h-7z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
</svg>
Donate
</button>
<img v-if="this.dvmpaymentaddr" :src=this.dvmpaymentaddr alt="Invoice" width="250"
@click="this.copyinvoice(this.dvminvoice)"/>
<h3 className="card-title">Donate to NostrSDK</h3>
<button class="v-Button2" @click="zap(this.nostrsdklnaddress, amount)">
<svg class="relative w-5 h-5 mr-2 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path d="M13 10V3L4 14h7v7l9-11h-7z" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
</svg>
Donate
</button>
<img v-if="this.nostrsdkpaymentaddr" :src=this.nostrsdkpaymentaddr alt="Invoice" width="250"
@click="this.copyinvoice(this.nostrsdkinvoice)"/>
</div>
</div>
</div>
</template>
@@ -116,17 +135,18 @@ export default {
<style scoped>
.v-Button {
@apply tracking-wide bg-black hover:bg-amber-400 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;
height: 24px;
@apply tracking-wide bg-black hover:bg-amber-400 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;
height: 24px;
}
.v-Button2 {
@apply tracking-wide bg-black hover:bg-amber-400 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;
@apply tracking-wide bg-black hover:bg-amber-400 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;
}
.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;
color: white;
background: black;
@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;
color: white;
background: black;
}
</style>

File diff suppressed because one or more lines are too long

View File

@@ -24,7 +24,6 @@ export default {
</template>
<style scoped>
.center {

View File

@@ -1,6 +1,5 @@
<script>
import ImageGeneration from "@/components/ImageGeneration.vue";
import Donate from "@/components/Donate.vue";
export default {
name: "Image",

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,6 @@
<script setup>
import { ref } from "vue";
import {ref} from "vue";
import {onClickOutside} from '@vueuse/core'
import store from "@/store.js";
import {EventBuilder, PublicKey, Tag, Timestamp} from "@rust-nostr/nostr-sdk";
const props = defineProps({
isOpen: Boolean,
@@ -11,27 +9,26 @@ const props = defineProps({
const emit = defineEmits(["modal-close"]);
const target = ref(null)
onClickOutside(target, ()=>emit('modal-close'))
onClickOutside(target, () => emit('modal-close'))
</script>
<template>
<div v-if="isOpen" class="modal-mask" >
<div class="modal-wrapper" >
<div class="modal-container" ref="target">
<div v-if="isOpen" class="modal-mask">
<div class="modal-wrapper">
<div ref="target" class="modal-container">
<div class="modal-header">
<slot name="header"> default header </slot>
<slot name="header"> default header</slot>
</div>
<div class="modal-body">
<slot name="content"> default content </slot>
<slot name="content"> default content</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<div>
<button @click.stop="emit('modal-close')"></button>
<button @click.stop="schedule(Date.now())"></button>
<button @click.stop="schedule(Date.now())"></button>
</div>
</slot>
</div>
@@ -54,6 +51,7 @@ onClickOutside(target, ()=>emit('modal-close'))
background-color: rgba(0, 0, 0, 0.5);
}
.modal-container {
@apply bg-base-200;

View File

@@ -1,155 +1,168 @@
<template>
<div class="flex flex-row gap-6 items-center">
<Logo />
<div class="flex flex-col gap-2">
<h1 class="text-7xl font-black tracking-wide">About</h1>
<h2 class="text-4xl font-black tracking-wide">Nostr NIP 90 Data Vending Machines</h2>
<div class="text-lg text-default">
<!-- There are many things that make using DVMs a bit of a magical experience. -->
</div>
</div>
<div class="flex flex-row gap-6 items-center">
<Logo/>
<div class="flex flex-col gap-2">
<h1 class="text-7xl font-black tracking-wide">About</h1>
<h2 class="text-4xl font-black tracking-wide">Nostr NIP 90 Data Vending Machines</h2>
<div class="text-lg text-default">
<!-- There are many things that make using DVMs a bit of a magical experience. -->
</div>
</div>
<br><br>
</div>
<br><br>
<div class="card card-compact rounded-box bg-black/30">
<div class="card-body">
<div class="card-title text-base-100-content font-bold">
What is this?
</div>
<p>Data Vending Machines are data-processing tools on top of the Nostr protocol.
</p>
<p>
You give them some data, sometimes a few sats, and they give you back some data.</p>
<p>
This page is just a demo client, showcasing a variety of DVM use-cases. Search Content, Search Profiles, Content
Discovery, Summarization of events, Image Generation, Scheduling Notes.
</p>
<p>
There's an ever growing number of tasks added to the protocol. The current list of tasks can be found <a
class="purple" href="https://www.data-vending-machines.org/" target="_blank">here</a>.
</p>
<p>
These DVMs are not running or being hosted on this site. Instead, the DVMs communicate via Nostr and are
available to any App or Client that wants to interact with them.
Want your app or website to support any of these tasks? See <a class="purple" href="https://github.com/nostr-protocol/nips/blob/master/90.md"
target="_blank">NIP90</a>
for more details.
</p>
<p>
Got interested in building your own DVM and provide it to the whole world? There's OpenSource frameworks to
start with, for example <a class="purple" href="https://github.com/believethehype/nostrdvm" target="_blank">NostrDVM</a>
in Python.
</p>
<p>
A List of all DVMs that have a NIP89 announcement is available below, ordered by latest announcement.
</p>
</div>
</div>
<br><br>
<div class="grid gap-5">
<div v-for="dvm in store.state.nip89dvms" :key="dvm.id" className="card bg-base-200 shadow-xl"
style="height: 300px">
<!-- -->
<!-- <div class="card bg-base-100 shadow-xl image-full" style="height: 400px">
<figure><img v-if="dvm.image" :src="dvm.image" style=" width: 100%; object-fit: cover;"
:alt="dvm.name" onerror="this.src='https://noogle.lol/favicon.ico'"/></figure>
<div class="card-body">
<div style="margin-left: auto; margin-right: 10px;">
<p v-if="dvm.amount.toString().toLowerCase()==='free'" class="badge bg-nostr">Free</p>
<p v-if="dvm.amount.toString().toLowerCase()==='flexible'" class="badge bg-nostr2" >Flexible</p>
<p v-if="dvm.amount.toString().toLowerCase()==='subscription'" class="badge bg-orange-500">Subscription</p>
<p v-if="dvm.amount.toString()===''" ></p>
<p v-if="!isNaN(parseInt(dvm.amount))" class="text-sm text-gray-600 rounded" ><div class="flex"><svg style="margin-top:3px" xmlns="http://www.w3.org/2000/svg" width="14" height="16" fill="currentColor" class="bi bi-lightning" viewBox="0 0 16 20">
<path d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641zM6.374 1 4.168 8.5H7.5a.5.5 0 0 1 .478.647L6.78 13.04 11.478 7H8a.5.5 0 0 1-.474-.658L9.306 1z"/></svg> {{dvm.amount/1000}}</div></p>
</div>
<div class="">
<h2 class="card-title">{{ dvm.name }}</h2>
<h3 class="fa-cut text-gray" >Kind: {{ dvm.kind }}</h3>
<h3 class="fa-cut" v-html="StringUtil.parseHyperlinks(dvm.about)"></h3>
<div class="card card-compact rounded-box bg-black/30">
<div class="card-body">
<div class="card-title text-base-100-content font-bold">
What is this?
</div>
<p>Data Vending Machines are data-processing tools on top of the Nostr protocol.
</p>
<p>
You give them some data, sometimes a few sats, and they give you back some data.</p>
<p>
This page is just a demo client, showcasing a variety of DVM use-cases. Search Content, Search Profiles, Content Discovery, Summarization of events, Image Generation, Scheduling Notes.
</p>
<p>
There's an ever growing number of tasks added to the protocol. The current list of tasks can be found <a class="purple" target="_blank" href="https://www.data-vending-machines.org/">here</a>.
</p>
<p>
These DVMs are not running or being hosted on this site. Instead, the DVMs communicate via Nostr and are available to any App or Client that wants to interact with them.
Want your app or website to support any of these tasks? See <a class="purple" target="_blank" href="https://github.com/nostr-protocol/nips/blob/master/90.md">NIP90</a> for more details.
</p>
<p>
Got interested in building your own DVM and provide it to the whole world? There's OpenSource frameworks to start with, for example <a class="purple" target="_blank" href="https://github.com/believethehype/nostrdvm">NostrDVM</a> in Python.
</p>
<p>
A List of all DVMs that have a NIP89 announcement is available below, ordered by latest announcement.
</p>
</div>
</div>
<br><br>
<div class="grid gap-5">
<div className="card bg-base-200 shadow-xl" style="height: 300px" v-for="dvm in store.state.nip89dvms"
:key="dvm.id">
<!-- -->
<!-- <div class="card bg-base-100 shadow-xl image-full" style="height: 400px">
<figure><img v-if="dvm.image" :src="dvm.image" style=" width: 100%; object-fit: cover;"
:alt="dvm.name" onerror="this.src='https://noogle.lol/favicon.ico'"/></figure>
<div class="card-body">
<div style="margin-left: auto; margin-right: 10px;">
<p v-if="dvm.amount.toString().toLowerCase()==='free'" class="badge bg-nostr">Free</p>
<p v-if="dvm.amount.toString().toLowerCase()==='flexible'" class="badge bg-nostr2" >Flexible</p>
<p v-if="dvm.amount.toString().toLowerCase()==='subscription'" class="badge bg-orange-500">Subscription</p>
<p v-if="dvm.amount.toString()===''" ></p>
<p v-if="!isNaN(parseInt(dvm.amount))" class="text-sm text-gray-600 rounded" ><div class="flex"><svg style="margin-top:3px" xmlns="http://www.w3.org/2000/svg" width="14" height="16" fill="currentColor" class="bi bi-lightning" viewBox="0 0 16 20">
<path d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641zM6.374 1 4.168 8.5H7.5a.5.5 0 0 1 .478.647L6.78 13.04 11.478 7H8a.5.5 0 0 1-.474-.658L9.306 1z"/></svg> {{dvm.amount/1000}}</div></p>
</div>
<div class="">
<h2 class="card-title">{{ dvm.name }}</h2>
<h3 class="fa-cut text-gray" >Kind: {{ dvm.kind }}</h3>
<h3 class="fa-cut" v-html="StringUtil.parseHyperlinks(dvm.about)"></h3>
<div class="card-actions justify-end ">
<button className="btn " style="margin-bottom: 10px" @click="copyDoiToClipboard(dvm.event);">Copy Event Json</button>
</div>
<div class="card-actions justify-end ">
<button className="btn " style="margin-bottom: 10px" @click="copyDoiToClipboard(dvm.event);">Copy Event Json</button>
</div>
</div>
</div> -->
<div class="card card-side bg-black/20 shadow-xl" style="height: 300px">
<figure style="max-width: 20%; flex: fit-content; background-size: cover;" >
<img v-if="dvm.image" style=" width: 90%; object-fit: cover;" :src="dvm.image" :alt="dvm.name" onerror="this.src='https://noogle.lol/favicon.ico'"/>
</figure>
<div class="card-body">
<div style="margin-left: auto; margin-right: 10px;">
<p v-if="dvm.amount.toString().toLowerCase()==='free'" class="badge bg-nostr">Free</p>
<p v-if="dvm.amount.toString().toLowerCase()==='flexible'" class="badge bg-nostr2" >Flexible</p>
<p v-if="dvm.subscription" class="badge text-white bg-gradient-to-br from-pink-500 to-orange-400">Subscription</p>
<p v-if="dvm.amount.toString()===''" ></p>
<p v-if="!isNaN(parseInt(dvm.amount))" class="text-sm text-gray-600 rounded" ><div class="flex"><svg style="margin-top:3px" xmlns="http://www.w3.org/2000/svg" width="14" height="16" fill="currentColor" class="bi bi-lightning" viewBox="0 0 16 20">
<path d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641zM6.374 1 4.168 8.5H7.5a.5.5 0 0 1 .478.647L6.78 13.04 11.478 7H8a.5.5 0 0 1-.474-.658L9.306 1z"/></svg> {{dvm.amount/1000}}</div></p>
</div>
<h2 class="card-title">{{ dvm.name }}</h2>
<h3 class="text-gray" >Kind: {{ dvm.kind }}</h3>
<h4 v-if="dvm.about !== null" class="fa-cut" style="max-width: 200px" v-html="dvm.about"></h4>
<div class="card-actions justify-end">
<button className="btn" @click="copyDoiToClipboard(dvm.event);">Copy Event Json</button>
</div>
</div>
</div>
<!--
<h2 className="card-title justify-center">{{ dvm.name }}</h2>
<div className="card-body">
<div className="playeauthor-wrapper flex align-top">
<figure className="w-40">
<img className="avatar" :src="dvm.image" alt="DVM Picture" />
</figure>
</div>
</div> -->
<br>
<h3 class="fa-cut" >Kind: {{ dvm.kind }}</h3>
<div class="card card-side bg-black/20 shadow-xl" style="height: 300px">
<h3 class="fa-cut" v-html="StringUtil.parseHyperlinks(dvm.about)"></h3>
<div className="card-actions justify-end mt-auto" >
<div className="card-actions justify-end">
<figure style="max-width: 20%; flex: fit-content; background-size: cover;">
<img v-if="dvm.image" :alt="dvm.name" :src="dvm.image" onerror="this.src='https://noogle.lol/favicon.ico'"
style=" width: 90%; object-fit: cover;"/>
</figure>
<div class="card-body">
<div style="margin-left: auto; margin-right: 10px;">
<p v-if="dvm.amount.toString().toLowerCase()==='free'" class="badge bg-nostr">Free</p>
<p v-if="dvm.amount.toString().toLowerCase()==='flexible'" class="badge bg-nostr2">Flexible</p>
<p v-if="dvm.subscription" class="badge text-white bg-gradient-to-br from-pink-500 to-orange-400">
Subscription</p>
<button className="btn glass" @click="copyDoiToClipboard(dvm.event);">Copy Event Json</button>
</div>
<p v-if="dvm.amount.toString()===''"></p>
<p v-if="!isNaN(parseInt(dvm.amount))" class="text-sm text-gray-600 rounded">
<div class="flex">
<svg class="bi bi-lightning" fill="currentColor" height="16" style="margin-top:3px"
viewBox="0 0 16 20" width="14" xmlns="http://www.w3.org/2000/svg">
<path
d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641zM6.374 1 4.168 8.5H7.5a.5.5 0 0 1 .478.647L6.78 13.04 11.478 7H8a.5.5 0 0 1-.474-.658L9.306 1z"/>
</svg>
{{ dvm.amount / 1000 }}
</div>
</p>
</div>
</div>-->
<h2 class="card-title">{{ dvm.name }}</h2>
<h3 class="text-gray">Kind: {{ dvm.kind }}</h3>
<h4 v-if="dvm.about !== null" class="fa-cut" style="max-width: 200px" v-html="dvm.about"></h4>
<div class="card-actions justify-end">
<button className="btn" @click="copyDoiToClipboard(dvm.event);">Copy Event Json</button>
</div>
</div>
</div>
<!--
<h2 className="card-title justify-center">{{ dvm.name }}</h2>
<div className="card-body">
<div className="playeauthor-wrapper flex align-top">
<figure className="w-40">
<img className="avatar" :src="dvm.image" alt="DVM Picture" />
</figure>
</div>
<br>
<h3 class="fa-cut" >Kind: {{ dvm.kind }}</h3>
<h3 class="fa-cut" v-html="StringUtil.parseHyperlinks(dvm.about)"></h3>
<div className="card-actions justify-end mt-auto" >
<div className="card-actions justify-end">
<button className="btn glass" @click="copyDoiToClipboard(dvm.event);">Copy Event Json</button>
</div>
</div>
</div>-->
</div>
</div>
</div>
</template>
<script>
import '../app.css'
import store from "@/store.js";
import {Alphabet, ClientBuilder, NostrSigner, Filter, Keys, NostrDatabase, Tag} from "@rust-nostr/nostr-sdk";
import {Keys} from "@rust-nostr/nostr-sdk";
import miniToastr from "mini-toastr";
import VueNotifications from "vue-notifications";
import StringUtil from "@/components/helper/string.ts";
import Donate from "@/components/Donate.vue"
import deadnip89s from './data/deadnip89s.json'
export default {
computed: {
@@ -164,17 +177,17 @@ export default {
}
},
methods: {
copyDoiToClipboard (doi) {
navigator.clipboard.writeText(doi)
miniToastr.showMessage("", "Copied Nip89 Event to clipboard", VueNotifications.types.info)
},
},
async mounted(){
copyDoiToClipboard(doi) {
navigator.clipboard.writeText(doi)
miniToastr.showMessage("", "Copied Nip89 Event to clipboard", VueNotifications.types.info)
},
},
async mounted() {
},
setup() {
@@ -182,16 +195,16 @@ async mounted(){
}
</script>
<style scoped>
donate{
donate {
position: fixed;
bottom:0;
background: rgba(0, 0, 0, 0.5);;
grid-area: footer;
width: 100vw;
height: 32px;
position: fixed;
bottom: 0;
background: rgba(0, 0, 0, 0.5);;
grid-area: footer;
width: 100vw;
height: 32px;
z-index: 10;
text-align: center;
}
z-index: 10;
text-align: center;
}
</style>

View File

@@ -1,150 +1,179 @@
<template>
<EasyDataTable class="customize-table" header-text-direction="left" table-class-name="customize-table"
:headers="headers"
:items="data"
:sort-by="sortBy"
:sort-type="sortType">
<EasyDataTable :headers="headers" :items="data" :sort-by="sortBy"
:sort-type="sortType"
class="customize-table"
header-text-direction="left"
table-class-name="customize-table">
<!--<template #expand="item">
<div style="padding: 15px">
<input class="c-Input" v-model="message">
<button class="v-Button" v-if="!item.replied" @click="reply(item.id, item.author, message)">Reply</button>
<button class="btn" v-if="item.replied" >Replied</button>
</div>
</template> -->
<template #item-content="{content, author, authorurl, avatar, indicator, links, lud16, id, authorid, zapped, zapAmount, reacted, reactions, boosts, boosted, event, replied}">
<!--<template #expand="item">
<div style="padding: 15px">
<input class="c-Input" v-model="message">
<button class="v-Button" v-if="!item.replied" @click="reply(item.id, item.author, message)">Reply</button>
<button class="btn" v-if="item.replied" >Replied</button>
</div>
</template> -->
<template
#item-content="{content, author, authorurl, avatar, indicator, links, lud16, id, authorid, zapped, zapAmount, reacted, reactions, boosts, boosted, event, replied}">
<div class="playeauthor-wrapper">
<div class="playeauthor-wrapper">
<img class="avatar" v-if="avatar" :src="avatar" alt="Avatar" onerror="this.src='https://noogle.lol/favicon.ico'" />
<img class="avatar" v-else src="@/assets/nostr-purple.svg" />
<img v-if="avatar" :src="avatar" alt="Avatar" class="avatar"
onerror="this.src='https://noogle.lol/favicon.ico'"/>
<img v-else class="avatar" src="@/assets/nostr-purple.svg"/>
<a class="purple" :href="authorurl" target="_blank">{{ author }}</a>
<a className="white" style="background: #1f2937; font-size: xx-small" v-if="store.state.followings.find(x => x == authorid) !== undefined">Following</a>
<div class="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)}}
<a :href="authorurl" class="purple" target="_blank">{{ author }}</a>
<a v-if="store.state.followings.find(x => x == authorid) !== undefined" className="white"
style="background: #1f2937; font-size: xx-small">Following</a>
<div class="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>
<!--.substr(0, 320) + "\u2026"}} -->
</div>
<!--.substr(0, 320) + "\u2026"}} -->
<h3 v-html="StringUtil.parseImages(content)"></h3>
<!-- <h3>{{StringUtil.parseImages(content)}}</h3> -->
<!--<p>{{content.substr(0, 320) + "\u2026"}}</p> -->
<div style="padding: 2px; text-align: left;" >
<a class="menusmall" :href="links.uri" target="_blank">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>
<h3 v-html="StringUtil.parseImages(content)"></h3>
<!-- <h3>{{StringUtil.parseImages(content)}}</h3> -->
<!--<p>{{content.substr(0, 320) + "\u2026"}}</p> -->
<div style="padding: 2px; text-align: left;">
<a :href="links.uri" class="menusmall" target="_blank">Client</a>
<a :href="links.njump" class="menusmall" target="_blank">NJump</a>
<!--<a class="menusmall" :href="links.highlighter" target="_blank">Highlighter</a> -->
<a :href="links.nostrudel" class="menusmall" target="_blank">Nostrudel</a>
<div class="flex" >
<div class="flex">
<div class="flex" style="margin-right: 5px;" v-if="!reacted" @click="react(id, authorid, event)">
<div style="margin-right: 5px;">
<svg style="margin-top:4px" width="14" height="12" xmlns="http://www.w3.org/2000/svg" class="bi bi-heart" fill-rule="evenodd" fill="currentColor" viewBox="0 0 20 25" clip-rule="evenodd"><path d="M12 21.593c-5.63-5.539-11-10.297-11-14.402 0-3.791 3.068-5.191 5.281-5.191 1.312 0 4.151.501 5.719 4.457 1.59-3.968 4.464-4.447 5.726-4.447 2.54 0 5.274 1.621 5.274 5.181 0 4.069-5.136 8.625-11 14.402m5.726-20.583c-2.203 0-4.446 1.042-5.726 3.238-1.285-2.206-3.522-3.248-5.719-3.248-3.183 0-6.281 2.187-6.281 6.191 0 4.661 5.571 9.429 12 15.809 6.43-6.38 12-11.148 12-15.809 0-4.011-3.095-6.181-6.274-6.181"/></svg>
</div>
<div v-if="!reacted" class="flex" style="margin-right: 5px;" @click="react(id, authorid, event)">
<div style="margin-right: 5px;">
<svg class="bi bi-heart" clip-rule="evenodd" fill="currentColor" fill-rule="evenodd" height="12"
style="margin-top:4px" viewBox="0 0 20 25" width="14" xmlns="http://www.w3.org/2000/svg">
<path
d="M12 21.593c-5.63-5.539-11-10.297-11-14.402 0-3.791 3.068-5.191 5.281-5.191 1.312 0 4.151.501 5.719 4.457 1.59-3.968 4.464-4.447 5.726-4.447 2.54 0 5.274 1.621 5.274 5.181 0 4.069-5.136 8.625-11 14.402m5.726-20.583c-2.203 0-4.446 1.042-5.726 3.238-1.285-2.206-3.522-3.248-5.719-3.248-3.183 0-6.281 2.187-6.281 6.191 0 4.661 5.571 9.429 12 15.809 6.43-6.38 12-11.148 12-15.809 0-4.011-3.095-6.181-6.274-6.181"/>
</svg>
</div>
<div>
<p style="float: left;">{{reactions}}</p>
</div>
</div>
<div class="flex" v-if="reacted" style="margin-right: 5px;" @click="react(id, authorid, event)">
<div style="margin-left: auto; margin-right: 5px; float: left;">
<svg style="margin-top:4px" xmlns="http://www.w3.org/2000/svg" width="14" height="12" class="bi bi-heart fill-red-500" viewBox="0 0 20 25"><path d="M12 4.419c-2.826-5.695-11.999-4.064-11.999 3.27 0 7.27 9.903 10.938 11.999 15.311 2.096-4.373 12-8.041 12-15.311 0-7.327-9.17-8.972-12-3.27z"/></svg> </div>
<div>
<p className="text-red-500" style="float: left;">{{reactions}}</p>
</div>
</div>
<div class="flex" v-if="lud16 != null && lud16 != '' && !zapped" style="margin-right: 5px;" @click="zap_local(lud16, id, authorid)">
<div style="margin-left: auto; margin-right: 5px; float: left;">
<svg style="margin-top:4px" xmlns="http://www.w3.org/2000/svg" width="14" height="16" fill="currentColor" class="bi bi-lightning" viewBox="0 0 16 20">
<path d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641zM6.374 1 4.168 8.5H7.5a.5.5 0 0 1 .478.647L6.78 13.04 11.478 7H8a.5.5 0 0 1-.474-.658L9.306 1z"/>
</svg> </div>
<div>
<p style="float: left;">{{zapAmount/1000}}</p>
</div>
</div>
<div class="flex" v-if="lud16 != null && lud16 != '' && zapped" style="margin-right: 5px;" @click="zap_local(lud16, id, authorid)" >
<div style="margin-left: auto; margin-right: 5px;">
<svg style="margin-top:4px" xmlns="http://www.w3.org/2000/svg" width="14" height="16" class="bi bi-lightning fill-amber-400" viewBox="0 0 16 20">
<path d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641z"/>
</svg></div>
<div>
<p style="float: left;" className="text-amber-400">{{zapAmount/1000}}</p>
</div>
</div>
<div class="flex" v-if="!boosted" @click="boost(id, authorid, event)">
<div style="margin-left: auto; margin-right: 5px; float: left;">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="28" viewBox="0 0 20 34"><path class="bi" fill="currentColor" d="M19 7a1 1 0 0 0-1-1h-8v2h7v5h-3l3.969 5L22 13h-3zM5 17a1 1 0 0 0 1 1h8v-2H7v-5h3L6 6l-4 5h3z"/></svg> </div>
<div>
<p style="float: left;">{{boosts}}</p>
</div>
</div>
<div class="flex" v-if="boosted" @click="boost(id, authorid, event)">
<div style="margin-left: auto; margin-right: 5px; float: left;">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="28" viewBox="0 0 20 34">
<path class="bi fill-green-700" d="M19 7a1 1 0 0 0-1-1h-8v2h7v5h-3l3.969 5L22 13h-3zM5 17a1 1 0 0 0 1 1h8v-2H7v-5h3L6 6l-4 5h3z"/>
</svg> </div>
<div>
<p className="text-green-700" style="float: left;">{{boosts}}</p>
</div>
</div>
<details>
<summary class="" style=" margin-right: 5px">
<div style="margin-right: 5px; margin-left: 10px;margin-top: 4px"> <svg id="Capa_1" fill="currentColor" height="14" viewBox="0 0 600 600" xmlns="http://www.w3.org/2000/svg"><g>
<g id="ad">
<path d="m113.241 463.222-4.3-88.312c-68.332-36.05-108.941-95.703-108.941-160.522 0-52.154 26.017-101.029 73.259-137.619 46.512-36.024 108.215-55.864 173.741-55.864s127.229 19.84 173.742 55.865c47.242 36.59 73.259 85.465 73.259 137.619s-26.017 101.03-73.259 137.621c-46.512 36.023-108.215 55.863-173.742 55.863-1.889 0-3.843-.021-6.01-.067l-113.406 63.371c-9.113 4.959-14.343-.411-14.343-7.955zm133.759-423.021c-125.556 0-227.703 78.141-227.703 174.189 0 58.936 38.629 113.466 103.33 145.859 3.116 1.56 5.148 4.679 5.317 8.159l3.814 78.334 102.12-57.064c1.514-.852 3.232-1.275 4.968-1.222 3.108.084 5.698.124 8.152.124 125.556 0 227.703-78.141 227.703-174.188s-102.144-174.191-227.701-174.191z"/> </g></g></svg> </div>
</summary>
<div class="collapse-content font-size-0" className="z-10" id="collapse">
<textarea class="c-Input" style="width: auto; margin-left: -100px" v-model="message"></textarea>
<br>
<button class="v-Button" v-if="!replied" @click="reply(id, author, message); message=''">Reply</button>
<button class="btn" v-if="replied" >Replied</button>
</div>
</details>
</div>
<div>
<p style="float: left;">{{ reactions }}</p>
</div>
</div>
</template>
<div v-if="reacted" class="flex" style="margin-right: 5px;" @click="react(id, authorid, event)">
<div style="margin-left: auto; margin-right: 5px; float: left;">
<svg class="bi bi-heart fill-red-500" height="12" style="margin-top:4px" viewBox="0 0 20 25"
width="14" xmlns="http://www.w3.org/2000/svg">
<path
d="M12 4.419c-2.826-5.695-11.999-4.064-11.999 3.27 0 7.27 9.903 10.938 11.999 15.311 2.096-4.373 12-8.041 12-15.311 0-7.327-9.17-8.972-12-3.27z"/>
</svg>
</div>
<div>
<p className="text-red-500" style="float: left;">{{ reactions }}</p>
</div>
</div>
<div v-if="lud16 != null && lud16 != '' && !zapped" class="flex" style="margin-right: 5px;"
@click="zap_local(lud16, id, authorid)">
<div style="margin-left: auto; margin-right: 5px; float: left;">
<svg class="bi bi-lightning" fill="currentColor" height="16" style="margin-top:4px" viewBox="0 0 16 20"
width="14" xmlns="http://www.w3.org/2000/svg">
<path
d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641zM6.374 1 4.168 8.5H7.5a.5.5 0 0 1 .478.647L6.78 13.04 11.478 7H8a.5.5 0 0 1-.474-.658L9.306 1z"/>
</svg>
</div>
<div>
<p style="float: left;">{{ zapAmount / 1000 }}</p>
</div>
</div>
<div v-if="lud16 != null && lud16 != '' && zapped" class="flex" style="margin-right: 5px;"
@click="zap_local(lud16, id, authorid)">
<div style="margin-left: auto; margin-right: 5px;">
<svg class="bi bi-lightning fill-amber-400" height="16" style="margin-top:4px" viewBox="0 0 16 20"
width="14" xmlns="http://www.w3.org/2000/svg">
<path
d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641z"/>
</svg>
</div>
<div>
<p className="text-amber-400" style="float: left;">{{ zapAmount / 1000 }}</p>
</div>
</div>
<div v-if="!boosted" class="flex" @click="boost(id, authorid, event)">
<div style="margin-left: auto; margin-right: 5px; float: left;">
<svg height="28" viewBox="0 0 20 34" width="14" xmlns="http://www.w3.org/2000/svg">
<path class="bi" d="M19 7a1 1 0 0 0-1-1h-8v2h7v5h-3l3.969 5L22 13h-3zM5 17a1 1 0 0 0 1 1h8v-2H7v-5h3L6 6l-4 5h3z"
fill="currentColor"/>
</svg>
</div>
<div>
<p style="float: left;">{{ boosts }}</p>
</div>
</div>
<div v-if="boosted" class="flex" @click="boost(id, authorid, event)">
<div style="margin-left: auto; margin-right: 5px; float: left;">
<svg height="28" viewBox="0 0 20 34" width="14" xmlns="http://www.w3.org/2000/svg">
<path class="bi fill-green-700"
d="M19 7a1 1 0 0 0-1-1h-8v2h7v5h-3l3.969 5L22 13h-3zM5 17a1 1 0 0 0 1 1h8v-2H7v-5h3L6 6l-4 5h3z"/>
</svg>
</div>
<div>
<p className="text-green-700" style="float: left;">{{ boosts }}</p>
</div>
</div>
<details>
<summary class="" style=" margin-right: 5px">
<div style="margin-right: 5px; margin-left: 10px;margin-top: 4px">
<svg id="Capa_1" fill="currentColor" height="14" viewBox="0 0 600 600"
xmlns="http://www.w3.org/2000/svg">
<g>
<g id="ad">
<path
d="m113.241 463.222-4.3-88.312c-68.332-36.05-108.941-95.703-108.941-160.522 0-52.154 26.017-101.029 73.259-137.619 46.512-36.024 108.215-55.864 173.741-55.864s127.229 19.84 173.742 55.865c47.242 36.59 73.259 85.465 73.259 137.619s-26.017 101.03-73.259 137.621c-46.512 36.023-108.215 55.863-173.742 55.863-1.889 0-3.843-.021-6.01-.067l-113.406 63.371c-9.113 4.959-14.343-.411-14.343-7.955zm133.759-423.021c-125.556 0-227.703 78.141-227.703 174.189 0 58.936 38.629 113.466 103.33 145.859 3.116 1.56 5.148 4.679 5.317 8.159l3.814 78.334 102.12-57.064c1.514-.852 3.232-1.275 4.968-1.222 3.108.084 5.698.124 8.152.124 125.556 0 227.703-78.141 227.703-174.188s-102.144-174.191-227.701-174.191z"/>
</g>
</g>
</svg>
</div>
</summary>
</EasyDataTable>
<p></p>
<!-- <p>{{data}}</p> -->
<div id="collapse" class="collapse-content font-size-0" className="z-10">
<textarea v-model="message" class="c-Input" style="width: auto; margin-left: -100px"></textarea>
<br>
<button v-if="!replied" class="v-Button" @click="reply(id, author, message); message=''">Reply</button>
<button v-if="replied" class="btn">Replied</button>
</div>
</details>
</div>
</div>
</template>
</EasyDataTable>
<p></p>
<!-- <p>{{data}}</p> -->
</template>
<script lang="ts" setup>
import type {Header, Item, SortType} from "vue3-easy-data-table";
import type {Header, SortType} from "vue3-easy-data-table";
import store from '../store';
import {types} from "sass";
import Null = types.Null;
import StringUtil from "@/components/helper/string";
import {copyinvoice, parseandreplacenpubs, } from "@/components/helper/Helper.vue";
import {requestProvider} from "webln";
import {Event, EventBuilder, EventId, PublicKey, Tag} from "@rust-nostr/nostr-sdk";
import {zap, zap_lud16, createBolt11Lud16, zaprequest} from "@/components/helper/Zap.vue";
import {EventBuilder, EventId, PublicKey, Tag} from "@rust-nostr/nostr-sdk";
import {zap_lud16} from "@/components/helper/Zap.vue";
import {ref} from "vue";
const props = defineProps<{
const props = defineProps<{
data: any[]
}>()
@@ -154,99 +183,98 @@ const sortBy: String = "index";
const sortType: SortType = "asc";
const headers: Header[] = [
{ text: "Results:", value: "content", fixed: true},
// { text: "Time", value: "indicator.index", sortable: true, },
{text: "Results:", value: "content", fixed: true},
// { text: "Time", value: "indicator.index", sortable: true, },
];
const message = ref("");
async function react(eventid, authorid, evt){
async function react(eventid, authorid, evt) {
let event_id = EventId.parse(eventid)
let public_key = PublicKey.parse(authorid);
let signer = store.state.signer
let client = store.state.client
let objects = (props.data.find(x=> x.id === eventid))
if (objects !== undefined){
if(!objects.reacted ){
let event_id = EventId.parse(eventid)
let public_key = PublicKey.parse(authorid);
let signer = store.state.signer
let client = store.state.client
let objects = (props.data.find(x => x.id === eventid))
if (objects !== undefined) {
if (!objects.reacted) {
let event = EventBuilder.reaction(evt, "🧡")
let requestid = await client.sendEventBuilder(event);
}
let event = EventBuilder.reaction(evt, "🧡")
let requestid = await client.sendEventBuilder(event);
}
objects.reacted = true
objects.reactions += 1
console.log("reacted")
objects.reacted = true
objects.reactions += 1
console.log("reacted")
}
}
}
async function reply(eventid, authorid, message) {
async function reply (eventid, authorid, message){
console.log(eventid)
let signer = store.state.signer
let client = store.state.client
let objects = (props.data.find(x=> x.id === eventid))
if (objects !== undefined){
console.log(eventid)
let signer = store.state.signer
let client = store.state.client
let objects = (props.data.find(x => x.id === eventid))
if (objects !== undefined) {
let tags = [Tag.parse(["e", eventid])]
let event = EventBuilder.textNote(message, tags)
let tags = [Tag.parse(["e", eventid])]
let event = EventBuilder.textNote(message, tags)
let requestid = await client.sendEventBuilder(event);
console.log(requestid.toHex())
let requestid = await client.sendEventBuilder(event);
console.log(requestid.toHex())
objects.replied = true
console.log("replied")
}
objects.replied = true
console.log("replied")
}
}
async function boost(eventid, authorid, evt){
async function boost(eventid, authorid, evt) {
// TODO
let event_id = EventId.parse(eventid)
let public_key = PublicKey.parse(authorid);
let signer = store.state.signer
let client = store.state.client
let objects = (props.data.find(x=> x.id === eventid))
if (objects !== undefined){
if(!objects.boosted ){
let event_id = EventId.parse(eventid)
let public_key = PublicKey.parse(authorid);
let signer = store.state.signer
let client = store.state.client
let objects = (props.data.find(x => x.id === eventid))
if (objects !== undefined) {
if (!objects.boosted) {
console.log(evt.asJson())
let relay = "wss://relay.damus.io"
for (let tag of evt.tags){
if (tag.asVec()[0] == "relays"){
console.log(tag.asVec()[1])
}
console.log(evt.asJson())
let relay = "wss://relay.damus.io"
for (let tag of evt.tags) {
if (tag.asVec()[0] == "relays") {
console.log(tag.asVec()[1])
}
}
}
let event = EventBuilder.repost(evt)
let requestid = await client.sendEventBuilder(event);
}
let event = EventBuilder.repost(evt)
let requestid = await client.sendEventBuilder(event);
}
objects.boosted = true
objects.boosts += 1
console.log("boosted")
}
objects.boosted = true
objects.boosts += 1
console.log("boosted")
}
}
async function zap_local(lud16, eventid, authorid) {
if (lud16 == undefined || lud16 == ""){
console.log("User has no lightning address")
if (lud16 == undefined || lud16 == "") {
console.log("User has no lightning address")
return
}
@@ -265,12 +293,9 @@ async function zap_local(lud16, eventid, authorid) {
console.log("zapped")
}
}
}
catch (error)
{
console.log(error)
}
} catch (error) {
console.log(error)
}
}
@@ -283,6 +308,7 @@ async function zap_local(lud16, eventid, authorid) {
width: 20px;
cursor: pointer;
}
.playeauthor-wrapper {
padding: 6px;
display: flex;
@@ -294,10 +320,10 @@ async function zap_local(lud16, eventid, authorid) {
@apply btn text-gray-600 bg-transparent border-transparent tracking-wide ;
}
}
.vue3-easy-data-table__footer.previous-page__click-button{
height:100px
.vue3-easy-data-table__footer.previous-page__click-button {
height: 100px
}
.time {
@@ -307,6 +333,7 @@ async function zap_local(lud16, eventid, authorid) {
align-items: center;
justify-items: center;
}
.avatar {
margin-right: 10px;
display: inline-block;
@@ -318,19 +345,20 @@ async function zap_local(lud16, eventid, authorid) {
}
.c-Input {
@apply bg-base-200 text-accent dark:bg-black dark:text-white 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-accent-content 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: 180px;
@apply bg-base-200 text-accent dark:bg-black dark:text-white 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-accent-content 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: 180px;
margin-top: 15px;
margin-top: 15px;
}
.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-left: 10px;
height: 48px;
margin-left: 10px;
}
.customize-table {
width: auto;
--easy-table-border: 2px solid bg-base;

View File

@@ -1,17 +1,20 @@
<template>
<EasyDataTable style="margin-top: 450px"
class="customize-table" header-text-direction="left" hide-rows-per-page=true rows-per-page=10 v-if="store.state.profile_results.length != 0 && router.currentRoute.value.path == '/'" table-class-name="customize-table"
:headers="headers"
:items="store.state.profile_results" >
<template #item-content="{ author, authorurl, avatar}">
<div class="playeauthor-wrapper" >
<img class="avatar" v-if="avatar" :src="avatar" alt="Avatar" onerror="this.src='https://noogle.lol/favicon.ico'" />
<img class="avatar" v-else src="@/assets/nostr-purple.svg" />
<a class="purple" :href="authorurl" target="_blank">{{ author }}</a>
</div>
<EasyDataTable v-if="store.state.profile_results.length != 0 && router.currentRoute.value.path == '/'"
:headers="headers" :items="store.state.profile_results" class="customize-table" header-text-direction="left"
hide-rows-per-page=true
rows-per-page=10
style="margin-top: 450px"
table-class-name="customize-table">
<template #item-content="{ author, authorurl, avatar}">
<div class="playeauthor-wrapper">
<img v-if="avatar" :src="avatar" alt="Avatar" class="avatar"
onerror="this.src='https://noogle.lol/favicon.ico'"/>
<img v-else class="avatar" src="@/assets/nostr-purple.svg"/>
<a :href="authorurl" class="purple" target="_blank">{{ author }}</a>
</div>
<!-- <p>{{content}}</p> -->
</template>
<!-- <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>
@@ -22,7 +25,7 @@
</template> -->
</EasyDataTable>
</EasyDataTable>
</template>
@@ -30,19 +33,17 @@
<script lang="ts" setup>
import type {Header, Item, SortType} from "vue3-easy-data-table";
import type {Header} from "vue3-easy-data-table";
import store from '../store';
import router from "../router";
const headers: Header[] = [
{ text: "Relevant Profiles:", value: "content", fixed:true},
// { text: "Time", value: "indicator.time", sortable: true, },
{text: "Relevant Profiles:", value: "content", fixed: true},
// { text: "Time", value: "indicator.time", sortable: true, },
];
</script>
<style scoped>
@@ -50,6 +51,7 @@ const headers: Header[] = [
width: 20px;
cursor: pointer;
}
.playeauthor-wrapper {
padding: 6px;
display: flex;
@@ -61,10 +63,10 @@ const headers: Header[] = [
@apply btn text-gray-600 bg-transparent border-transparent tracking-wide;
}
}
.vue3-easy-data-table__footer.previous-page__click-button{
height:100px
.vue3-easy-data-table__footer.previous-page__click-button {
height: 100px
}
.time {
@@ -74,6 +76,7 @@ const headers: Header[] = [
align-items: center;
justify-items: center;
}
.avatar {
margin-right: 10px;
display: inline-block;
@@ -83,8 +86,9 @@ const headers: Header[] = [
object-fit: cover;
box-shadow: inset 0 4px 4px 0 rgb(0 0 0 / 10%);
}
.customize-table {
width:auto;
width: auto;
--easy-table-border: 3px solid #000000;
--easy-table-row-border: 0px;
@@ -118,7 +122,7 @@ const headers: Header[] = [
--easy-table-rows-per-page-selector-option-padding: 10px;
--easy-table-rows-per-page-selector-z-index: 1;
--easy-table-scrollbar-track-color: bg-base;
--easy-table-scrollbar-track-color: bg-base;
--easy-table-scrollbar-color: bg-base;
--easy-table-scrollbar-thumb-color: bg-base;
--easy-table-scrollbar-corner-color: bg-base;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,33 @@
<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">
<EasyDataTable v-if="store.state.results.length != 0" :headers="headers" :items="store.state.results"
:sort-by="sortBy"
:sort-type="sortType"
class="customize-table" header-text-direction="left"
table-class-name="customize-table">
<template #item-content="{ content, author, authorurl, avatar, indicator, links}">
<div class="playeauthor-wrapper">
<img class="avatar" v-if="avatar" :src="avatar" alt="Avatar" onerror="this.src='https://noogle.lol/favicon.ico'" />
<img class="avatar" v-else src="@/assets/nostr-purple.svg" />
<img v-if="avatar" :src="avatar" alt="Avatar" class="avatar"
onerror="this.src='https://noogle.lol/favicon.ico'"/>
<img v-else class="avatar" 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)}}
<a :href="authorurl" class="purple" target="_blank">{{ author }}</a>
<div :data-tip="indicator.time" class="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>
</template>
</EasyDataTable>
<p>{{ content.substr(0, 320) + "\u2026" }}</p>
<div style="padding: 2px; text-align: left;">
<a :href="links.uri" class="menusmall" target="_blank">Nostr Client</a>
<a :href="links.njump" class="menusmall" target="_blank">NJump</a>
<a :href="links.highlighter" class="menusmall" target="_blank">Highlighter</a>
<a :href="links.nostrudel" class="menusmall" target="_blank">Nostrudel</a>
</div>
</template>
</EasyDataTable>
</template>
@@ -33,14 +35,14 @@
<script lang="ts" setup>
import type {Header, Item, SortType} from "vue3-easy-data-table";
import type {Header, 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: "Results:", value: "content", fixed: true},
];
@@ -51,6 +53,7 @@ const headers: Header[] = [
width: 20px;
cursor: pointer;
}
.playeauthor-wrapper {
padding: 6px;
display: flex;
@@ -62,10 +65,10 @@ const headers: Header[] = [
@apply btn text-gray-600 bg-transparent border-transparent tracking-wide;
}
}
.vue3-easy-data-table__footer.previous-page__click-button{
height:100px
.vue3-easy-data-table__footer.previous-page__click-button {
height: 100px
}
.time {
@@ -75,6 +78,7 @@ const headers: Header[] = [
align-items: center;
justify-items: center;
}
.avatar {
margin-right: 10px;
display: inline-block;
@@ -84,6 +88,7 @@ const headers: Header[] = [
object-fit: cover;
box-shadow: inset 0 4px 4px 0 rgb(0 0 0 / 10%);
}
.customize-table {
width: auto;
--easy-table-border: 2px solid #000000;

View File

@@ -1,249 +1,221 @@
<script setup>
import {
Client,
Filter,
Timestamp,
Event,
Metadata,
PublicKey,
EventBuilder,
Tag,
EventId,
Nip19Event, Alphabet, Keys, nip04_decrypt, SecretKey, Duration
} from "@rust-nostr/nostr-sdk";
import {EventBuilder, Filter, Tag, Timestamp} from "@rust-nostr/nostr-sdk";
import store from '../store';
import miniToastr from "mini-toastr";
import VueNotifications from "vue-notifications";
import {computed, watch} from "vue";
import deadnip89s from "@/components/data/deadnip89s.json";
import {data} from "autoprefixer";
import {requestProvider} from "webln";
import Newnote from "@/components/Newnote.vue";
import {post_note, schedule, copyurl, copyinvoice, sleep, nextInput} from "../components/helper/Helper.vue"
import { ref } from "vue";
import ModalComponent from "../components/Newnote.vue";
import VueDatePicker from "@vuepic/vue-datepicker";
import {timestamp} from "@vueuse/core";
import NoteTable from "@/components/NoteTable.vue";
import {ref} from "vue";
import {sleep} from "../components/helper/Helper.vue"
import {zap} from "@/components/helper/Zap.vue";
import index from "vuex";
let dvms =[]
let dvms = []
let requestids = []
async function summarizefeed(eventids) {
listen()
let sortedIds = eventids.sort(function (a, b) {
return (a.index > b.index) ? 1 : ((b.index > a.index) ? -1 : 0);
});
let sortedIds = eventids.sort(function(a,b) {return (a.index > b.index) ? 1 : ((b.index > a.index) ? -1 : 0);} );
try {
if (store.state.pubkey === undefined || localStorage.getItem('nostr-key-method') === "anon") {
miniToastr.showMessage("In order to receive personalized recommendations, sign-in first.", "Not signed in.", VueNotifications.types.warn)
return
}
try {
if(store.state.pubkey === undefined || localStorage.getItem('nostr-key-method') === "anon"){
miniToastr.showMessage("In order to receive personalized recommendations, sign-in first.", "Not signed in.", VueNotifications.types.warn)
return
}
dvms = []
store.commit('set_summarization_dvms', dvms)
dvms = []
store.commit('set_summarization_dvms', dvms)
let client = store.state.client
let content = "NIP 90 Summarization request"
let kind = 5001
let client = store.state.client
let content = "NIP 90 Summarization request"
let kind = 5001
let tags = []
for (const tag of sortedIds){
try{
tags.push(["i", tag.id, "event"])
}
catch{}
}
let r = ["relays"]
for (let relay of store.state.relays){
r.push(relay)
}
tags.push(r)
let res;
let requestid;
let tags_t = []
for (let tag of tags){
tags_t.push(Tag.parse(tag))
}
let evt = new EventBuilder(kind, content, tags_t)
res = await client.sendEventBuilder(evt);
requestid = res.toHex();
console.log(res)
requestids.push(requestid)
store.commit('set_current_request_id_summarization', requestids)
} catch (error) {
console.log(error);
let tags = []
for (const tag of sortedIds) {
try {
tags.push(["i", tag.id, "event"])
} catch {
}
}
let r = ["relays"]
for (let relay of store.state.relays) {
r.push(relay)
}
tags.push(r)
let res;
let requestid;
let tags_t = []
for (let tag of tags) {
tags_t.push(Tag.parse(tag))
}
let evt = new EventBuilder(kind, content, tags_t)
res = await client.sendEventBuilder(evt);
requestid = res.toHex();
console.log(res)
requestids.push(requestid)
store.commit('set_current_request_id_summarization', requestids)
} catch (error) {
console.log(error);
}
}
async function listen() {
let client = store.state.client
let pubkey = store.state.pubkey
async function listen() {
let client = store.state.client
let pubkey = store.state.pubkey
const filter = new Filter().kinds([7000, 6001]).pubkey(pubkey).since(Timestamp.now());
await client.subscribe([filter]);
const filter = new Filter().kinds([7000, 6001]).pubkey(pubkey).since(Timestamp.now());
await client.subscribe([filter]);
const handle = {
// Handle event
handleEvent: async (relayUrl, subscriptionId, event) => {
/* if (store.state.summarizationhasEventListener === false){
return true
}*/
//const dvmname = getNamefromId(event.author.toHex())
console.log("Received new event from", relayUrl);
console.log(event.asJson())
let resonsetorequest = false
sleep(0).then(async () => {
for (let tag in event.tags) {
if (event.tags[tag].asVec()[0] === "e") {
const handle = {
// Handle event
handleEvent: async (relayUrl, subscriptionId, event) => {
/* if (store.state.summarizationhasEventListener === false){
return true
}*/
//const dvmname = getNamefromId(event.author.toHex())
console.log("Received new event from", relayUrl);
console.log(event.asJson())
let resonsetorequest = false
sleep(0).then(async () => {
for (let tag in event.tags) {
if (event.tags[tag].asVec()[0] === "e") {
if (store.state.requestidSummarization.includes(event.tags[tag].asVec()[1])){
resonsetorequest = true
}
}
if (store.state.requestidSummarization.includes(event.tags[tag].asVec()[1])) {
resonsetorequest = true
}
}
}
if (resonsetorequest === true) {
if (event.kind === 7000) {
try {
console.log("7000: ", event.content);
console.log("DVM: " + event.author.toHex())
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]
}
else{
let profiles = await get_user_infos([event.author.toHex()])
let created = 0
let current
console.log("NUM KIND0 FOUND " + profiles.length)
if (profiles.length > 0){
// for (const profile of profiles){
console.log(profiles[0].profile)
let current = profiles[0]
// if (profiles[0].profile.createdAt > created){
// created = profile.profile.createdAt
// current = profile
// }
let lud16 = current.profile.lud16
if (lud16 !== null && lud16 !== ""){
console.log("LUD16: " + lud16)
jsonentry.bolt11 = await createBolt11Lud16(lud16, jsonentry.amount)
console.log(jsonentry.bolt11)
if(jsonentry.bolt11 === ""){
status = "error"
}
}
else {
console.log("NO LNURL")
}
}
else {
console.log("PROFILE NOT FOUND")
}
}
}
}
//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)
}
/*if (event.content !== ""){
status = event.content
}*/
dvms.find(i => i.id === jsonentry.id).status = status
store.commit('set_summarization_dvms', dvms)
} catch (error) {
console.log("Error: ", error);
}
}
else if (event.kind === 6001){
console.log(event.content)
dvms.find(i => i.id === event.author.toHex()).result = event.content
dvms.find(i => i.id === event.author.toHex()).status = "finished"
store.commit('set_summarization_dvms', dvms)
}
}
})
},
// Handle relay message
handleMsg: async (relayUrl, message) => {
//console.log("Received message from", relayUrl, message.asJson());
}
};
if (resonsetorequest === true) {
if (event.kind === 7000) {
client.handleNotifications(handle);
try {
console.log("7000: ", event.content);
console.log("DVM: " + event.author.toHex())
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]
} else {
let profiles = await get_user_infos([event.author.toHex()])
let created = 0
let current
console.log("NUM KIND0 FOUND " + profiles.length)
if (profiles.length > 0) {
// for (const profile of profiles){
console.log(profiles[0].profile)
let current = profiles[0]
// if (profiles[0].profile.createdAt > created){
// created = profile.profile.createdAt
// current = profile
// }
let lud16 = current.profile.lud16
if (lud16 !== null && lud16 !== "") {
console.log("LUD16: " + lud16)
jsonentry.bolt11 = await createBolt11Lud16(lud16, jsonentry.amount)
console.log(jsonentry.bolt11)
if (jsonentry.bolt11 === "") {
status = "error"
}
} else {
console.log("NO LNURL")
}
} else {
console.log("PROFILE NOT FOUND")
}
}
}
}
//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)
}
/*if (event.content !== ""){
status = event.content
}*/
dvms.find(i => i.id === jsonentry.id).status = status
store.commit('set_summarization_dvms', dvms)
} catch (error) {
console.log("Error: ", error);
}
} else if (event.kind === 6001) {
console.log(event.content)
dvms.find(i => i.id === event.author.toHex()).result = event.content
dvms.find(i => i.id === event.author.toHex()).status = "finished"
store.commit('set_summarization_dvms', dvms)
}
}
})
},
// Handle relay message
handleMsg: async (relayUrl, message) => {
//console.log("Received message from", relayUrl, message.asJson());
}
};
client.handleNotifications(handle);
}
async function zap_local(invoice) {
let success = await zap(invoice)
if (success){
dvms.find(i => i.bolt11 === invoice).status = "paid"
if (success) {
dvms.find(i => i.bolt11 === invoice).status = "paid"
store.commit('set_summarization_dvms', dvms)
}
@@ -257,7 +229,6 @@ defineProps({
})
const isModalOpened = ref(false);
const modalcontent = ref("");
const datetopost = ref(Date.now());
@@ -284,7 +255,6 @@ const submitHandler = async () => {
}
</script>
<!-- font-thin bg-gradient-to-r from-white to-nostr bg-clip-text text-transparent -->
@@ -296,79 +266,80 @@ const submitHandler = async () => {
<h3 class="text-7xl font-black tracking-wide">Summarization</h3>
<h3>
<br>
<button class="v-Button" @click="summarizefeed($props.events)">Summarize Results</button>
<br>
<button class="v-Button" @click="summarizefeed($props.events)">Summarize Results</button>
</h3>
</div>
<br>
<div class=" relative space-y-2">
<div class="grid grid-cols-1 gap-2 " >
<div className="card w-70 bg-base-100 shadow-xl" v-for="dvm in store.state.summarizationdvms"
:key="dvm.id">
<div class="grid grid-cols-1 gap-2 ">
<div v-for="dvm in store.state.summarizationdvms" :key="dvm.id"
className="card w-70 bg-base-100 shadow-xl">
<div className="card-body">
<div className="playeauthor-wrapper">
<figure className="w-20">
<img className="avatar" v-if="dvm.image" :src="dvm.image" alt="DVM Picture" />
<img class="avatar" v-else src="@/assets/nostr-purple.svg" />
</figure>
<div className="playeauthor-wrapper">
<figure className="w-20">
<img v-if="dvm.image" :src="dvm.image" alt="DVM Picture" className="avatar"/>
<img v-else class="avatar" src="@/assets/nostr-purple.svg"/>
</figure>
<h2 className="card-title">{{ dvm.name }}</h2>
</div>
<h3 class="fa-cut" >{{ dvm.about }}</h3>
<h2 className="card-title">{{ dvm.name }}</h2>
</div>
<h3 class="fa-cut">{{ dvm.about }}</h3>
<div className="card-actions justify-end mt-auto">
<div className="card-actions justify-end mt-auto" >
<div className="tooltip mt-auto">
<div className="tooltip mt-auto">
<button v-if="dvm.status !== 'finished' && dvm.status !== 'paid' && dvm.status !== 'payment-required' && dvm.status !== 'error'" className="btn">{{dvm.status}}</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_local(dvm.bolt11);">{{ dvm.amount/1000 }} Sats</button>
<button
v-if="dvm.status !== 'finished' && dvm.status !== 'paid' && dvm.status !== 'payment-required' && dvm.status !== 'error'"
className="btn">{{ dvm.status }}
</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_local(dvm.bolt11);">
{{ dvm.amount / 1000 }} Sats
</button>
</div>
</div>
</div>
<!-- <div v-if="dvm.result.length > 0" class="collapse bg-base-200">
<input type="checkbox" class="peer" />
<div class="collapse-title bg-primary text-primary-content peer-checked:bg-secondary peer-checked:text-secondary-content">
Click me to show/hide content
</div>
<div class="collapse-content bg-primary text-primary-content peer-checked:bg-base-200 peer-checked:text-accent">
</div>
</div> -->
<p v-if="dvm.status === 'finished'">{{ dvm.result }}</p>
<!-- <details v-if="dvm.status === 'finished'" class="collapse bg-base">
<summary class="collapse-title "><div class="btn">Show/Hide Results</div></summary>
<div class="collapse-content font-size-0" className="z-10" id="collapse">
</div>
</details>-->
<!-- <div v-if="dvm.result.length > 0" class="collapse bg-base-200">
<input type="checkbox" class="peer" />
<div class="collapse-title bg-primary text-primary-content peer-checked:bg-secondary peer-checked:text-secondary-content">
Click me to show/hide content
</div>
<div class="collapse-content bg-primary text-primary-content peer-checked:bg-base-200 peer-checked:text-accent">
</div>
</div> -->
<p v-if="dvm.status === 'finished'">{{dvm.result}}</p>
<!-- <details v-if="dvm.status === 'finished'" class="collapse bg-base">
<summary class="collapse-title "><div class="btn">Show/Hide Results</div></summary>
<div class="collapse-content font-size-0" className="z-10" id="collapse">
</div>
</details>-->
</div>
</div>
</div>
@@ -380,15 +351,15 @@ const submitHandler = async () => {
<style scoped>
.zap-Button{
.zap-Button {
@apply btn hover:bg-amber-400 border-amber-400 text-base;
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;
height: 48px;
margin: 5px;
}
.c-Input {
@@ -400,7 +371,7 @@ const submitHandler = async () => {
}
.d-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;
@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: 300px;
color: white;
@@ -415,16 +386,16 @@ const submitHandler = async () => {
}
.logo {
display: flex;
width:100%;
height:125px;
justify-content: center;
align-items: center;
display: flex;
width: 100%;
height: 125px;
justify-content: center;
align-items: center;
}
h3 {
font-size: 1.0rem;
text-align: left;
text-align: left;
}

View File

@@ -1,74 +1,218 @@
[
{"id": "766809b054c9b772652377ef968625509a7e92c56669e302940ac08c8c3d0f96"},
{"id": "7fb49260fbd9148e08672b8339bca6c5a866cf7aaa03051898ed02f6d85109b2"},
{"id": "edd11ae518e4f59a25472d5ef869f114c8e5399723fd7bed32389eef37a6ec0c"},
{"id": "b6e93a7185036b69b04a55665409957ba4d9fb2a944e43c690e6f4d64678c43f"},
{"id": "be40dfce56ff47bce6cfa2073dd6c6d88e53d44d7e1178cc30ebb4ca991de4e4"},
{"id": "72d86d5428049c74f94ac335cd662772f580fa27497398dd06b443653a16b4ad"},
{"id": "0e2b90ea31426f03f9ccfff6093aacde0322a2c026d3fedf47fa35e722970fdf"},
{"id": "ad281d17781cdcbdfce38cf13188f56b9dbb16977ca029823a3d6e0fa502e73a"},
{"id": "c0361dd4bbae4cc32be424cf564f547b29496b3bd7bbbf3ede0cb0b8d8930b5c"},
{"id": "349fdcad3da119f09bde6861806ae3ff461b1eb3b3708067f0abb0e669c54841"},
{"id": "d9a016283161f262b2764e6a5710f9c2dc1aca19a42d19cca5af7cc20ff2955e"},
{"id": "365aa211f1e873988dacb4ff1a10fe3b7221a940c3d155b8f4d33a25ca42fa52"},
{"id": "2b07103533f747c0899f00f575c79cdea960ac62b33d06780e284eb020215c0b"},
{"id": "5f7ce70135b7172358ee41b0f1f0ff9110af7294eef7ca7878882e129e6104db"},
{"id": "b570d7d7d68130750c4b84aa3808fd209ed767300246365a5deaaedffcfb6d0b"},
{"id": "3468c0769e9a8c10cc74e9bdbf11a00df1b35480b65059f71357c7f1a9e35d68"},
{"id": "1f0cf47de297037e91450631552b3ff7ce6567b73eac57e94bbbe2d6ca99e744"},
{"id": "02650e51270e0a734505fb2876adbef89f26bbe660ca4e8fadea0ecf1ea1b1d0"},
{"id": "764b2ac58c23310f2caeecd155eff294f190e433438d3df5a244b5af979d3a81"},
{"id": "c788b8a0ce4e9d795dd1895e87c0e3dd019766ebbfcd4f99112d523b8374e9de"},
{"id": "e9ec70f0f0c1e8134efacb9941647d451f4c6d3acccb40b878598ade9308599a"},
{"id": "4f3e5fbbb27392ce4b4ef46ee0d5bc42e5112bde6cb72644a34d89bc7505b9d5"},
{"id": "5e4e3c95215be93be3bc5bac242f6b332c1265140d179f31af858e8f172c8d6a"},
{"id": "bdbcfb112b0f7d55e2bcc231ec06335ea5051d49edcbed8170f717f8ecf1a965"},
{"id": "294303fbde21251093bb86683701023bd1d7e310a64e0b1068f6160696f3c6a4"},
{"id": "00ef6f71fcaa72742493178b8409c32bb68d92c9f67af717f92bef35272a74d4"},
{"id": "4fff1259602cf46619d379ee8c790a1acc310a53cb617fa46d522978d6b4876b"},
{"id": "aab06b1602f0380e6c2f442c7992c82259968d8abbba1da69d774a32d747c3b4"},
{"id": "4bbee7e48d393b692f80e5a5357fcb435adbd46172b38f367a43c3aeb45b2fb3"},
{"id": "97a7fa0776225a5eb644da81db9a73eacebf046d7fe745f567345c1cec0a9e32"},
{"id": "aad1de5bb5dc4ce80de3d55a6ce7037ddb46aadb4e44c3742781d1422cf79765"},
{"id": "2dcd9ea8b4959c7b986bfda2bdc8175ed156a474457d38be42f54f027a1dff5a"},
{"id": "747215ea31506d60af14bae6914fd1107de0893f99c0f2e178216bea79de4677"},
{"id": "d69a3d1b7d635ba12be30ebb9473ad4a973138e54ef1aaa2f6cce060a82937b4"},
{"id": "c4ba426af0bb7be9de06b774aec33b7733cb952c5e1bc723c9bf021b3e2be1ea"},
{"id": "0f7dac8f31a9aac4d4479373153489fc57889c964e82dd619bed2f60f0af27ee"},
{"id": "561420baa35477e27b85e62ecfded0b76cab0c0acaedc9b3ab6ac7d88be42165"},
{"id": "d68d8eab7bad9c263f5af0eb46db168d2d82ad19acc5fb19c606fcb18de7994b"},
{"id": "86f7e9f6d98831e0ad19a575512f3d969d3af6921260809cc7a33b3b918d87f1"},
{"id": "f9287d47f86cc0af606026fe5e017fd479230b6cd2dcc82db915603658312d82"},
{"id": "cb83acb45cd810d8fd0df5f1f40d5bfd5406b74e37c9cda54c77114c5dcd357a"},
{"id": "5457c08086b3e78887c8eeb39cdd8dcb6559ceea13f32cc4a6f8a84513bfacf1"},
{"id": "1c86e2d22620ec6c94aac12fad7ed304bdf439020e74bbc0f0fc096bd5335891"},
{"id": "6ad22ca994d0b5952b26cb0b4cae939d474f57729e18509574ace9882a635641"},
{"id": "e15e167f70fb7d3ab740248e993096ecd7819de7ad5640f05e5c302b34737f33"},
{"id": "a391df97b5fdf380f78091d18da0626afbf9ca2f9517935f3dee766cd0ac72fe"},
{"id": "7b4185b0d115b5a12ba57f6804703789c68fb52d1587487161e96011a6a72223"},
{"id": "dbd86fc945e0748b2f263abad2338ff212ae02a895f38b0a2c262a0da518ebd2"},
{"id": "91591d5dd56657a1acbcc04116f17b2264dd369b9ad361bf15033e6ca326f5ac"},
{"id": "eb382df17d822d81d85097f28a49f86dc69ba8a05285dff39e2d877ea31e21cc"},
{"id": "b4a85c1e7e4c13281ae58538c57529cc6035ee465a2f69e40b41a6711a2eeb18"},
{"id": "0ea69892da43e1b4de82bde7bb599c3f15a71120f9f506fd210c2712ba7026a3"},
{"id": "b424c79388a2ea8b04e72f7ea32c0648db15ca5f25705bcd4231d0b658156af1"},
{"id": "db11596a64f76082991df4d1d1e8764f4d8da926f81ddbe09333d2ca1335ecd6"},
{"id": "f6e4c5cba1dc008f9b9611515ba163ccd1489105265dc8b2809eb846c1b94209"},
{"id": "cd4c4f1e65bd1f351dabf8c04fe2903b043ce98ce5613808c027c6609a0556d5"},
{"id": "9b0172004b25ee43e517ed6dd969bceb3fef4db3a577f91d8a3dc9cb6fe4e1d1"},
{"id": "ca0ee728c85f4df5ffab3561f55fdd2295291a86cd409839c59b92903d041025"},
{"id": "c589506d090796e304763dc269731029be08dee1706c1e87413fb376a2e84a97"},
{"id": "99ea6a5a7701c255661fc2bea32cb615ca0d4674c45fe6633e58e7eeb5f92873"},
{"id": "8e55f6ec8de9e8b4f75e3a771c601c1583855b5d113124ac9fb997b8589117fc"},
{"id": "11803eb1505d5014bc13c48621638a94f0b852587f0b5adbcb3ee471d9488ec3"},
{"id": "488cf9801acccc925b75d6828287ecaaff8b2bee9b58ce26fa0a2abdd61bd155"},
{"id": "0e9bc4a5989a39d4fc7ba73876c88822928b1cc965ed158b431759378363c182"},
{"id": "386b2cd47df9260f5b313b151ae988d0710e83e615dfd2abc948f1fa93eb76d6"},
{"id": "a451833e4856194aa5f56508eb34c298a5718539b9d320a2b7b30f32a107cc37"},
{"id": "91c0639025aba28c5af2178f49d653757bcc68e88d7cc461c86edc1ac2a61942"},
{"id": "aaf0b0846e265dec3dcf7b943ea2fc0331daf29a6114ac2eb971c10988e73f6d"},
{"id": "d26a9c5d89b9ce197e03bf91e2768df571cf04df796b5ae08742aea97be1c8c5"},
{"id": "490debe9303abe3c72fae49c62f8be15556a78c77c4d74e82305c5ce5723986a"},
{"id": "52348da7537eb13da45277d755b7b26dfcb249b3b602b2c49b65ecd908c6cde0"},
{"id": "1f31fe5bfb3e75c5e984201bfd6be15632f266171ecaf8714829a503818865bf"}
{
"id": "766809b054c9b772652377ef968625509a7e92c56669e302940ac08c8c3d0f96"
},
{
"id": "7fb49260fbd9148e08672b8339bca6c5a866cf7aaa03051898ed02f6d85109b2"
},
{
"id": "edd11ae518e4f59a25472d5ef869f114c8e5399723fd7bed32389eef37a6ec0c"
},
{
"id": "b6e93a7185036b69b04a55665409957ba4d9fb2a944e43c690e6f4d64678c43f"
},
{
"id": "be40dfce56ff47bce6cfa2073dd6c6d88e53d44d7e1178cc30ebb4ca991de4e4"
},
{
"id": "72d86d5428049c74f94ac335cd662772f580fa27497398dd06b443653a16b4ad"
},
{
"id": "0e2b90ea31426f03f9ccfff6093aacde0322a2c026d3fedf47fa35e722970fdf"
},
{
"id": "ad281d17781cdcbdfce38cf13188f56b9dbb16977ca029823a3d6e0fa502e73a"
},
{
"id": "c0361dd4bbae4cc32be424cf564f547b29496b3bd7bbbf3ede0cb0b8d8930b5c"
},
{
"id": "349fdcad3da119f09bde6861806ae3ff461b1eb3b3708067f0abb0e669c54841"
},
{
"id": "d9a016283161f262b2764e6a5710f9c2dc1aca19a42d19cca5af7cc20ff2955e"
},
{
"id": "365aa211f1e873988dacb4ff1a10fe3b7221a940c3d155b8f4d33a25ca42fa52"
},
{
"id": "2b07103533f747c0899f00f575c79cdea960ac62b33d06780e284eb020215c0b"
},
{
"id": "5f7ce70135b7172358ee41b0f1f0ff9110af7294eef7ca7878882e129e6104db"
},
{
"id": "b570d7d7d68130750c4b84aa3808fd209ed767300246365a5deaaedffcfb6d0b"
},
{
"id": "3468c0769e9a8c10cc74e9bdbf11a00df1b35480b65059f71357c7f1a9e35d68"
},
{
"id": "1f0cf47de297037e91450631552b3ff7ce6567b73eac57e94bbbe2d6ca99e744"
},
{
"id": "02650e51270e0a734505fb2876adbef89f26bbe660ca4e8fadea0ecf1ea1b1d0"
},
{
"id": "764b2ac58c23310f2caeecd155eff294f190e433438d3df5a244b5af979d3a81"
},
{
"id": "c788b8a0ce4e9d795dd1895e87c0e3dd019766ebbfcd4f99112d523b8374e9de"
},
{
"id": "e9ec70f0f0c1e8134efacb9941647d451f4c6d3acccb40b878598ade9308599a"
},
{
"id": "4f3e5fbbb27392ce4b4ef46ee0d5bc42e5112bde6cb72644a34d89bc7505b9d5"
},
{
"id": "5e4e3c95215be93be3bc5bac242f6b332c1265140d179f31af858e8f172c8d6a"
},
{
"id": "bdbcfb112b0f7d55e2bcc231ec06335ea5051d49edcbed8170f717f8ecf1a965"
},
{
"id": "294303fbde21251093bb86683701023bd1d7e310a64e0b1068f6160696f3c6a4"
},
{
"id": "00ef6f71fcaa72742493178b8409c32bb68d92c9f67af717f92bef35272a74d4"
},
{
"id": "4fff1259602cf46619d379ee8c790a1acc310a53cb617fa46d522978d6b4876b"
},
{
"id": "aab06b1602f0380e6c2f442c7992c82259968d8abbba1da69d774a32d747c3b4"
},
{
"id": "4bbee7e48d393b692f80e5a5357fcb435adbd46172b38f367a43c3aeb45b2fb3"
},
{
"id": "97a7fa0776225a5eb644da81db9a73eacebf046d7fe745f567345c1cec0a9e32"
},
{
"id": "aad1de5bb5dc4ce80de3d55a6ce7037ddb46aadb4e44c3742781d1422cf79765"
},
{
"id": "2dcd9ea8b4959c7b986bfda2bdc8175ed156a474457d38be42f54f027a1dff5a"
},
{
"id": "747215ea31506d60af14bae6914fd1107de0893f99c0f2e178216bea79de4677"
},
{
"id": "d69a3d1b7d635ba12be30ebb9473ad4a973138e54ef1aaa2f6cce060a82937b4"
},
{
"id": "c4ba426af0bb7be9de06b774aec33b7733cb952c5e1bc723c9bf021b3e2be1ea"
},
{
"id": "0f7dac8f31a9aac4d4479373153489fc57889c964e82dd619bed2f60f0af27ee"
},
{
"id": "561420baa35477e27b85e62ecfded0b76cab0c0acaedc9b3ab6ac7d88be42165"
},
{
"id": "d68d8eab7bad9c263f5af0eb46db168d2d82ad19acc5fb19c606fcb18de7994b"
},
{
"id": "86f7e9f6d98831e0ad19a575512f3d969d3af6921260809cc7a33b3b918d87f1"
},
{
"id": "f9287d47f86cc0af606026fe5e017fd479230b6cd2dcc82db915603658312d82"
},
{
"id": "cb83acb45cd810d8fd0df5f1f40d5bfd5406b74e37c9cda54c77114c5dcd357a"
},
{
"id": "5457c08086b3e78887c8eeb39cdd8dcb6559ceea13f32cc4a6f8a84513bfacf1"
},
{
"id": "1c86e2d22620ec6c94aac12fad7ed304bdf439020e74bbc0f0fc096bd5335891"
},
{
"id": "6ad22ca994d0b5952b26cb0b4cae939d474f57729e18509574ace9882a635641"
},
{
"id": "e15e167f70fb7d3ab740248e993096ecd7819de7ad5640f05e5c302b34737f33"
},
{
"id": "a391df97b5fdf380f78091d18da0626afbf9ca2f9517935f3dee766cd0ac72fe"
},
{
"id": "7b4185b0d115b5a12ba57f6804703789c68fb52d1587487161e96011a6a72223"
},
{
"id": "dbd86fc945e0748b2f263abad2338ff212ae02a895f38b0a2c262a0da518ebd2"
},
{
"id": "91591d5dd56657a1acbcc04116f17b2264dd369b9ad361bf15033e6ca326f5ac"
},
{
"id": "eb382df17d822d81d85097f28a49f86dc69ba8a05285dff39e2d877ea31e21cc"
},
{
"id": "b4a85c1e7e4c13281ae58538c57529cc6035ee465a2f69e40b41a6711a2eeb18"
},
{
"id": "0ea69892da43e1b4de82bde7bb599c3f15a71120f9f506fd210c2712ba7026a3"
},
{
"id": "b424c79388a2ea8b04e72f7ea32c0648db15ca5f25705bcd4231d0b658156af1"
},
{
"id": "db11596a64f76082991df4d1d1e8764f4d8da926f81ddbe09333d2ca1335ecd6"
},
{
"id": "f6e4c5cba1dc008f9b9611515ba163ccd1489105265dc8b2809eb846c1b94209"
},
{
"id": "cd4c4f1e65bd1f351dabf8c04fe2903b043ce98ce5613808c027c6609a0556d5"
},
{
"id": "9b0172004b25ee43e517ed6dd969bceb3fef4db3a577f91d8a3dc9cb6fe4e1d1"
},
{
"id": "ca0ee728c85f4df5ffab3561f55fdd2295291a86cd409839c59b92903d041025"
},
{
"id": "c589506d090796e304763dc269731029be08dee1706c1e87413fb376a2e84a97"
},
{
"id": "99ea6a5a7701c255661fc2bea32cb615ca0d4674c45fe6633e58e7eeb5f92873"
},
{
"id": "8e55f6ec8de9e8b4f75e3a771c601c1583855b5d113124ac9fb997b8589117fc"
},
{
"id": "11803eb1505d5014bc13c48621638a94f0b852587f0b5adbcb3ee471d9488ec3"
},
{
"id": "488cf9801acccc925b75d6828287ecaaff8b2bee9b58ce26fa0a2abdd61bd155"
},
{
"id": "0e9bc4a5989a39d4fc7ba73876c88822928b1cc965ed158b431759378363c182"
},
{
"id": "386b2cd47df9260f5b313b151ae988d0710e83e615dfd2abc948f1fa93eb76d6"
},
{
"id": "a451833e4856194aa5f56508eb34c298a5718539b9d320a2b7b30f32a107cc37"
},
{
"id": "91c0639025aba28c5af2178f49d653757bcc68e88d7cc461c86edc1ac2a61942"
},
{
"id": "aaf0b0846e265dec3dcf7b943ea2fc0331daf29a6114ac2eb971c10988e73f6d"
},
{
"id": "d26a9c5d89b9ce197e03bf91e2768df571cf04df796b5ae08742aea97be1c8c5"
},
{
"id": "490debe9303abe3c72fae49c62f8be15556a78c77c4d74e82305c5ce5723986a"
},
{
"id": "52348da7537eb13da45277d755b7b26dfcb249b3b602b2c49b65ecd908c6cde0"
},
{
"id": "1f31fe5bfb3e75c5e984201bfd6be15632f266171ecaf8714829a503818865bf"
}
]

View File

@@ -4,65 +4,61 @@ import store from "@/store";
import {
Alphabet,
Duration,
Event,
EventBuilder,
EventId,
Filter,
Keys,
PublicKey,
SingleLetterTag,
Tag,
Timestamp, UnsignedEvent
Timestamp
} from "@rust-nostr/nostr-sdk";
import miniToastr from "mini-toastr/mini-toastr";
import VueNotifications from "vue-notifications";
import {bech32} from "bech32";
export default defineComponent({
name: "posting"
})
export async function post_note(note){
let client = store.state.client
let tags = []
export async function post_note(note) {
let client = store.state.client
let tags = []
await client.publishTextNote(note, tags);
await client.publishTextNote(note, tags);
}
export async function react_to_dvm(dvm, reaction) {
let client = store.state.client
let client = store.state.client
let event = EventBuilder.reaction(dvm.event, reaction)
let requestid = await client.sendEventBuilder(event);
let event = EventBuilder.reaction(dvm.event, reaction)
let requestid = await client.sendEventBuilder(event);
let users = await get_user_infos([store.state.pubkey])
console.log(users[0])
if (reaction === "👎"){
dvm.reactions.negativeUser = true
let users = await get_user_infos([store.state.pubkey])
console.log(users[0])
if (reaction === "👎") {
dvm.reactions.negativeUser = true
dvm.reactions.negative.push(users[0])
}
else {
dvm.reactions.positiveUser = true
dvm.reactions.positive.push(users[0])
}
dvm.reactions.negative.push(users[0])
} else {
dvm.reactions.positiveUser = true
dvm.reactions.positive.push(users[0])
}
}
export async function schedule(note, datetopost) {
let schedule = Timestamp.fromSecs(datetopost/1000)
let schedule = Timestamp.fromSecs(datetopost / 1000)
let humandatetime = schedule.toHumanDatetime()
let time = humandatetime.split("T")[1].split("Z")[0].trim()
let date = humandatetime.split("T")[0].split("-")[2].trim() + "." + humandatetime.split("T")[0].split("-")[1].trim() + "." + humandatetime.split("T")[0].split("-")[0].trim().slice(2)
let time = humandatetime.split("T")[1].split("Z")[0].trim()
let date = humandatetime.split("T")[0].split("-")[2].trim() + "." + humandatetime.split("T")[0].split("-")[1].trim() + "." + humandatetime.split("T")[0].split("-")[0].trim().slice(2)
console.log("Date: " + date + " Time: "+ time )
console.log("Date: " + date + " Time: " + time)
let client = store.state.client
let signer = store.state.signer
@@ -90,14 +86,14 @@ export async function schedule(note, datetopost) {
console.log(evt)
let res = await client.sendEventBuilder(evt);
console.log(res)
miniToastr.showMessage("Note scheduled for " + ("Date: " + date + " Time: "+ time ))
miniToastr.showMessage("Note scheduled for " + ("Date: " + date + " Time: " + time))
}
export async function getEvents(eventids) {
let ids = []
for (let eid of eventids){
for (let eid of eventids) {
ids.push(EventId.parse(eid))
}
const event_filter = new Filter().ids(ids)
@@ -105,21 +101,22 @@ export async function getEvents(eventids) {
return await client.getEventsOf([event_filter], Duration.fromSecs(5))
}
export async function getEventsOriginalOrder(eventids) {
let ids = []
for (let eid of eventids){
for (let eid of eventids) {
ids.push(EventId.parse(eid))
}
const event_filter = new Filter().ids(ids)
let client = store.state.client
let results = await client.getEventsOf([event_filter], Duration.fromSecs(5))
let results = await client.getEventsOf([event_filter], Duration.fromSecs(5))
/*console.log(results.length)
for (let e of results){
console.log(e.id.toHex())
} */
let final = []
for (let f of eventids){
for (let f of eventids) {
let note = results.find(value => value.id.toHex() === f)
//console.log(note)
final.push(note)
@@ -137,164 +134,161 @@ export function nextInput(e) {
}
}
export async function get_user_infos(pubkeys){
let pkeys = []
for (let pk of pubkeys){
pkeys.push(PublicKey.parse(pk))
}
let profiles = []
let client = store.state.client
const profile_filter = new Filter().kind(0).authors(pkeys)
let evts = await client.getEventsOf([profile_filter], Duration.fromSecs(10))
for (const entry of evts){
try{
let contentjson = JSON.parse(entry.content)
//console.log(contentjson)
profiles.push({profile: contentjson, author: entry.author.toHex(), createdAt: entry.createdAt});
}
catch(error){
console.log("error")
}
}
return profiles
}
export async function get_event_reactions(ids){
let zapsandreactions = []
for (let id of ids){
zapsandreactions.push({
id: id.toHex(),
amount: 0,
reactions: 0,
reposts: 0,
zappedbyUser: false,
reactedbyUser: false,
repostedbyUser: false,})
}
let client = store.state.client
const zap_filter = new Filter().kinds([9735, 6, 7]).events(ids)
let evts = await client.getEventsOf([zap_filter], Duration.fromSecs(10))
for (const entry of evts){
try{
//let contentjson = JSON.parse(entry.content)
if (entry.kind === 9735){
for (let tag of entry.tags) {
if (tag.asVec()[0] === "description") {
let request = JSON.parse(tag.asVec()[1])
let etag = ""
let amount = 0
for (let tg of request.tags) {
if (tg[0] === "amount") {
amount = parseInt(tg[1])
}
if (tg[0] === "e") {
etag = tg[1]
//console.log(request.pubkey)
if (request.pubkey === localStorage.getItem("nostr-key")) {
zapsandreactions.find(x => x.id === etag).zappedbyUser = true
}
}
}
zapsandreactions.find(x => x.id === etag).amount += amount
}
}
}
else if (entry.kind === 7) {
for (let tag of entry.tags) {
if (tag.asVec()[0] === "e") {
if (entry.author.toHex() === localStorage.getItem("nostr-key")) {
zapsandreactions.find(x => x.id === tag.asVec()[1]).reactedbyUser = true
}
zapsandreactions.find(x => x.id === tag.asVec()[1]).reactions += 1
}
}
}
else if (entry.kind === 6) {
for (let tag of entry.tags) {
if (tag.asVec()[0] === "e") {
if (entry.author.toHex() === localStorage.getItem("nostr-key")) {
zapsandreactions.find(x => x.id === tag.asVec()[1]).repostedbyUser = true
}
zapsandreactions.find(x => x.id === tag.asVec()[1]).reposts += 1
}
}
}
//console.log(contentjson)
//zaps.push({profile: contentjson, author: entry.author.toHex(), createdAt: entry.createdAt});
}
catch(error){
//console.log(error)
}
}
//console.log(zapsandreactions)
return zapsandreactions
export async function get_user_infos(pubkeys) {
let pkeys = []
for (let pk of pubkeys) {
pkeys.push(PublicKey.parse(pk))
}
let profiles = []
let client = store.state.client
const profile_filter = new Filter().kind(0).authors(pkeys)
let evts = await client.getEventsOf([profile_filter], Duration.fromSecs(10))
for (const entry of evts) {
try {
let contentjson = JSON.parse(entry.content)
//console.log(contentjson)
profiles.push({profile: contentjson, author: entry.author.toHex(), createdAt: entry.createdAt});
} catch (error) {
console.log("error")
}
export async function get_reactions(ids){
let reactions = []
let jsonentry = {}
for (let id of ids){
reactions.push({
id: id.toHex(),
amount: 0,
ReactedbyUser: false,})
}
}
let client = store.state.client
const zap_filter = new Filter().kind(7).events(ids)
let evts = await client.getEventsOf([zap_filter], Duration.fromSecs(10))
return profiles
for (const entry of evts){
try{
//let contentjson = JSON.parse(entry.content)
}
for (let tag of entry.tags){
export async function get_event_reactions(ids) {
let zapsandreactions = []
if (tag.asVec()[0] === "e") {
console.log(entry.pubkey )
if(entry.pubkey === localStorage.getItem("nostr-key")){
reactions.find(x=> x.id === tag.asVec()[1]).ReactedbyUser = true
for (let id of ids) {
zapsandreactions.push({
id: id.toHex(),
amount: 0,
reactions: 0,
reposts: 0,
zappedbyUser: false,
reactedbyUser: false,
repostedbyUser: false,
})
}
let client = store.state.client
const zap_filter = new Filter().kinds([9735, 6, 7]).events(ids)
let evts = await client.getEventsOf([zap_filter], Duration.fromSecs(10))
for (const entry of evts) {
try {
//let contentjson = JSON.parse(entry.content)
if (entry.kind === 9735) {
for (let tag of entry.tags) {
if (tag.asVec()[0] === "description") {
let request = JSON.parse(tag.asVec()[1])
let etag = ""
let amount = 0
for (let tg of request.tags) {
if (tg[0] === "amount") {
amount = parseInt(tg[1])
}
if (tg[0] === "e") {
etag = tg[1]
//console.log(request.pubkey)
if (request.pubkey === localStorage.getItem("nostr-key")) {
zapsandreactions.find(x => x.id === etag).zappedbyUser = true
}
reactions.find(x=> x.id === tag.asVec()[1]).amount += 1
}
}
//console.log(contentjson)
//zaps.push({profile: contentjson, author: entry.author.toHex(), createdAt: entry.createdAt});
}
catch(error){
console.log("error")
}
zapsandreactions.find(x => x.id === etag).amount += amount
}
}
} else if (entry.kind === 7) {
for (let tag of entry.tags) {
if (tag.asVec()[0] === "e") {
if (entry.author.toHex() === localStorage.getItem("nostr-key")) {
zapsandreactions.find(x => x.id === tag.asVec()[1]).reactedbyUser = true
}
zapsandreactions.find(x => x.id === tag.asVec()[1]).reactions += 1
}
}
console.log(reactions)
return reactions
} else if (entry.kind === 6) {
for (let tag of entry.tags) {
if (tag.asVec()[0] === "e") {
if (entry.author.toHex() === localStorage.getItem("nostr-key")) {
zapsandreactions.find(x => x.id === tag.asVec()[1]).repostedbyUser = true
}
zapsandreactions.find(x => x.id === tag.asVec()[1]).reposts += 1
}
}
}
//console.log(contentjson)
//zaps.push({profile: contentjson, author: entry.author.toHex(), createdAt: entry.createdAt});
} catch (error) {
//console.log(error)
}
}
//console.log(zapsandreactions)
return zapsandreactions
}
export async function get_reactions(ids) {
let reactions = []
let jsonentry = {}
for (let id of ids) {
reactions.push({
id: id.toHex(),
amount: 0,
ReactedbyUser: false,
})
}
let client = store.state.client
const zap_filter = new Filter().kind(7).events(ids)
let evts = await client.getEventsOf([zap_filter], Duration.fromSecs(10))
for (const entry of evts) {
try {
//let contentjson = JSON.parse(entry.content)
for (let tag of entry.tags) {
if (tag.asVec()[0] === "e") {
console.log(entry.pubkey)
if (entry.pubkey === localStorage.getItem("nostr-key")) {
reactions.find(x => x.id === tag.asVec()[1]).ReactedbyUser = true
}
reactions.find(x => x.id === tag.asVec()[1]).amount += 1
}
}
//console.log(contentjson)
//zaps.push({profile: contentjson, author: entry.author.toHex(), createdAt: entry.createdAt});
} catch (error) {
console.log("error")
}
}
console.log(reactions)
return reactions
}
export const sleep = (ms) => {
@@ -302,38 +296,36 @@ export const sleep = (ms) => {
}
export async function copyinvoice(invoice){
export async function copyinvoice(invoice) {
window.open("lightning:" + invoice,"_blank")
await navigator.clipboard.writeText(invoice)
miniToastr.showMessage("", "Copied Invoice to clipboard", VueNotifications.types.info)
}
window.open("lightning:" + invoice, "_blank")
await navigator.clipboard.writeText(invoice)
miniToastr.showMessage("", "Copied Invoice to clipboard", VueNotifications.types.info)
}
export async function copyurl(url){
await navigator.clipboard.writeText(url)
miniToastr.showMessage("", "Copied link to clipboard", VueNotifications.types.info)
}
export async function copyurl(url) {
await navigator.clipboard.writeText(url)
miniToastr.showMessage("", "Copied link to clipboard", VueNotifications.types.info)
}
export async function parseandreplacenpubs(note){
export async function parseandreplacenpubs(note) {
note = note.replace("\n", " ")
const myArray = note.split(" ");
let finalnote = ""
for (let word in myArray){
for (let word in myArray) {
if(myArray[word].startsWith("nostr:npub")){
if (myArray[word].startsWith("nostr:npub")) {
console.log(myArray[word])
//console.log(pk.toBech32())
try{
console.log(myArray[word])
//console.log(pk.toBech32())
try {
let pk = PublicKey.parse(myArray[word].replace("nostr:", ""))
let profiles = await get_user_infos([pk.toHex()])
console.log(profiles)
//console.log(profiles[0].profile.nip05)
myArray[word] = profiles[0].profile.nip05 // replace with nip05 for now
}
catch{
} catch {
}
}
@@ -345,40 +337,35 @@ export async function parseandreplacenpubs(note){
}
export async function parseandreplacenpubsName(note){
export async function parseandreplacenpubsName(note) {
const myArray = note.split(/\n | \r | /);
let finalnote = ""
for (let word in myArray){
for (let word in myArray) {
if (myArray[word].startsWith("https")){
myArray[word] = myArray[word] + "\n"
}
if (myArray[word].startsWith("https")) {
myArray[word] = myArray[word] + "\n"
}
if(myArray[word].startsWith("nostr:note")){
myArray[word] = "<a class='purple' target=\"_blank\" href='https://njump.me/" + myArray[word].replace("nostr:", "")+ "'>" +myArray[word].replace("nostr:", "") + "</a> "
}
else if(myArray[word].startsWith("nostr:nevent")){
myArray[word] = "<a class='purple' target=\"_blank\" href='https://njump.me/" + myArray[word].replace("nostr:", "")+ "'>" +myArray[word].replace("nostr:", "") + "</a> "
}
else if(myArray[word].startsWith("nostr:npub")){
if (myArray[word].startsWith("nostr:note")) {
myArray[word] = "<a class='purple' target=\"_blank\" href='https://njump.me/" + myArray[word].replace("nostr:", "") + "'>" + myArray[word].replace("nostr:", "") + "</a> "
} else if (myArray[word].startsWith("nostr:nevent")) {
myArray[word] = "<a class='purple' target=\"_blank\" href='https://njump.me/" + myArray[word].replace("nostr:", "") + "'>" + myArray[word].replace("nostr:", "") + "</a> "
} else if (myArray[word].startsWith("nostr:npub")) {
//console.log(myArray[word])
//console.log(pk.toBech32())
try{
//console.log(pk.toBech32())
try {
let pk = PublicKey.parse(myArray[word].replace("nostr:", ""))
let profiles = await get_user_infos([pk.toHex()])
//console.log(profiles[0].profile.nip05)
// myArray[word] = "<a class='purple' target=\"_blank\" href=\"https://njump.com/" + myArray[word].replace("nostr:", "") +" \">" + profiles[0].profile.name + "</a> "
myArray[word] = "<a class='purple' target=\"_blank\" href='https://njump.me/" + myArray[word].replace("nostr:", "")+ "'>" + profiles[0].profile.name + "</a> "
// myArray[word] = "<a class='purple' target=\"_blank\" href=\"https://njump.com/" + myArray[word].replace("nostr:", "") +" \">" + profiles[0].profile.name + "</a> "
myArray[word] = "<a class='purple' target=\"_blank\" href='https://njump.me/" + myArray[word].replace("nostr:", "") + "'>" + profiles[0].profile.name + "</a> "
// profiles[0].profile.name // replace with nip05 for now
}
catch{
// profiles[0].profile.name // replace with nip05 for now
} catch {
}
}
@@ -389,7 +376,7 @@ export async function parseandreplacenpubsName(note){
return finalnote.trimEnd()
}
export async function fetchAsync (url) {
export async function fetchAsync(url) {
let response = await fetch(url);
let data = await response.json();
return data;
@@ -397,125 +384,111 @@ export async function fetchAsync (url) {
export async function dvmreactions(dvmid, authors) {
let reactions = {
positive: [],
negative: [],
positiveUser: false,
negativeUser: false
}
positive: [],
negative: [],
positiveUser: false,
negativeUser: false
}
let client = store.state.client
let client = store.state.client
let authorscheck = []
for (let author of authors){
try{
for (let author of authors) {
try {
authorscheck.push(PublicKey.parse(author))
}
catch{
} catch {
console.log("err" + author)
}
}
let reactionfilter = new Filter().kind(7).pubkey (dvmid).authors(authorscheck).since(Timestamp.fromSecs(Timestamp.now().asSecs() - 60*60*24*60)) // reactions by our followers in the last 2 months
let evts = await client.getEventsOf([reactionfilter], Duration.fromSecs(5))
let npubs = []
for (let evt of evts){
npubs.push(evt.author.toHex())
}
let reactionfilter = new Filter().kind(7).pubkey(dvmid).authors(authorscheck).since(Timestamp.fromSecs(Timestamp.now().asSecs() - 60 * 60 * 24 * 60)) // reactions by our followers in the last 2 months
let evts = await client.getEventsOf([reactionfilter], Duration.fromSecs(5))
let npubs = []
for (let evt of evts) {
npubs.push(evt.author.toHex())
}
let users = await get_user_infos(npubs)
console.log(users)
if (evts.length > 0){
for (let reaction of evts){
if (reaction.content === "👎"){
let profile = users.find(x => x.author === reaction.author.toHex() )
reactions.negative.push(profile)
/*if (reaction.author.toHex() === store.state.pubkey.toHex()){
reactions.negativeUser = true
}*/
}
else{
let profile = users.find(x => x.author === reaction.author.toHex() )
reactions.positive.push(profile)
// if (reaction.author.toHex() === store.state.pubkey.toHex()){
//reactions.positiveUser = true
// }
}
if (evts.length > 0) {
for (let reaction of evts) {
if (reaction.content === "👎") {
let profile = users.find(x => x.author === reaction.author.toHex())
reactions.negative.push(profile)
/*if (reaction.author.toHex() === store.state.pubkey.toHex()){
reactions.negativeUser = true
}*/
} else {
let profile = users.find(x => x.author === reaction.author.toHex())
reactions.positive.push(profile)
// if (reaction.author.toHex() === store.state.pubkey.toHex()){
//reactions.positiveUser = true
// }
}
}
}
return reactions
}
export async function hasActiveSubscription(pubkeystring, tiereventdtag, tierauthorid) {
console.log("Checking for subscription")
let client = store.state.client
let subscriptionstatus = {
isActive: false,
validUntil: 0,
subscriptionId: "",
expires: false
console.log("Checking for subscription")
let client = store.state.client
let subscriptionstatus = {
isActive: false,
validUntil: 0,
subscriptionId: "",
expires: false
}
let subscriptionfilter = new Filter().kind(7003).pubkey(PublicKey.parse(tierauthorid)).customTag(SingleLetterTag.uppercase(Alphabet.P), [pubkeystring]).limit(1)
let evts = await client.getEventsOf([subscriptionfilter], Duration.fromSecs(5))
if (evts.length > 0) {
console.log(evts[0].asJson())
let matchesdtag = false
for (let tag of evts[0].tags) {
if (tag.asVec()[0] === "valid") {
subscriptionstatus["validUntil"] = parseInt(tag.asVec()[2])
} else if (tag.asVec()[0] === "e") {
subscriptionstatus["subscriptionId"] = tag.asVec()[1]
} else if (tag.asVec()[0] === "tier") {
if (tag.asVec()[1] === tiereventdtag) {
matchesdtag = true
}
}
}
let subscriptionfilter = new Filter().kind(7003).pubkey(PublicKey.parse(tierauthorid)).customTag(SingleLetterTag.uppercase(Alphabet.P), [pubkeystring]).limit(1)
let evts = await client.getEventsOf([subscriptionfilter], Duration.fromSecs(5))
if (subscriptionstatus["validUntil"] > Timestamp.now().asSecs() && matchesdtag) {
subscriptionstatus["isActive"] = true
}
if (evts.length > 0){
console.log(evts[0].asJson())
let matchesdtag = false
for (let tag of evts[0].tags){
if (tag.asVec()[0] === "valid"){
subscriptionstatus["validUntil"] = parseInt(tag.asVec()[2])
}
else if (tag.asVec()[0] === "e"){
subscriptionstatus["subscriptionId"] = tag.asVec()[1]
}
else if (tag.asVec()[0] === "tier"){
if (tag.asVec()[1] === tiereventdtag)
{
matchesdtag = true
}
}
if (subscriptionstatus["isActive"] === true) {
const filter = new Filter().kind(7002).author(PublicKey.parse(pubkeystring)).pubkey(PublicKey.parse(tierauthorid)).event(EventId.parse(subscriptionstatus["subscriptionId"])).limit(1) // get latest with these conditons # customTag(SingleLetterTag.lowercase(Alphabet.A), [eventid])
let cancelevts = await client.getEventsOf([filter], Duration.fromSecs(5))
if (cancelevts.length > 0) {
if (cancelevts[0].createdAt.asSecs() > evts[0].createdAt.asSecs()) {
subscriptionstatus["expires"] = true
}
if (subscriptionstatus["validUntil"] > Timestamp.now().asSecs() && matchesdtag){
subscriptionstatus["isActive"] = true
}
if( subscriptionstatus["isActive"] === true){
const filter = new Filter().kind(7002).author(PublicKey.parse(pubkeystring)).pubkey(PublicKey.parse(tierauthorid)).event(EventId.parse(subscriptionstatus["subscriptionId"])).limit(1) // get latest with these conditons # customTag(SingleLetterTag.lowercase(Alphabet.A), [eventid])
let cancelevts = await client.getEventsOf([filter], Duration.fromSecs(5))
if (cancelevts.length > 0) {
if (cancelevts[0].createdAt.asSecs() > evts[0].createdAt.asSecs()) {
subscriptionstatus["expires"] = true
}
}
}
return subscriptionstatus
}
}
return subscriptionstatus
return subscriptionstatus
}
return subscriptionstatus
}
</script>
<template>

View File

@@ -11,133 +11,122 @@ import miniToastr from "mini-toastr";
import VueNotifications from "vue-notifications";
async function zap_nwc(invoice) {
async function zap_nwc(invoice){
const nwc = new webln.NostrWebLNProvider({
nostrWalletConnectUrl: loadNWCUrl(),
}); // loadNWCUrl is some function to get the NWC URL from some (encrypted) storage
const nwc = new webln.NostrWebLNProvider({
nostrWalletConnectUrl: loadNWCUrl(),
}); // loadNWCUrl is some function to get the NWC URL from some (encrypted) storage
// connect to the relay
await nwc.enable();
// connect to the relay
await nwc.enable();
// now you can send payments by passing in the invoice
try{
const response = await nwc.sendPayment(invoice);
console.log(response)
return true
}
catch (error){
// now you can send payments by passing in the invoice
try {
const response = await nwc.sendPayment(invoice);
console.log(response)
return true
} catch (error) {
miniToastr.showMessage(error, "This didn't work", VueNotifications.types.error)
console.log(error)
return false
return false
}
}
}
export function loadNWCObject() {
if (localStorage.getItem("nwc")){
if(JSON.parse(localStorage.getItem("nwc")).nwcUrl.startsWith("nostr+walletconnect://")){
return JSON.parse(localStorage.getItem("nwc"))
}
if (localStorage.getItem("nwc")) {
if (JSON.parse(localStorage.getItem("nwc")).nwcUrl.startsWith("nostr+walletconnect://")) {
return JSON.parse(localStorage.getItem("nwc"))
}
}
return null
}
return null
}
function loadNWCUrl() {
if (localStorage.getItem("nwc")){
if(JSON.parse(localStorage.getItem("nwc")).nwcUrl.startsWith("nostr+walletconnect://")){
return JSON.parse(localStorage.getItem("nwc")).nwcUrl
}
if (localStorage.getItem("nwc")) {
if (JSON.parse(localStorage.getItem("nwc")).nwcUrl.startsWith("nostr+walletconnect://")) {
return JSON.parse(localStorage.getItem("nwc")).nwcUrl
}
}
return ""
}
return ""
}
export async function zap(invoice){
export async function zap(invoice) {
let nwcstring = loadNWCUrl()
if (nwcstring.startsWith("nostr+walletconnect://"))
{
if (nwcstring.startsWith("nostr+walletconnect://")) {
return zap_nwc(invoice)
}
else{
} else {
let webln;
//this.dvmpaymentaddr = `https://chart.googleapis.com/chart?cht=qr&chl=${invoice}&chs=250x250&chld=M|0`;
//this.dvmpaymentaddr = `https://chart.googleapis.com/chart?cht=qr&chl=${invoice}&chs=250x250&chld=M|0`;
try {
webln = await requestProvider();
} catch (err) {
await copyinvoice(invoice)
}
if (webln) {
try{
let response = await webln.sendPayment(invoice)
return true
}
catch(err){
console.log(err)
await copyinvoice(invoice)
}
}
}
return false
}
export async function zap_lud16(lud16, eventid, authorid){
if(lud16 !== null && lud16 !== ""){
let invoice = await zaprequest(lud16, 21 , "with love from noogle.lol", eventid, authorid, store.state.relays)
let nwcstring = loadNWCUrl()
if (nwcstring.startsWith("nostr+walletconnect://"))
{
return zap_nwc(invoice)
}
else{
let webln;
try {
webln = await requestProvider();
} catch (err) {
if (invoice === null){
invoice = await createBolt11Lud16(lud16, 21)
}
await copyinvoice(invoice)
}
if (webln) {
try {
let response = await webln.sendPayment(invoice)
if (response.preimage != null && response.preimage !== "") {
return true
}
}
return true
} catch (err) {
console.log(err)
await copyinvoice(invoice)
catch(err){
}
}
}
return false
}
export async function zap_lud16(lud16, eventid, authorid) {
if (lud16 !== null && lud16 !== "") {
let invoice = await zaprequest(lud16, 21, "with love from noogle.lol", eventid, authorid, store.state.relays)
let nwcstring = loadNWCUrl()
if (nwcstring.startsWith("nostr+walletconnect://")) {
return zap_nwc(invoice)
} else {
let webln;
try {
webln = await requestProvider();
} catch (err) {
if (invoice === null) {
invoice = await createBolt11Lud16(lud16, 21)
}
await copyinvoice(invoice)
}
if (webln) {
try {
let response = await webln.sendPayment(invoice)
if (response.preimage != null && response.preimage !== "") {
return true
}
} catch (err) {
console.log(err)
await copyinvoice(invoice)
}
}
}
}
}
return false
}
return false
}
}
export async function zaprequest(lud16, amount, content, zapped_evt_id, zapped_usr_id, relay_list){
let url = ""
export async function zaprequest(lud16, amount, content, zapped_evt_id, zapped_usr_id, relay_list) {
let url = ""
console.log(lud16)
console.log(zapped_evt_id)
@@ -147,87 +136,81 @@ export async function zap_lud16(lud16, eventid, authorid){
let zapped_event_id = EventId.parse(zapped_evt_id).toHex()
if (lud16 !== "" && lud16.toString().includes('@')){
if (lud16 !== "" && lud16.toString().includes('@')) {
url = `https://${lud16.split('@')[1]}/.well-known/lnurlp/${lud16.split('@')[0]}`;
console.log(url)
console.log(url)
} else {
return null
}
try {
let ob = await fetchAsync(url)
let callback = ob["callback"]
console.log(callback)
const urlBytes = new TextEncoder().encode(url);
const encoded_lnurl = bech32.encode('lnurl', bech32.toWords(urlBytes), 1023);
const amount_tag = ['amount', (amount * 1000).toString()];
let relays = ['relays']
relays.push.apply(relays, relay_list)
//let relays_tag = Tag.parse(relays);
const lnurl_tag = ['lnurl', encoded_lnurl];
let tags = []
let p_tag = ['p', zapped_user_id]
if (zapped_event_id !== null) {
let e_tag = ['e', zapped_event_id]
tags = [amount_tag, relays, p_tag, e_tag, lnurl_tag]
} else {
tags = [amount_tag, relays, p_tag, lnurl_tag]
}
else{
return null
/*if (zaptype === "private") {
const key_str = keys.secret_key().to_hex() + zapped_event.id().to_hex() + zapped_event.created_at().as_secs().toString();
const encryption_key = sha256(key_str).toString('hex');
const zap_request = new EventBuilder(9733, content, [p_tag, e_tag]).to_event(keys).as_json();
keys = Keys.parse(encryption_key);
const encrypted_content = enrypt_private_zap_message(zap_request, keys.secret_key(), zapped_event.author());
const anon_tag = Tag.parse(['anon', encrypted_content]);
tags.push(anon_tag);
content = "";
} */
let signer = store.state.signer
let zap_request = ""
let tags_t = []
for (let tag of tags) {
tags_t.push(Tag.parse(tag))
}
try{
let ob = await fetchAsync(url)
let callback = ob["callback"]
console.log(callback)
let noteevent = new EventBuilder(9734, content, tags_t).toUnsignedEvent(store.state.pubkey)
let signedEvent = await signer.signEvent(noteevent)
zap_request = signedEvent.asJson()
const urlBytes = new TextEncoder().encode(url);
const encoded_lnurl = bech32.encode('lnurl', bech32.toWords(urlBytes), 1023);
try {
const queryString = `amount=${(amount * 1000).toString()}&nostr=${encodeURIComponent(zap_request)}&lnurl=${encoded_lnurl}`;
const amount_tag = ['amount', (amount * 1000).toString()];
let relays = ['relays']
relays.push.apply(relays, relay_list)
//let relays_tag = Tag.parse(relays);
const lnurl_tag = ['lnurl', encoded_lnurl];
let tags = []
let p_tag = ['p', zapped_user_id]
if (zapped_event_id !== null){
let e_tag = ['e', zapped_event_id]
tags = [amount_tag, relays, p_tag, e_tag, lnurl_tag]
}
else{
tags = [amount_tag, relays, p_tag, lnurl_tag]
}
/*if (zaptype === "private") {
const key_str = keys.secret_key().to_hex() + zapped_event.id().to_hex() + zapped_event.created_at().as_secs().toString();
const encryption_key = sha256(key_str).toString('hex');
const zap_request = new EventBuilder(9733, content, [p_tag, e_tag]).to_event(keys).as_json();
keys = Keys.parse(encryption_key);
const encrypted_content = enrypt_private_zap_message(zap_request, keys.secret_key(), zapped_event.author());
const anon_tag = Tag.parse(['anon', encrypted_content]);
tags.push(anon_tag);
content = "";
} */
let signer = store.state.signer
let zap_request = ""
let tags_t = []
for (let tag of tags){
tags_t.push(Tag.parse(tag))
}
let noteevent = new EventBuilder(9734, content, tags_t).toUnsignedEvent(store.state.pubkey)
let signedEvent = await signer.signEvent(noteevent)
zap_request = signedEvent.asJson()
try{
const queryString = `amount=${(amount * 1000).toString()}&nostr=${encodeURIComponent(zap_request)}&lnurl=${encoded_lnurl}`;
console.log(queryString)
let ob = await fetchAsync(`${callback}?${queryString}`)
return ob["pr"]
}
catch(e){
console.log(e)
}
console.log(queryString)
let ob = await fetchAsync(`${callback}?${queryString}`)
return ob["pr"]
} catch (e) {
console.log(e)
}
catch(error){
} catch (error) {
console.log("ZAP REQUEST: " + error)
console.log("ZAP REQUEST: " + error)
}
return null
return null
}
export async function createBolt11Lud16(lud16, amount) {
if (lud16 === null || lud16 === "") {
return null;

View File

@@ -1,18 +1,18 @@
const Regex_Url_Str = "^https?:\/\/(?:.*\/)?[^\/.]+$" // domain name
const Regex_Url_Img = "(https?:\\/\\/.*\\.(?:png|jpg|jpeg|webp|gif))" // domain name
const Regex_Url_Video = "(https?:\\/\\/.*\\.(?:mp4|mov|avi))" // domain name
const Regex_Urlw_Str = "(https:\\/\\/)"+ "((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,})+[\\/]{0,1}" // domain name
const Regex_Urlw_Str = "(https:\\/\\/)" + "((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,})+[\\/]{0,1}" // domain name
;
const Regex_Nip05_Str= "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\\])"
const Regex_Nip05_Str = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\\])"
const StringUtil = {
isValidUrl: (str: string): boolean => new RegExp(Regex_Url_Str, "i").test(str),
parseHyperlinks: (str: string): string => str.replace(new RegExp(Regex_Urlw_Str, "gim"), "<a class='purple' target=\"_blank\" rel=\"noreferrer\" href=\"$&\">$&</a>").replace(new RegExp(Regex_Nip05_Str, "gim"), "<a class='purple' target=\"_blank\" rel=\"noreferrer\" href=\"https://njump.me/$&\">$&</a> "),
parseImages: (str: string): string => str.toLowerCase().includes('nsfw') || str.toLowerCase().includes('lingerie') || str.toLowerCase().includes('sex') || str.toLowerCase().includes('porn') ? str.replace(" http", "\nhttp").replace(new RegExp(Regex_Url_Img, "gim"), "<details><summary class=\"collapse-title \"><div class=\"btn\">NSFW Show/Hide Results</div></summary><img src='$&'/></div></details> ").replace(new RegExp(Regex_Url_Video, "gim"), "<details><summary class=\"collapse-title \"><div class=\"btn\">NSFW Show/Hide Results</div><video controls muted autoplay src=\"$&\"></video></summary></details>").replace(new RegExp(Regex_Url_Str, "gim"), "<a class='purple' target=\"_blank\" rel=\"noreferrer\" href=\"$&\">$&</a> ") : str.replace(" http", "\nhttp").replace(new RegExp(Regex_Url_Img, "gim"), "<img src='$&'/> ").replace(new RegExp(Regex_Url_Video, "gim"), "<video controls muted autoplay src=\"$&\"></video> ").replace(new RegExp(Regex_Url_Str, "gim"), "<a class='purple' target=\"_blank\" rel=\"noreferrer\" href=\"$&\">$&</a> "),
isValidUrl: (str: string): boolean => new RegExp(Regex_Url_Str, "i").test(str),
parseHyperlinks: (str: string): string => str.replace(new RegExp(Regex_Urlw_Str, "gim"), "<a class='purple' target=\"_blank\" rel=\"noreferrer\" href=\"$&\">$&</a>").replace(new RegExp(Regex_Nip05_Str, "gim"), "<a class='purple' target=\"_blank\" rel=\"noreferrer\" href=\"https://njump.me/$&\">$&</a> "),
parseImages: (str: string): string => str.toLowerCase().includes('nsfw') || str.toLowerCase().includes('lingerie') || str.toLowerCase().includes('sex') || str.toLowerCase().includes('porn') ? str.replace(" http", "\nhttp").replace(new RegExp(Regex_Url_Img, "gim"), "<details><summary class=\"collapse-title \"><div class=\"btn\">NSFW Show/Hide Results</div></summary><img src='$&'/></div></details> ").replace(new RegExp(Regex_Url_Video, "gim"), "<details><summary class=\"collapse-title \"><div class=\"btn\">NSFW Show/Hide Results</div><video controls muted autoplay src=\"$&\"></video></summary></details>").replace(new RegExp(Regex_Url_Str, "gim"), "<a class='purple' target=\"_blank\" rel=\"noreferrer\" href=\"$&\">$&</a> ") : str.replace(" http", "\nhttp").replace(new RegExp(Regex_Url_Img, "gim"), "<img src='$&'/> ").replace(new RegExp(Regex_Url_Video, "gim"), "<video controls muted autoplay src=\"$&\"></video> ").replace(new RegExp(Regex_Url_Str, "gim"), "<a class='purple' target=\"_blank\" rel=\"noreferrer\" href=\"$&\">$&</a> "),
//parseImages: (str: string): string => str.replace(" http", "<br>http") //.replace("\n", " ").replace(new RegExp(Regex_Url_Img, "gim"), "<img src='$&'/> ")
//parseImages: (str: string): string => str.replace(" http", "<br>http") //.replace("\n", " ").replace(new RegExp(Regex_Url_Img, "gim"), "<img src='$&'/> ")
};

View File

@@ -1,7 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<svg fill="currentColor" height="20" width="20" xmlns="http://www.w3.org/2000/svg">
<path
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
/>
</svg>
</template>

View File

@@ -1,7 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
<svg fill="currentColor" height="17" width="20" xmlns="http://www.w3.org/2000/svg">
<path
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
/>
</svg>
</template>

View File

@@ -1,7 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
<svg fill="currentColor" height="20" width="18" xmlns="http://www.w3.org/2000/svg">
<path
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
/>
</svg>
</template>

View File

@@ -1,7 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<svg fill="currentColor" height="20" width="20" xmlns="http://www.w3.org/2000/svg">
<path
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
/>
</svg>
</template>

View File

@@ -1,19 +1,18 @@
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--mdi"
width="24"
height="24"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 24 24"
aria-hidden="true"
class="iconify iconify--mdi"
height="24"
preserveAspectRatio="xMidYMid meet"
role="img"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
fill="currentColor"
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
fill="currentColor"
></path>
</svg>
</template>

View File

@@ -1,52 +1,51 @@
<script setup>
import Login from "@/components/Login.vue";
import {isVisible} from "bootstrap/js/src/util/index.js";
</script>
<template>
<div className="navbar bg-base-100 scroll-auto">
<div className="flex-none">
<div className="flex-none">
</div>
<div className="flex-1">
<div class="scroll">
<router-link class="menu" to="/">Search</router-link>
<router-link class="menu" to="/discover">Discover</router-link>
<router-link class="menu" to="/filter">Filter</router-link>
<router-link class="menu" to="/image">Create</router-link>
<router-link class="menu" to="/ai">AI</router-link>
<router-link class="menu" to="/nip89">DVMs</router-link>
</div>
<div className="flex-1">
<div class="scroll">
<router-link class="menu" to="/">Search</router-link>
<router-link class="menu" to="/discover">Discover</router-link>
<router-link class="menu" to="/filter">Filter</router-link>
<router-link class="menu" to="/image">Create</router-link>
<router-link class="menu" to="/ai">AI</router-link>
<router-link class="menu" to="/nip89">DVMs</router-link>
</div>
</div>
<Login/>
</div>
<Login/>
</div>
<div class="three-column-layout">
<header>
<!-- <AppLogo />-->
<!-- <AppLogo />-->
</header>
<main >
<router-view />
<main>
<router-view/>
<slot/>
</main>
<aside>
<slot name="aside" />
<slot name="aside"/>
</aside>
<footer>
<!--<Donate style="margin-top: 4px"/> -->
<footer>
<!--<Donate style="margin-top: 4px"/> -->
</footer>
</div>
</div>
</template>
<style scoped lang="scss">
<style lang="scss" scoped>
.three-column-layout {
display: grid;
grid-template-areas:
@@ -55,20 +54,21 @@ import {isVisible} from "bootstrap/js/src/util/index.js";
"aside"
"footer";
div.scroll {
margin: 4px;
padding: 4px;
background-color: #08c708;
width: 300px;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
}
div.scroll {
margin: 4px;
padding: 4px;
background-color: #08c708;
width: 300px;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
}
header {
grid-area: header;
margin-top: 30px;
}
main {
grid-area: main;
@@ -77,10 +77,11 @@ import {isVisible} from "bootstrap/js/src/util/index.js";
padding: 20px;
}
footer{
footer {
position: fixed;
bottom:0;
bottom: 0;
background: rgba(0, 0, 0, 0);;
grid-area: footer;
width: 100vw;
@@ -89,6 +90,7 @@ import {isVisible} from "bootstrap/js/src/util/index.js";
z-index: 10;
text-align: center;
}
aside {
grid-area: aside;
margin-top: 10px;
@@ -96,18 +98,16 @@ import {isVisible} from "bootstrap/js/src/util/index.js";
}
.router-link-exact-active{
color: rgba(255, 255, 255, 0.87);
}
.router-link-exact-active {
color: rgba(255, 255, 255, 0.87);
}
.v-Button {
@apply bg-black hover:bg-nostr focus:ring-nostr mb-2 inline-flex flex-none items-center rounded-lg border border-nostr 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: 44px;
}
.v-Button {
@apply bg-black hover:bg-nostr focus:ring-nostr mb-2 inline-flex flex-none items-center rounded-lg border border-nostr 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: 44px;
}
@media (min-width: 768px) {

View File

@@ -1,5 +1,5 @@
//import './assets/main.css'
import { createApp } from 'vue'
import {createApp} from 'vue'
import App from './App.vue'
import store from './store';
@@ -13,31 +13,25 @@ import VueDatePicker from '@vuepic/vue-datepicker';
import '@vuepic/vue-datepicker/dist/main.css'
//This is all for notifications
import VueNotifications from "vue-notifications";
import miniToastr from 'mini-toastr'
import { registerSW } from 'virtual:pwa-register'
import {registerSW} from 'virtual:pwa-register'
registerSW({ immediate: true })
registerSW({immediate: true})
miniToastr.init()
function toast ({title, message, type, timeout, cb}) {
return miniToastr[type](message, title, timeout, cb)
function toast({title, message, type, timeout, cb}) {
return miniToastr[type](message, title, timeout, cb)
}
const options = {
success: toast,
error: toast,
info: toast,
warn: toast
success: toast,
error: toast,
info: toast,
warn: toast
}
//This is all for notifications end

View File

@@ -1,24 +1,23 @@
import { createWebHistory, createRouter } from "vue-router";
import {createRouter, createWebHistory} from "vue-router";
const routes = [
{ path: "/", component: () => import("@/components/Home.vue") },
{ path: "/about", component: () => import("@/components/AboutPage.vue") },
{ path: "/donate", component: () => import("@/components/Donate.vue") },
{ path: "/nip89", component: () => import("@/components/Nip89view.vue") },
{ path: "/image", component: () => import("@/components/Image.vue") },
{ path: "/filter", component: () => import("@/components/FilterGeneration.vue") },
{ path: "/ai", component: () => import("@/components/ChatGeneration.vue") },
{path: "/", component: () => import("@/components/Home.vue")},
{path: "/about", component: () => import("@/components/AboutPage.vue")},
{path: "/donate", component: () => import("@/components/Donate.vue")},
{path: "/nip89", component: () => import("@/components/Nip89view.vue")},
{path: "/image", component: () => import("@/components/Image.vue")},
{path: "/filter", component: () => import("@/components/FilterGeneration.vue")},
{path: "/ai", component: () => import("@/components/ChatGeneration.vue")},
{ path: "/discover", component: () => import("@/components/RecommendationGeneration.vue") },
{ path: "/article/:id", component: () => import("@/components/Home.vue") },
{ path: '/:pathMatch(.*)*', component: () => import("@/components/Home.vue") },
{path: "/discover", component: () => import("@/components/RecommendationGeneration.vue")},
{path: "/article/:id", component: () => import("@/components/Home.vue")},
{path: '/:pathMatch(.*)*', component: () => import("@/components/Home.vue")},
];
const router = createRouter({
history: createWebHistory(),
routes,
history: createWebHistory(),
routes,
});
export default router;

View File

@@ -2,157 +2,155 @@ import {createStore} from "vuex";
import {Client, NostrSigner, PublicKey} from "@rust-nostr/nostr-sdk";
const store = createStore({
state () {
return {
count: 0,
client: Client,
signer: NostrSigner,
dbclient: Client,
pubkey: PublicKey,
followings: [],
contacts: [],
mutes: [],
nooglekey: import.meta.env.VITE_NOOGLE_PK,
subscription_verifier_pubkey: import.meta.env.VITE_SUBSCRIPTIPON_VERIFIER_PUBKEY,
requestidSearch: String,
requestidSearch2: String,
requestidSearchProfile: String,
requestidImage: [],
requestidRecommendation: [],
requestidChat: [],
requestidSummarization: [],
requestidFilter: [],
imagedvmreplies: [],
chatdvmreplies: [],
nip89dvms: [],
activesearchdvms: [],
recommendationdvms: [],
filterdvms: [],
summarizationdvms: [],
results: [],
profile_results: [],
relays: ["wss://relay.primal.net",
"wss://nostr.mom", "wss://nostr.oxtr.dev",
"wss://relay.nostr.net"
],
state() {
return {
count: 0,
client: Client,
signer: NostrSigner,
dbclient: Client,
pubkey: PublicKey,
followings: [],
contacts: [],
mutes: [],
nooglekey: import.meta.env.VITE_NOOGLE_PK,
subscription_verifier_pubkey: import.meta.env.VITE_SUBSCRIPTIPON_VERIFIER_PUBKEY,
requestidSearch: String,
requestidSearch2: String,
requestidSearchProfile: String,
requestidImage: [],
requestidRecommendation: [],
requestidChat: [],
requestidSummarization: [],
requestidFilter: [],
imagedvmreplies: [],
chatdvmreplies: [],
nip89dvms: [],
activesearchdvms: [],
recommendationdvms: [],
filterdvms: [],
summarizationdvms: [],
results: [],
profile_results: [],
relays: ["wss://relay.primal.net",
"wss://nostr.mom", "wss://nostr.oxtr.dev",
"wss://relay.nostr.net"
],
}
},
mutations: {
increment(state) {
state.count++
},
set_client(state, client) {
state.client = client
},
set_dbclient(state, dbclient) {
state.dbclient = dbclient
},
set_signer(state, signer) {
state.signer = signer
},
set_pubkey(state, pubkey) {
state.pubkey = pubkey
},
set_followings(state, items) {
state.followings.length = 0
state.followings.push.apply(state.followings, items)
},
set_contacts(state, items) {
state.contacts.length = 0
state.contacts.push.apply(state.contacts, items)
},
set_mutes(state, items) {
state.mutes.length = 0
state.mutes.push.apply(state.mutes, items)
},
set_nip89dvms(state, nip89dvms) {
state.nip89dvms.length = 0
//console.log(nip89dvms)
let nip89dvmssorted = nip89dvms.sort(function (a, b) {
return a.createdAt - b.createdAt;
});
//console.log(nip89dvmssorted)
state.nip89dvms.push.apply(state.nip89dvms, nip89dvmssorted)
},
set_current_request_id_search(state, requestid) {
state.requestidSearch = String(requestid)
},
set_current_request_id_search2(state, requestid2) {
state.requestidSearch2 = String(requestid2)
},
set_current_request_id_summarization(state, requestid) {
state.requestidSummarization.length = 0
state.requestidSummarization.push.apply(state.requestidSummarization, requestid)
},
set_current_request_id_filter(state, requestid) {
state.requestidFilter.length = 0
state.requestidFilter.push.apply(state.requestidFilter, requestid)
},
set_current_request_profile_id_search(state, requestid) {
state.requestidSearchProfile = String(requestid)
},
set_active_search_dvms(state, dvms) {
state.activesearchdvms.length = 0
state.activesearchdvms.push.apply(state.activesearchdvms, dvms)
},
set_recommendation_dvms(state, dvms) {
state.recommendationdvms.length = 0
state.recommendationdvms.push.apply(state.recommendationdvms, dvms)
},
set_filter_dvms(state, dvms) {
state.filterdvms.length = 0
state.filterdvms.push.apply(state.filterdvms, dvms)
},
set_summarization_dvms(state, dvms) {
state.summarizationdvms.length = 0
state.summarizationdvms.push.apply(state.summarizationdvms, dvms)
},
set_search_results_profiles(state, items) {
state.profile_results.length = 0
state.profile_results.push.apply(state.profile_results, items)
},
set_current_request_id_image(state, requestid) {
state.requestidImage.length = 0
state.requestidImage.push.apply(state.requestidImage, requestid)
},
set_current_request_id_recommendation(state, requestid) {
state.requestidRecommendation.length = 0
state.requestidRecommendation.push.apply(state.requestidRecommendation, requestid)
},
set_current_request_id_chat(state, requestid) {
state.requestidChat.length = 0
state.requestidChat.push.apply(state.requestidChat, requestid)
},
set_search_results(state, results) {
state.results.length = 0
state.results.push.apply(state.results, results)
},
set_imagedvm_results(state, results) {
state.imagedvmreplies.length = 0
state.imagedvmreplies.push.apply(state.imagedvmreplies, results)
},
set_chat_dvm_results(state, results) {
state.chatdvmreplies.length = 0
state.chatdvmreplies.push.apply(state.chatdvmreplies, results)
},
}
},
mutations: {
increment (state) {
state.count++
},
set_client (state, client) {
state.client = client
},
set_dbclient (state, dbclient) {
state.dbclient = dbclient
},
set_signer (state, signer) {
state.signer = signer
},
set_pubkey(state, pubkey) {
state.pubkey = pubkey
},
set_followings(state, items) {
state.followings.length = 0
state.followings.push.apply(state.followings, items)
},
set_contacts(state, items) {
state.contacts.length = 0
state.contacts.push.apply(state.contacts, items)
},
set_mutes(state, items) {
state.mutes.length = 0
state.mutes.push.apply(state.mutes, items)
},
set_nip89dvms(state, nip89dvms) {
state.nip89dvms.length = 0
//console.log(nip89dvms)
let nip89dvmssorted = nip89dvms.sort(function(a, b) {
return a.createdAt - b.createdAt;
});
//console.log(nip89dvmssorted)
state.nip89dvms.push.apply(state.nip89dvms, nip89dvmssorted)
},
set_current_request_id_search(state, requestid){
state.requestidSearch = String(requestid)
},
set_current_request_id_search2(state, requestid2){
state.requestidSearch2 = String(requestid2)
},
set_current_request_id_summarization(state, requestid){
state.requestidSummarization.length = 0
state.requestidSummarization.push.apply(state.requestidSummarization, requestid)
},
set_current_request_id_filter(state, requestid){
state.requestidFilter.length = 0
state.requestidFilter.push.apply(state.requestidFilter, requestid)
},
set_current_request_profile_id_search(state, requestid){
state.requestidSearchProfile = String(requestid)
},
set_active_search_dvms(state, dvms) {
state.activesearchdvms.length = 0
state.activesearchdvms.push.apply(state.activesearchdvms, dvms)
},
set_recommendation_dvms(state, dvms) {
state.recommendationdvms.length = 0
state.recommendationdvms.push.apply(state.recommendationdvms, dvms)
},
set_filter_dvms(state, dvms) {
state.filterdvms.length = 0
state.filterdvms.push.apply(state.filterdvms, dvms)
},
set_summarization_dvms(state, dvms) {
state.summarizationdvms.length = 0
state.summarizationdvms.push.apply(state.summarizationdvms, dvms)
},
set_search_results_profiles(state, items){
state.profile_results.length = 0
state.profile_results.push.apply(state.profile_results, items)
},
set_current_request_id_image(state, requestid){
state.requestidImage.length = 0
state.requestidImage.push.apply(state.requestidImage, requestid)
},
set_current_request_id_recommendation(state, requestid){
state.requestidRecommendation.length = 0
state.requestidRecommendation.push.apply(state.requestidRecommendation, requestid)
},
set_current_request_id_chat(state, requestid){
state.requestidChat.length = 0
state.requestidChat.push.apply(state.requestidChat, requestid)
},
set_search_results(state, results){
state.results.length = 0
state.results.push.apply(state.results, results)
},
set_imagedvm_results(state, results){
state.imagedvmreplies.length = 0
state.imagedvmreplies.push.apply(state.imagedvmreplies, results)
},
set_chat_dvm_results(state, results){
state.chatdvmreplies.length = 0
state.chatdvmreplies.push.apply(state.chatdvmreplies, results)
},
}
})
export default store;

View File

@@ -2,21 +2,21 @@
export default {
darkMode: "class",
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
],
theme: {
extend: {
colors:{
'nostr': '#6d52f1',
'nostr2': '#8453f1',
extend: {
colors: {
'nostr': '#6d52f1',
'nostr2': '#8453f1',
}
}
},
},
},
plugins: [require("daisyui")],
plugins: [require("daisyui")],
}

View File

@@ -1,16 +1,24 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"include": [
"env.d.ts",
"src/**/*",
"src/**/*.vue"
],
"exclude": [
"src/**/__tests__/*"
],
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
"@/*": [
"./src/*"
]
},
"allowJs": true,
"noImplicitAny": false,
"verbatimModuleSyntax":false,
"verbatimModuleSyntax": false
}
}

View File

@@ -11,9 +11,10 @@
"composite": true,
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
"types": [
"node"
]
}
}

View File

@@ -1,43 +1,43 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import {fileURLToPath, URL} from 'node:url'
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
import {VitePWA} from 'vite-plugin-pwa'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
VitePWA({
plugins: [
vue(),
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: 'Noogle',
short_name: 'Noogle',
description: 'Other Stuff on Nostr',
theme_color: '#ffffff',
icons: [
{
src: 'pwa-192x192.png',
sizes: '192x192',
type: 'image/png'
},
{
src: 'pwa-512x512.png',
sizes: '512x512',
type: 'image/png'
}
]
},
devOptions: {
enabled: true,
},
workbox: {
maximumFileSizeToCacheInBytes: 8000000,
},
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
registerType: 'autoUpdate',
manifest: {
name: 'Noogle',
short_name: 'Noogle',
description: 'Other Stuff on Nostr',
theme_color: '#ffffff',
icons: [
{
src: 'pwa-192x192.png',
sizes: '192x192',
type: 'image/png'
},
{
src: 'pwa-512x512.png',
sizes: '512x512',
type: 'image/png'
}
]
},
devOptions: {
enabled: true,
},
workbox: {
maximumFileSizeToCacheInBytes: 8000000,
},
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
}
})