UniRef: implement DiscourseReferenceDetector (#1530)
Discourse ReferenceDetector detector that relies on database lookups. (Should be the main way to solve #1479, when UniRef is used by all plugins)
This commit is contained in:
parent
5cf0fba634
commit
9e8e6845bc
|
@ -0,0 +1,64 @@
|
|||
// @flow
|
||||
|
||||
import type {NodeAddressT} from "../../core/graph";
|
||||
import type {ReferenceDetector, URL} from "../../core/references";
|
||||
import type {ReadRepository} from "./mirrorRepository";
|
||||
import {topicAddress, userAddress, postAddress} from "./address";
|
||||
import {linksToReferences} from "./references";
|
||||
|
||||
/**
|
||||
* Discourse ReferenceDetector detector that relies on database lookups.
|
||||
*/
|
||||
export class DiscourseReferenceDetector implements ReferenceDetector {
|
||||
data: ReadRepository;
|
||||
|
||||
constructor(data: ReadRepository) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
addressFromUrl(url: URL): ?NodeAddressT {
|
||||
const [reference] = linksToReferences([url]);
|
||||
if (!reference) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (reference.type) {
|
||||
case "TOPIC": {
|
||||
// Just validating the topic exists.
|
||||
if (this.data.topicById(reference.topicId)) {
|
||||
return topicAddress(reference.serverUrl, reference.topicId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "POST": {
|
||||
// For posts, we need to convert from topicId + index to a post ID.
|
||||
// We're using it to validate the topic and post index exist as well.
|
||||
const postId = this.data.findPostInTopic(
|
||||
reference.topicId,
|
||||
reference.postIndex
|
||||
);
|
||||
if (postId) {
|
||||
return postAddress(reference.serverUrl, postId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "USER": {
|
||||
// Look up the username to validate it exists, and make sure we use
|
||||
// the result. As this should correct our capitalization. See #1479.
|
||||
const username = this.data.findUsername(reference.username);
|
||||
if (username) {
|
||||
return userAddress(reference.serverUrl, username);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
throw new Error(
|
||||
`Unexpected reference type: ${(reference.type: empty)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
// @flow
|
||||
|
||||
import Database from "better-sqlite3";
|
||||
import type {Topic, Post} from "./fetch";
|
||||
import {SqliteMirrorRepository} from "./mirrorRepository";
|
||||
import {DiscourseReferenceDetector} from "./referenceDetector";
|
||||
import {type NodeAddressT, NodeAddress} from "../../core/graph";
|
||||
|
||||
const TEST_URL = "https://example.com";
|
||||
|
||||
const emptyRepository = (): SqliteMirrorRepository => {
|
||||
const db = new Database(":memory:");
|
||||
return new SqliteMirrorRepository(db, TEST_URL);
|
||||
};
|
||||
|
||||
const maybeToParts = (a: ?NodeAddressT) => {
|
||||
return a ? NodeAddress.toParts(a) : a;
|
||||
};
|
||||
|
||||
describe("plugins/discourse/referenceDetector", () => {
|
||||
describe("DiscourseReferenceDetector", () => {
|
||||
it("should detect user reference", () => {
|
||||
// Given
|
||||
const repo = emptyRepository();
|
||||
const detector = new DiscourseReferenceDetector(repo);
|
||||
const username = "PascalFan1988";
|
||||
repo.addUser(username);
|
||||
|
||||
// When
|
||||
const result = detector.addressFromUrl(`${TEST_URL}/u/pascalfan1988`);
|
||||
|
||||
// Then
|
||||
expect(maybeToParts(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"sourcecred",
|
||||
"discourse",
|
||||
"user",
|
||||
"https://example.com",
|
||||
"PascalFan1988",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it("should detect topic reference", () => {
|
||||
// Given
|
||||
const repo = emptyRepository();
|
||||
const detector = new DiscourseReferenceDetector(repo);
|
||||
const topic: Topic = {
|
||||
id: 123,
|
||||
categoryId: 1,
|
||||
title: "Sample topic",
|
||||
timestampMs: 456789,
|
||||
bumpedMs: 456999,
|
||||
authorUsername: "credbot",
|
||||
};
|
||||
repo.addTopic(topic);
|
||||
|
||||
// When
|
||||
const result = detector.addressFromUrl(`${TEST_URL}/t/random-slug/123`);
|
||||
|
||||
// Then
|
||||
expect(maybeToParts(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"sourcecred",
|
||||
"discourse",
|
||||
"topic",
|
||||
"https://example.com",
|
||||
"123",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it("should detect post reference", () => {
|
||||
// Given
|
||||
const repo = emptyRepository();
|
||||
const detector = new DiscourseReferenceDetector(repo);
|
||||
const topic: Topic = {
|
||||
id: 123,
|
||||
categoryId: 1,
|
||||
title: "Sample topic",
|
||||
timestampMs: 456789,
|
||||
bumpedMs: 456999,
|
||||
authorUsername: "credbot",
|
||||
};
|
||||
const p1: Post = {
|
||||
id: 100,
|
||||
topicId: 123,
|
||||
indexWithinTopic: 1,
|
||||
replyToPostIndex: null,
|
||||
timestampMs: 456789,
|
||||
authorUsername: "credbot",
|
||||
cooked: "<p>Valid post</p>",
|
||||
};
|
||||
repo.addTopic(topic);
|
||||
repo.addPost(p1);
|
||||
|
||||
// When
|
||||
const result = detector.addressFromUrl(`${TEST_URL}/t/random-slug/123/1`);
|
||||
|
||||
// Then
|
||||
expect(maybeToParts(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"sourcecred",
|
||||
"discourse",
|
||||
"post",
|
||||
"https://example.com",
|
||||
"100",
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue