Skip to content

Commit

Permalink
POC of the auto unsubscribe functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Eliezer Steinbock committed Mar 26, 2025
1 parent 74c3373 commit d9e3013
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 4 deletions.
8 changes: 7 additions & 1 deletion apps/unsubscriber/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,13 @@ async function performFallbackUnsubscribe(page: Page): Promise<boolean> {
return false;
}

export async function autoUnsubscribe(url: string): Promise<boolean> {
export async function autoUnsubscribe({
url,
email,
}: {
url: string;
email: string;
}): Promise<boolean> {
if (!isValidUrl(url)) {
console.error("Invalid URL provided:", url);
return false;
Expand Down
5 changes: 3 additions & 2 deletions apps/unsubscriber/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ if (env.CORS_ORIGIN) {

const unsubscribeSchema = z.object({
url: z.string().url(),
email: z.string().email(),
});

server.get("/", async (request, reply) => {
Expand All @@ -24,8 +25,8 @@ server.get("/", async (request, reply) => {

server.post("/unsubscribe", async (request, reply) => {
try {
const { url } = unsubscribeSchema.parse(request.body);
const success = await autoUnsubscribe(url);
const { url, email } = unsubscribeSchema.parse(request.body);
const success = await autoUnsubscribe({ url, email });
return {
success,
message: success
Expand Down
10 changes: 9 additions & 1 deletion apps/web/app/(app)/bulk-unsubscribe/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import React, { useCallback, useState } from "react";
import { toast } from "sonner";
import type { PostHog } from "posthog-js/react";
import { onAutoArchive, onDeleteFilter } from "@/utils/actions/client";
import { setNewsletterStatusAction } from "@/utils/actions/unsubscriber";
import {
setNewsletterStatusAction,
unsubscribeAction,
} from "@/utils/actions/unsubscriber";
import { decrementUnsubscribeCreditAction } from "@/utils/actions/premium";
import { NewsletterStatus } from "@prisma/client";
import { cleanUnsubscribeLink } from "@/utils/parse/parseHtml.client";
Expand Down Expand Up @@ -54,6 +57,10 @@ export function useUnsubscribe<T extends Row>({
posthog.capture("Clicked Unsubscribe");

if (item.status === NewsletterStatus.UNSUBSCRIBED) {
if (item.lastUnsubscribeLink) {
await unsubscribeAction({ url: item.lastUnsubscribeLink });
}

await setNewsletterStatusAction({
newsletterEmail: item.name,
status: null,
Expand All @@ -72,6 +79,7 @@ export function useUnsubscribe<T extends Row>({
hasUnsubscribeAccess,
item.name,
item.status,
item.lastUnsubscribeLink,
mutate,
refetchPremium,
posthog,
Expand Down
2 changes: 2 additions & 0 deletions apps/web/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ export const env = createEnv({
LICENSE_5_SEAT_VARIANT_ID: z.coerce.number().optional(),
LICENSE_10_SEAT_VARIANT_ID: z.coerce.number().optional(),
LICENSE_25_SEAT_VARIANT_ID: z.coerce.number().optional(),

UNSUBSCRIBER_API_URL: z.string().optional(),
},
client: {
NEXT_PUBLIC_LEMON_STORE_ID: z.string().nullish().default("inboxzero"),
Expand Down
21 changes: 21 additions & 0 deletions apps/web/utils/actions/unsubscriber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { auth } from "@/app/api/auth/[...nextauth]/auth";
import prisma from "@/utils/prisma";
import type { NewsletterStatus } from "@prisma/client";
import { withActionInstrumentation } from "@/utils/actions/middleware";
import { env } from "@/env";

export const setNewsletterStatusAction = withActionInstrumentation(
"setNewsletterStatus",
Expand All @@ -30,3 +31,23 @@ export const setNewsletterStatusAction = withActionInstrumentation(
});
},
);

export const unsubscribeAction = withActionInstrumentation(
"unsubscribe",
async (options: { url: string }) => {
const session = await auth();
if (!session?.user.email) return { error: "Not logged in" };

const { url } = options;

const response = await fetch(
`${env.UNSUBSCRIBER_API_URL}/unsubscribe?url=${url}&email=${session.user.email}`,
);

if (!response.ok) {
return { error: "Failed to unsubscribe" };
}

return { success: true };
},
);

0 comments on commit d9e3013

Please sign in to comment.