Skip to content

Commit

Permalink
Manual verification to Slack
Browse files Browse the repository at this point in the history
  • Loading branch information
dcadenas committed Mar 27, 2024
1 parent bf9f5e7 commit c0ba361
Show file tree
Hide file tree
Showing 4 changed files with 398 additions and 148 deletions.
45 changes: 36 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
'use strict';
"use strict";

import functions from '@google-cloud/functions-framework';
import openAIClientPool from './src/lib/openAIClientPool.js';
import RateLimiting from './src/lib/rateLimiting.js';
import Nostr, { REPORT_KIND } from './src/lib/nostr.js';
import DuplicationHandling from './src/lib/duplicationHandling.js';
import functions from "@google-cloud/functions-framework";
import openAIClientPool from "./src/lib/openAIClientPool.js";
import RateLimiting from "./src/lib/rateLimiting.js";
import Nostr, { REPORT_KIND } from "./src/lib/nostr.js";
import Slack from "./src/lib/slack.js";
import DuplicationHandling from "./src/lib/duplicationHandling.js";

functions.cloudEvent('nostrEventsPubSub', async (cloudEvent) => {
const nostrEvent = Nostr.getVerifiedEvent(cloudEvent.data.message.data);
functions.cloudEvent("nostrEventsPubSub", async (cloudEvent) => {
//The nostr event can either directly be the object or be encapsulated within
//a nostrEvent key, if present. A nostrEvent key indicates a user-initiated
//manual report request originating from the reportinator server. These events
//require Slack-based verification, except when they get auto-flagged."
const [nostrEventJson, userReportRequest] = getJSONFromCloudEvent(cloudEvent);
const nostrEvent = Nostr.getVerifiedEvent(nostrEventJson);

if (!nostrEvent) {
return;
Expand Down Expand Up @@ -35,11 +41,32 @@ functions.cloudEvent('nostrEventsPubSub', async (cloudEvent) => {
);

if (!moderation) {
return console.log(skipMessage);
if (!userReportRequest) {
console.log(skipMessage);
return;
}

await Slack.postManualVerification(nostrEventJson, userReportRequest);
console.log(
`Event ${eventToModerate.id} reported by ${userReportRequest.pubkey} not flagged. Sending to Slack`
);
return;
}

await Nostr.publishModeration(eventToModerate, moderation);
}
);
});
});

function getJSONFromCloudEvent(cloudEvent) {
const data = cloudEvent.data.message.data;
const jsonString = data ? Buffer.from(data, "base64").toString() : "{}";
const json = JSON.parse(jsonString);

if (json?.userReportRequest) {
return [json?.nostrEvent, json.userReportRequest];
}

return [json, null];
}
37 changes: 17 additions & 20 deletions src/lib/nostr.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import NDK, { NDKEvent, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk';
import { validateEvent, verifySignature } from 'nostr-tools';
import OPENAI_CATEGORIES from './openAICategories.js';
import { WebSocket } from 'ws';
import NDK, { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { validateEvent, verifySignature } from "nostr-tools";
import OPENAI_CATEGORIES from "./openAICategories.js";
import { WebSocket } from "ws";

if (!process.env.NOSTR_PRIVATE_KEY) {
throw new Error('NOSTR_PRIVATE_KEY environment variable is required');
throw new Error("NOSTR_PRIVATE_KEY environment variable is required");
}

// Hack to be able to have a global WebSocket object in Google Cloud Functions
global.WebSocket = WebSocket;

const RELAYS = [
'wss://relay.nos.social',
'wss://relay.damus.io',
'wss://relay.nostr.band',
'wss://relayable.org',
'wss://nostr.wine',
"wss://relay.nos.social",
"wss://relay.damus.io",
"wss://relay.nostr.band",
"wss://relayable.org",
"wss://nostr.wine",
];

const signer = new NDKPrivateKeySigner(process.env.NOSTR_PRIVATE_KEY);
Expand Down Expand Up @@ -69,12 +69,9 @@ export default class Nostr {
await event.publish();
}

static getVerifiedEvent(data) {
const eventJSON = data ? Buffer.from(data, 'base64').toString() : '{}';
const event = JSON.parse(eventJSON);

static getVerifiedEvent(event) {
if (!validateEvent(event)) {
console.error('Invalid Nostr Event');
console.error("Invalid Nostr Event");
return;
}

Expand All @@ -92,15 +89,15 @@ export default class Nostr {

static async setTags(moderationNostrEvent, moderatedNostrEvent, moderation) {
const reportType = this.inferReportType(moderation);
moderationNostrEvent.tags.push(['e', moderatedNostrEvent.id, reportType]);
moderationNostrEvent.tags.push(['L', 'MOD']);
moderationNostrEvent.tags.push(["e", moderatedNostrEvent.id, reportType]);
moderationNostrEvent.tags.push(["L", "MOD"]);

for (const [category, isFlagged] of Object.entries(moderation.categories)) {
if (isFlagged) {
moderationNostrEvent.tags.push([
'l',
"l",
`MOD>${OPENAI_CATEGORIES[category].nip69}`,
'MOD',
"MOD",
JSON.stringify({
confidence: moderation.category_scores[category],
}),
Expand All @@ -110,7 +107,7 @@ export default class Nostr {
}

static async getReportedNostrEvent(reportNostrEvent) {
const reportedNostrEventId = reportNostrEvent.tagValue('e');
const reportedNostrEventId = reportNostrEvent.tagValue("e");
const reportedNostrEvent = await ndk.fetchEvent({
ids: [reportedNostrEventId],
});
Expand Down
5 changes: 5 additions & 0 deletions src/lib/slack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default class Slack {
static async postManualVerification(nostrEventJson, userReportRequest) {
console.log(`userReportRequest: ${userReportRequest}`);
}
}
Loading

0 comments on commit c0ba361

Please sign in to comment.