-
Notifications
You must be signed in to change notification settings - Fork 6
Feat/ecurrency transaction messages #523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,18 +1,23 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| import { Request, Response } from "express"; | ||||||||||||||||||||||||||||||||||||||||||||
| import { UserService } from "../services/UserService"; | ||||||||||||||||||||||||||||||||||||||||||||
| import { GroupService } from "../services/GroupService"; | ||||||||||||||||||||||||||||||||||||||||||||
| import { MessageService } from "../services/MessageService"; | ||||||||||||||||||||||||||||||||||||||||||||
| import { adapter } from "../web3adapter/watchers/subscriber"; | ||||||||||||||||||||||||||||||||||||||||||||
| import { User } from "../database/entities/User"; | ||||||||||||||||||||||||||||||||||||||||||||
| import { Group } from "../database/entities/Group"; | ||||||||||||||||||||||||||||||||||||||||||||
| import { Message } from "../database/entities/Message"; | ||||||||||||||||||||||||||||||||||||||||||||
| import axios from "axios"; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| export class WebhookController { | ||||||||||||||||||||||||||||||||||||||||||||
| userService: UserService; | ||||||||||||||||||||||||||||||||||||||||||||
| groupService: GroupService; | ||||||||||||||||||||||||||||||||||||||||||||
| messageService: MessageService; | ||||||||||||||||||||||||||||||||||||||||||||
| adapter: typeof adapter; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| constructor() { | ||||||||||||||||||||||||||||||||||||||||||||
| this.userService = new UserService(); | ||||||||||||||||||||||||||||||||||||||||||||
| this.groupService = new GroupService(); | ||||||||||||||||||||||||||||||||||||||||||||
| this.messageService = new MessageService(); | ||||||||||||||||||||||||||||||||||||||||||||
| this.adapter = adapter; | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -179,6 +184,86 @@ export class WebhookController { | |||||||||||||||||||||||||||||||||||||||||||
| finalLocalId = group.id; | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } else if (mapping.tableName === "messages") { | ||||||||||||||||||||||||||||||||||||||||||||
| console.log("Processing message with data:", local.data); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // Extract sender and group from the message data | ||||||||||||||||||||||||||||||||||||||||||||
| let sender: User | null = null; | ||||||||||||||||||||||||||||||||||||||||||||
| let group: Group | null = null; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (local.data.sender && typeof local.data.sender === "string") { | ||||||||||||||||||||||||||||||||||||||||||||
| const senderId = local.data.sender.split("(")[1].split(")")[0]; | ||||||||||||||||||||||||||||||||||||||||||||
| sender = await this.userService.getUserById(senderId); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (local.data.group && typeof local.data.group === "string") { | ||||||||||||||||||||||||||||||||||||||||||||
| const groupId = local.data.group.split("(")[1].split(")")[0]; | ||||||||||||||||||||||||||||||||||||||||||||
| group = await this.groupService.getGroupById(groupId); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // Check if this is a system message (no sender required) | ||||||||||||||||||||||||||||||||||||||||||||
| const isSystemMessage = local.data.isSystemMessage === true || | ||||||||||||||||||||||||||||||||||||||||||||
| (local.data.text && typeof local.data.text === 'string' && local.data.text.startsWith('$$system-message$$')); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (!group) { | ||||||||||||||||||||||||||||||||||||||||||||
| console.error("Group not found for message"); | ||||||||||||||||||||||||||||||||||||||||||||
| return res.status(500).send(); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // For system messages, sender can be null | ||||||||||||||||||||||||||||||||||||||||||||
| if (!isSystemMessage && !sender) { | ||||||||||||||||||||||||||||||||||||||||||||
| console.error("Sender not found for non-system message"); | ||||||||||||||||||||||||||||||||||||||||||||
| return res.status(500).send(); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (localId) { | ||||||||||||||||||||||||||||||||||||||||||||
| console.log("Updating existing message with localId:", localId); | ||||||||||||||||||||||||||||||||||||||||||||
| const message = await this.messageService.getMessageById(localId); | ||||||||||||||||||||||||||||||||||||||||||||
| if (!message) { | ||||||||||||||||||||||||||||||||||||||||||||
| console.error("Message not found for localId:", localId); | ||||||||||||||||||||||||||||||||||||||||||||
| return res.status(500).send(); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // For system messages, ensure the prefix is preserved | ||||||||||||||||||||||||||||||||||||||||||||
| if (isSystemMessage && !(local.data.text as string).startsWith('$$system-message$$')) { | ||||||||||||||||||||||||||||||||||||||||||||
| message.text = `$$system-message$$ ${local.data.text as string}`; | ||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||
| message.text = local.data.text as string; | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| message.sender = sender || undefined; | ||||||||||||||||||||||||||||||||||||||||||||
| message.group = group; | ||||||||||||||||||||||||||||||||||||||||||||
| message.isSystemMessage = isSystemMessage as boolean; | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+227
to
+235
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential data loss: sender field may be unintentionally cleared. On line 233, setting Consider preserving the existing sender if lookup fails: if (isSystemMessage && !(local.data.text as string).startsWith('$$system-message$$')) {
message.text = `$$system-message$$ ${local.data.text as string}`;
} else {
message.text = local.data.text as string;
}
- message.sender = sender || undefined;
+ // Only update sender if explicitly provided (preserve existing sender if lookup fails)
+ if (local.data.sender) {
+ message.sender = sender || undefined;
+ }
message.group = group;
message.isSystemMessage = isSystemMessage as boolean;📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| this.adapter.addToLockedIds(localId); | ||||||||||||||||||||||||||||||||||||||||||||
| await this.messageService.messageRepository.save(message); | ||||||||||||||||||||||||||||||||||||||||||||
| console.log("Updated message:", message.id); | ||||||||||||||||||||||||||||||||||||||||||||
| finalLocalId = message.id; | ||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||
| console.log("Creating new message"); | ||||||||||||||||||||||||||||||||||||||||||||
| let message: Message; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if (isSystemMessage) { | ||||||||||||||||||||||||||||||||||||||||||||
| message = await this.messageService.createSystemMessageWithoutPrefix({ | ||||||||||||||||||||||||||||||||||||||||||||
| text: local.data.text as string, | ||||||||||||||||||||||||||||||||||||||||||||
| groupId: group.id, | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||
| message = await this.messageService.createMessage({ | ||||||||||||||||||||||||||||||||||||||||||||
| text: local.data.text as string, | ||||||||||||||||||||||||||||||||||||||||||||
| senderId: sender!.id, // We know sender exists for non-system messages | ||||||||||||||||||||||||||||||||||||||||||||
| groupId: group.id, | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| console.log("Created message with ID:", message.id); | ||||||||||||||||||||||||||||||||||||||||||||
| this.adapter.addToLockedIds(message.id); | ||||||||||||||||||||||||||||||||||||||||||||
| await this.adapter.mappingDb.storeMapping({ | ||||||||||||||||||||||||||||||||||||||||||||
| localId: message.id, | ||||||||||||||||||||||||||||||||||||||||||||
| globalId: req.body.id, | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| console.log("Stored mapping for message:", message.id, "->", req.body.id); | ||||||||||||||||||||||||||||||||||||||||||||
| finalLocalId = message.id; | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| res.status(200).send(); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import { | ||
| Entity, | ||
| PrimaryGeneratedColumn, | ||
| Column, | ||
| CreateDateColumn, | ||
| UpdateDateColumn, | ||
| ManyToOne, | ||
| } from "typeorm"; | ||
| import { User } from "./User"; | ||
| import { Group } from "./Group"; | ||
|
|
||
| @Entity("messages") | ||
| export class Message { | ||
| @PrimaryGeneratedColumn("uuid") | ||
| id!: string; | ||
|
|
||
| @ManyToOne(() => User, { nullable: true }) | ||
| sender?: User; // Nullable for system messages | ||
|
|
||
| @Column("text") | ||
| text!: string; | ||
|
|
||
| @ManyToOne(() => Group, (group) => group.messages) | ||
| group!: Group; | ||
|
|
||
| @Column({ default: false }) | ||
| isSystemMessage!: boolean; // Flag to identify system messages | ||
|
|
||
| @Column("uuid", { nullable: true }) | ||
| voteId?: string; // ID of the vote/poll this system message relates to | ||
|
|
||
| @CreateDateColumn() | ||
| createdAt!: Date; | ||
|
|
||
| @UpdateDateColumn() | ||
| updatedAt!: Date; | ||
|
|
||
| @Column({ default: false }) | ||
| isArchived!: boolean; | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import { | ||
| Entity, | ||
| PrimaryGeneratedColumn, | ||
| Column, | ||
| CreateDateColumn, | ||
| UpdateDateColumn, | ||
| } from "typeorm"; | ||
|
|
||
| @Entity("user_evault_mappings") | ||
| export class UserEVaultMapping { | ||
| @PrimaryGeneratedColumn("uuid") | ||
| id!: string; | ||
|
|
||
| @Column() | ||
| localUserId!: string; | ||
|
|
||
| @Column() | ||
| evaultW3id!: string; | ||
|
|
||
| @Column() | ||
| evaultUri!: string; | ||
|
|
||
| @Column({ nullable: true }) | ||
| userProfileId!: string; // ID of the UserProfile object in the eVault | ||
|
|
||
| @Column({ type: "jsonb", nullable: true }) | ||
| userProfileData!: any; // Store the UserProfile data | ||
coodos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| @CreateDateColumn() | ||
| createdAt!: Date; | ||
|
|
||
| @UpdateDateColumn() | ||
| updatedAt!: Date; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { MigrationInterface, QueryRunner } from "typeorm"; | ||
|
|
||
| export class Migration1765208128946 implements MigrationInterface { | ||
| name = 'Migration1765208128946' | ||
|
|
||
| public async up(queryRunner: QueryRunner): Promise<void> { | ||
| await queryRunner.query(`CREATE TABLE "messages" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "text" text NOT NULL, "isSystemMessage" boolean NOT NULL DEFAULT false, "voteId" uuid, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "isArchived" boolean NOT NULL DEFAULT false, "senderId" uuid, "groupId" uuid, CONSTRAINT "PK_18325f38ae6de43878487eff986" PRIMARY KEY ("id"))`); | ||
| await queryRunner.query(`CREATE TABLE "user_evault_mappings" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "localUserId" character varying NOT NULL, "evaultW3id" character varying NOT NULL, "evaultUri" character varying NOT NULL, "userProfileId" character varying, "userProfileData" jsonb, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_744ddb4ddca6af2de54773e9213" PRIMARY KEY ("id"))`); | ||
| await queryRunner.query(`ALTER TABLE "messages" ADD CONSTRAINT "FK_2db9cf2b3ca111742793f6c37ce" FOREIGN KEY ("senderId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); | ||
| await queryRunner.query(`ALTER TABLE "messages" ADD CONSTRAINT "FK_438f09ab5b4bbcd27683eac2a5e" FOREIGN KEY ("groupId") REFERENCES "group"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); | ||
coodos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| public async down(queryRunner: QueryRunner): Promise<void> { | ||
| await queryRunner.query(`ALTER TABLE "messages" DROP CONSTRAINT "FK_438f09ab5b4bbcd27683eac2a5e"`); | ||
| await queryRunner.query(`ALTER TABLE "messages" DROP CONSTRAINT "FK_2db9cf2b3ca111742793f6c37ce"`); | ||
| await queryRunner.query(`DROP TABLE "user_evault_mappings"`); | ||
| await queryRunner.query(`DROP TABLE "messages"`); | ||
| } | ||
|
|
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.