Setup Discord cli2 plugin
This adds a cliPlugin to the experimental Discord plugin, along the lines of the cli 2 plugins for GitHub and Discourse. Test plan: I set up a Cred instance for SourceCred including our Discord config, and successfully loaded Cred for it. Not easy to give full reproduction instructions, not least because it requires a private Discord bot token.
This commit is contained in:
parent
6e6d749902
commit
dd76595ac2
|
@ -3,6 +3,7 @@
|
|||
import type {CliPlugin} from "./cliPlugin";
|
||||
import {GithubCliPlugin} from "../plugins/github/cliPlugin";
|
||||
import {DiscourseCliPlugin} from "../plugins/discourse/cliPlugin";
|
||||
import {DiscordCliPlugin} from "../plugins/experimental-discord/cliPlugin";
|
||||
|
||||
/**
|
||||
* Returns an object mapping owner-name pairs to CLI plugin
|
||||
|
@ -12,5 +13,6 @@ export function bundledPlugins(): {[pluginId: string]: CliPlugin} {
|
|||
return {
|
||||
"sourcecred/github": new GithubCliPlugin(),
|
||||
"sourcecred/discourse": new DiscourseCliPlugin(),
|
||||
"sourcecred/discord": new DiscordCliPlugin(),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
// @flow
|
||||
|
||||
import Database from "better-sqlite3";
|
||||
|
||||
import type {CliPlugin, PluginDirectoryContext} from "../../cli2/cliPlugin";
|
||||
import type {PluginDeclaration} from "../../analysis/pluginDeclaration";
|
||||
import {parseConfig, type DiscordConfig, type DiscordToken} from "./config";
|
||||
import {declaration} from "./declaration";
|
||||
import {join as pathJoin} from "path";
|
||||
import fs from "fs-extra";
|
||||
import {type TaskReporter} from "../../util/taskReporter";
|
||||
import {Fetcher} from "./fetcher";
|
||||
import {Mirror} from "./mirror";
|
||||
import type {ReferenceDetector} from "../../core/references/referenceDetector";
|
||||
import type {WeightedGraph} from "../../core/weightedGraph";
|
||||
import {weightsForDeclaration} from "../../analysis/pluginDeclaration";
|
||||
import {createGraph} from "./createGraph";
|
||||
import * as Model from "./models";
|
||||
import {SqliteMirrorRepository} from "./mirrorRepository";
|
||||
|
||||
async function loadConfig(
|
||||
dirContext: PluginDirectoryContext
|
||||
): Promise<DiscordConfig> {
|
||||
const dirname = dirContext.configDirectory();
|
||||
const path = pathJoin(dirname, "config.json");
|
||||
const contents = await fs.readFile(path);
|
||||
return Promise.resolve(parseConfig(JSON.parse(contents)));
|
||||
}
|
||||
|
||||
const TOKEN_ENV_VAR_NAME = "SOURCECRED_DISCORD_TOKEN";
|
||||
|
||||
function getTokenFromEnv(): DiscordToken {
|
||||
const rawToken = process.env[TOKEN_ENV_VAR_NAME];
|
||||
if (rawToken == null) {
|
||||
throw new Error(`No Discord token provided: set ${TOKEN_ENV_VAR_NAME}`);
|
||||
}
|
||||
return rawToken;
|
||||
}
|
||||
|
||||
export class DiscordCliPlugin implements CliPlugin {
|
||||
declaration(): PluginDeclaration {
|
||||
return declaration;
|
||||
}
|
||||
|
||||
async load(
|
||||
ctx: PluginDirectoryContext,
|
||||
reporter: TaskReporter
|
||||
): Promise<void> {
|
||||
const {guildId} = await loadConfig(ctx);
|
||||
const token = getTokenFromEnv();
|
||||
const fetcher = new Fetcher({token});
|
||||
const repo = await repository(ctx, guildId);
|
||||
const mirror = new Mirror(repo, fetcher, guildId);
|
||||
await mirror.update(reporter);
|
||||
}
|
||||
|
||||
async graph(
|
||||
ctx: PluginDirectoryContext,
|
||||
rd: ReferenceDetector
|
||||
): Promise<WeightedGraph> {
|
||||
const _ = rd; // TODO(#1808): not yet used
|
||||
const {guildId, reactionWeights} = await loadConfig(ctx);
|
||||
const repo = await repository(ctx, guildId);
|
||||
const declarationWeights = weightsForDeclaration(declaration);
|
||||
return await createGraph(
|
||||
guildId,
|
||||
repo,
|
||||
declarationWeights,
|
||||
reactionWeights
|
||||
);
|
||||
}
|
||||
|
||||
async referenceDetector(
|
||||
_unused_ctx: PluginDirectoryContext
|
||||
): Promise<ReferenceDetector> {
|
||||
// TODO: Implement Discord reference detection
|
||||
// (low priority bc ppl rarely hardlink to Discord messages)
|
||||
return {addressFromUrl: () => undefined};
|
||||
}
|
||||
}
|
||||
|
||||
async function repository(
|
||||
ctx: PluginDirectoryContext,
|
||||
guild: Model.Snowflake
|
||||
): Promise<SqliteMirrorRepository> {
|
||||
const path = pathJoin(ctx.cacheDirectory(), "discordMirror.db");
|
||||
const db = await new Database(path);
|
||||
return new SqliteMirrorRepository(db, guild);
|
||||
}
|
Loading…
Reference in New Issue