Skip to content
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

Accept empty input to SubredditConfig constructor #66

Merged
merged 11 commits into from
Oct 31, 2024
32 changes: 32 additions & 0 deletions src/classes/SubredditConfig.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,36 @@
import test from 'ava';
import {DEFAULT_CONFIG} from '../helpers/config';
import {SubredditConfig} from './SubredditConfig';

test('constructor: accept empty input', t => {
t.assert(
new SubredditConfig() instanceof SubredditConfig,
'passing nothing to SubredditConfig constructor should return a SubredditConfig instance',
);

t.assert(
new SubredditConfig('') instanceof SubredditConfig,
'passing empty string to SubredditConfig constructor should return a SubredditConfig instance',
);
});

test('constructor: results of passing in nothing and empty input are identical', t => {
const configFromNothing = new SubredditConfig();
const configFromEmpty = new SubredditConfig('');

t.deepEqual(
configFromNothing.toJSON(),
configFromEmpty.toJSON(),
'SubredditConfig initiated with nothing vs empty should be identical',
);
});

test('constructor: on empty input, the default config is returned', t => {
const config = new SubredditConfig();
const configAsJson = config.toJSON();

t.deepEqual(configAsJson, DEFAULT_CONFIG, "SubredditConfig initiated with nothing should return default config");
});

test.todo('getAllNoteTypes');
test.todo('getNoteType');
Expand Down
10 changes: 8 additions & 2 deletions src/classes/SubredditConfig.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
DEFAULT_CONFIG,
DEFAULT_USERNOTE_TYPES,
migrateConfigToLatestSchema,
} from '../helpers/config';
Expand All @@ -15,8 +16,13 @@ import type {Usernote} from '../types/Usernote';
export class SubredditConfig {
private data: RawSubredditConfig;

constructor (jsonString: string) {
this.data = migrateConfigToLatestSchema(JSON.parse(jsonString));
constructor (jsonString?: string) {
if (jsonString) {
this.data = migrateConfigToLatestSchema(JSON.parse(jsonString));
} else {
// TODO: the default config value isn't actually typed correctly, this needs to be cleaned up eventually
this.data = DEFAULT_CONFIG as unknown as RawSubredditConfig;
}
}

/** Returns all usernote types. */
Expand Down
23 changes: 19 additions & 4 deletions src/classes/ToolboxClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {RedditAPIClient} from '@devvit/public-api';
import {RedditAPIClient, WikiPage} from '@devvit/public-api';
import {Usernote, UsernoteInit} from '../types/Usernote';
import {SubredditConfig} from './SubredditConfig';
import {Usernotes} from './Usernotes';
Expand Down Expand Up @@ -140,9 +140,24 @@ export class ToolboxClient {
await this.writeUsernotes(subreddit, notes, reason);
}

/** */
/**
* Retrieves toolbox configuration for a subreddit.
* @param subreddit Name of the subreddit to retrieve config for
*/
async getConfig (subreddit: string) {
const page = await this.reddit.getWikiPage(subreddit, TB_CONFIG_PAGE);
return new SubredditConfig(page.content);
let page: WikiPage | undefined;
try {
page = await this.reddit.getWikiPage(subreddit, TB_CONFIG_PAGE);
} catch (error) {
// Devvit throws an error when page is not present, but also
// sometimes for other reasons. Check if the page actually
// exists; if it doesn't we'll use the default config, but if it
// does then something else is wrong and we'll rethrow the error.
const allPages = await this.reddit.getWikiPages(subreddit);
if (allPages.includes(TB_CONFIG_PAGE)) {
throw error;
}
}
return new SubredditConfig(page?.content);
}
}
14 changes: 14 additions & 0 deletions src/helpers/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ export const DEFAULT_USERNOTE_TYPES: readonly RawUsernoteType[] = [
{key: 'botban', color: 'black', text: 'Bot Ban'},
];

/**
* Default subreddit configuration to use if subreddit doesnt have one.
* Empty strings are used in the default config by the plugin even though
* this doesn't match the type exactly.
*/
export const DEFAULT_CONFIG = {
ver: LATEST_KNOWN_CONFIG_SCHEMA,
domainTags: '',
removalReasons: '',
modMacros: '',
usernoteColors: '',
banMacros: '',
};

/**
* Checks the schema version of raw subreddit config data and attempts to update
* it to the latest known schema version if it's out of date. Throws an error if
Expand Down