···22import Database from 'better-sqlite3';
3344const SUBS_PER_ACCOUNT_LIMIT = 5;
55+const SECONDARY_FILTERS_LIMIT = 100;
66+57const SCHEMA_FNAME = './schema.sql';
6879export class DB {
···1820 #stmt_set_role;
1921 #stmt_get_notify_account_globals;
2022 #stmt_set_notify_account_globals;
2323+ #stmt_set_notification_filter;
2424+ #stmt_get_notification_filter;
2525+ #stmt_count_notification_filters;
2626+ #stmt_rm_notification_filter;
21272228 #stmt_admin_add_secret;
2329 #stmt_admin_expire_secret;
···127133 notify_self = :notify_self
128134 where did = :did`);
129135136136+ this.#stmt_set_notification_filter = db.prepare(
137137+ `insert into notification_filters (account_did, selector, selection, notify)
138138+ values (:did, :selector, :selection, :notify)
139139+ on conflict do update
140140+ set notify = excluded.notify`);
141141+142142+ this.#stmt_get_notification_filter = db.prepare(
143143+ `select notify
144144+ from notification_filters
145145+ where account_did = :did
146146+ and selector = :selector
147147+ and selection = :selection`);
148148+149149+ this.#stmt_count_notification_filters = db.prepare(
150150+ `select count(*) as n
151151+ from notification_filters
152152+ where account_did = :did`);
153153+154154+ this.#stmt_rm_notification_filter = db.prepare(
155155+ `delete from notification_filters
156156+ where account_did = :did
157157+ and selector = :selector
158158+ and selection = :selection`);
159159+130160131161 this.#stmt_admin_add_secret = db.prepare(
132162 `insert into top_secret_passwords (password)
···233263 update.did = did;
234264 this.#stmt_set_notify_account_globals.run(update);
235265 });
266266+ }
267267+268268+ getNotificationFilter(did, selector, selection) {
269269+ const res = this.#stmt_get_notification_filter.get({ did, selector, selection });
270270+ const dbNotify = res?.notify;
271271+ if (dbNotify === 1) return true;
272272+ else if (dbNotify === 0) return false;
273273+ else return null;
274274+ }
275275+276276+ setNotificationFilter(did, selector, selection, notify) {
277277+ if (notify === null) {
278278+ this.#stmt_rm_notification_filter.run({ did, selector, selection });
279279+ } else {
280280+ this.#transactionally(() => {
281281+ const { n } = this.#stmt_count_notification_filters.get({ did });
282282+ if (n >= SECONDARY_FILTERS_LIMIT) {
283283+ throw new Error('max filters set for account');
284284+ }
285285+ let dbNotify = null;
286286+ if (notify === true) dbNotify = 1;
287287+ else if (notify === false) dbNotify = 0;
288288+ this.#stmt_set_notification_filter.run({ did, selector, selection, notify: dbNotify });
289289+ });
290290+ }
236291 }
237292238293
+2-2
server/schema.sql
···3131 check(length(password) >= 3)
3232) strict;
33333434-create table if not exists mute_by_secondary (
3434+create table if not exists notification_filters (
3535 account_did text not null,
3636 selector text not null,
3737 selection text not null,
3838- mute integer not null default true,
3838+ notify integer null,
39394040 primary key(account_did, selector, selection),
4141 check(selector in ('all', 'app', 'group', 'source')),