···66 pdsHost: text("pds_host").notNull(),
77 active: integer("active", { mode: "boolean" }).notNull(),
88 dateFirstSeen: integer("date_first_seen", { mode: "timestamp" }).notNull(),
99+ //If set means a take down was issued
1010+ takeDownIssuedDate: integer("take_down_issued_date", {
1111+ mode: "timestamp",
1212+ }),
913});
10141115export const labelsApplied = sqliteTable("labels_applied", {
···1822 action: text("action").notNull(),
1923 negated: integer("negated", { mode: "boolean" }).default(false).notNull(),
2024 dateApplied: integer("date_applied", { mode: "timestamp" }).notNull(),
2525+ // * AT URI of the record, repository (account), or other resource that this label applies to.
2626+ uri: text("uri"),
2127});
22282329export const labelerCursor = sqliteTable("labeler_cursors", {
+81-29
src/handlers/handleNewLabel.ts
···66import * as schema from "../db/schema.js";
77import { and, eq } from "drizzle-orm";
88import type PQueue from "p-queue";
99-import { Client, simpleFetchHandler, ok } from "@atcute/client";
99+import { Client, simpleFetchHandler } from "@atcute/client";
1010import { ComAtprotoAdminUpdateSubjectStatus } from "@atcute/atproto";
1111const adminAuthHeader = (password: string) => ({
1212 Authorization: `Basic ${Buffer.from(`admin:${password}`).toString("base64")}`,
···3535 targetDid = repoDid;
3636 }
37373838- // TODO: MAKE SURE TO CHECK NEG
3938 let labledDate = new Date(label.cts);
4039 logger.debug(
4140 {
···4948 );
50495150 let labelConfig = config.labels[label.val];
5151+ //If the label is a watched one dig in
5252 if (labelConfig) {
5353 const isRepoWatched = await db
5454 .select()
···6161 )
6262 .limit(1);
63636464+ //If a watched repo/user is the target of the label dig in
6465 if (isRepoWatched.length > 0) {
6566 const watchedRepo = isRepoWatched[0];
6667 if (watchedRepo == undefined) {
···7879 `Listed label: ${label.val} found added to ${watchedRepo.did}`,
7980 );
80818282+ // Check if this label already exists
8183 const existing = await db
8284 .select()
8385 .from(schema.labelsApplied)
···126128 labeler: config.host,
127129 negated: label.neg ?? false,
128130 dateApplied: labledDate,
131131+ targetUri: label.uri,
129132 takeDown: false,
130133 }).catch((err) =>
131134 logger.error({ err }, "Error sending label notification email"),
132135 ),
133136 );
134134- case "takedown":
137137+ break;
138138+ case "takedown": {
139139+ let takedownSuccess: boolean;
140140+135141 if (pdsConfig.pdsAdminPassword) {
136142 const rpc = new Client({
137143 handler: simpleFetchHandler({
···139145 }),
140146 });
141147142142- logger.info("taking down the account");
143143- //TODO do atcute actions and then send email
144144- if (label.neg) {
145145- //reverse takedown
146146- let reverseTakeDown = rpc.call(
147147- ComAtprotoAdminUpdateSubjectStatus,
148148- {
148148+ try {
149149+ if (label.neg) {
150150+ logger.info({ did: targetDid }, "Reversing takedown");
151151+ await rpc.call(ComAtprotoAdminUpdateSubjectStatus, {
149152 input: {
150153 subject: {
151154 $type: "com.atproto.admin.defs#repoRef",
···156159 },
157160 },
158161 headers: adminAuthHeader(pdsConfig.pdsAdminPassword),
159159- },
162162+ });
163163+ logger.info(
164164+ { did: targetDid },
165165+ "Takedown reversed successfully",
166166+ );
167167+ } else {
168168+ if (!watchedRepo.takeDownIssuedDate) {
169169+ logger.info({ did: targetDid }, "Issuing takedown");
170170+ await rpc.call(ComAtprotoAdminUpdateSubjectStatus, {
171171+ input: {
172172+ subject: {
173173+ $type: "com.atproto.admin.defs#repoRef",
174174+ did: targetDid as `did:${string}:${string}.`,
175175+ },
176176+ takedown: {
177177+ applied: true,
178178+ ref: Math.floor(Date.now() / 1000).toString(),
179179+ },
180180+ },
181181+ headers: adminAuthHeader(pdsConfig.pdsAdminPassword),
182182+ });
183183+ await db.update(schema.watchedRepos).set({
184184+ takeDownIssuedDate: new Date(),
185185+ });
186186+187187+ logger.info(
188188+ { did: targetDid },
189189+ "Takedown issued successfully",
190190+ );
191191+ takedownSuccess = true;
192192+ } else {
193193+ logger.info(
194194+ { did: targetDid },
195195+ "Duplicate event, not reissuing a takedown",
196196+ );
197197+ }
198198+ }
199199+ } catch (err) {
200200+ takedownSuccess = false;
201201+ logger.error(
202202+ { err, did: targetDid },
203203+ label.neg
204204+ ? "Failed to reverse takedown"
205205+ : "Failed to issue takedown",
160206 );
161161- } else {
162162- //issue takedown
163163- let takeDown = rpc.call(ComAtprotoAdminUpdateSubjectStatus, {
164164- input: {
165165- subject: {
166166- $type: "com.atproto.admin.defs#repoRef",
167167- did: targetDid as `did:${string}:${string}.`,
168168- },
169169- takedown: {
170170- applied: true,
171171- ref: Math.floor(Date.now() / 1000).toString(),
172172- },
173173- },
174174- headers: adminAuthHeader(pdsConfig.pdsAdminPassword),
175175- });
176207 }
177177- break;
178208 } else {
179179- logger.warn("PDS admin password not set, takedown not issued");
209209+ logger.warn(
210210+ { did: targetDid },
211211+ "PDS admin password not set, takedown not issued",
212212+ );
180213 }
181214182182- //Send the email here still. IF passwrod is not set always set takedown as false?
215215+ await mailQueue.add(() =>
216216+ sendLabelNotification(pdsConfig.notifyEmails, {
217217+ did: targetDid,
218218+ pds: pdsConfig.host,
219219+ label: label.val,
220220+ labeler: config.host,
221221+ negated: label.neg ?? false,
222222+ dateApplied: labledDate,
223223+ takeDown: true,
224224+ targetUri: label.uri,
225225+ takedownSuccess,
226226+ }).catch((err) =>
227227+ logger.error(
228228+ { err },
229229+ "Error sending takedown notification email",
230230+ ),
231231+ ),
232232+ );
233233+ break;
234234+ }
183235 }
184236185237 return;
+2-1
src/index.ts
···1010import { backFillPds } from "./pds.js";
1111import { pdsSubscriber } from "./handlers/pdsSubscriber.js";
12121313-const labelQueue = new PQueue({ concurrency: 2 });
1313+//Leaveing this at 1 concurrency right now since some labelers do multiple labels at once I've found.
1414+const labelQueue = new PQueue({ concurrency: 1 });
1415const identityQueue = new PQueue({ concurrency: 2 });
1516const mailQueue = new PQueue({ concurrency: 1 });
1617