Skip to content

Commit

Permalink
UniRef: implement DiscourseReferenceDetector
Browse files Browse the repository at this point in the history
  • Loading branch information
Beanow committed Jan 10, 2020
1 parent c1387e4 commit b0db4ce
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 0 deletions.
64 changes: 64 additions & 0 deletions src/plugins/discourse/referenceDetector.js
@@ -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)}`
);
}
}
}
}
112 changes: 112 additions & 0 deletions src/plugins/discourse/referenceDetector.test.js
@@ -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",
]
`);
});
});
});

0 comments on commit b0db4ce

Please sign in to comment.