From 6cee3b82bb803b6e50298c4c1c40da40fd69ca99 Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Tue, 28 Jun 2022 14:48:45 +0200 Subject: [PATCH] Removing some builtin plugs --- package-lock.json | 48 ---- packages/plugs/ghost/ghost.plug.yaml | 9 - packages/plugs/ghost/ghost.ts | 220 ------------------ packages/plugs/git/git.plug.yaml | 21 -- packages/plugs/git/git.ts | 48 ---- packages/plugs/github/github.plug.yaml | 10 - packages/plugs/github/github.ts | 169 -------------- .../plugs/mattermost/mattermost.plug.yaml | 6 - packages/plugs/mattermost/mattermost.ts | 124 ---------- packages/plugs/package.json | 2 - 10 files changed, 657 deletions(-) delete mode 100644 packages/plugs/ghost/ghost.plug.yaml delete mode 100644 packages/plugs/ghost/ghost.ts delete mode 100644 packages/plugs/git/git.plug.yaml delete mode 100644 packages/plugs/git/git.ts delete mode 100644 packages/plugs/github/github.plug.yaml delete mode 100644 packages/plugs/github/github.ts delete mode 100644 packages/plugs/mattermost/mattermost.plug.yaml delete mode 100644 packages/plugs/mattermost/mattermost.ts diff --git a/package-lock.json b/package-lock.json index 1b0bb9f7..0fe23868 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1274,36 +1274,6 @@ "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.0.tgz", "integrity": "sha512-ohydQe+Hb+w4oMDvXzs8uuJd2NoA3D8YDcLiuDsLqH+yflDTPEpgCsWI3/6rH5C3BAedtH1/R51dxENldQceEA==" }, - "node_modules/@mattermost/client": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@mattermost/client/-/client-7.0.0.tgz", - "integrity": "sha512-ySzXez63Z2nzFhn2yBIe/FhWk/cWi75Xf0QXW51yQUurME/yhkilVY2yuAcbpVmOq0YhQM6WJOIKL4LKNI/Yyw==", - "dependencies": { - "form-data": "^4.0.0" - }, - "peerDependencies": { - "@mattermost/types": "*", - "typescript": "^4.3" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@mattermost/types": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@mattermost/types/-/types-7.0.0.tgz", - "integrity": "sha512-8aqU1lYzZqZinZoQmxhmFYM4me5+WdVE4GWUcvwx+6FlBxd9O/VQ6YeyCFZeYVnzrcOai9MVaZdyWp29S8GBCw==", - "peerDependencies": { - "typescript": "^4.3" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@mischnic/json-sourcemap": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@mischnic/json-sourcemap/-/json-sourcemap-0.1.0.tgz", @@ -19156,8 +19126,6 @@ "@jest/globals": "^27.5.1", "@lezer/generator": "1.0.0", "@lezer/lr": "1.0.0", - "@mattermost/client": "^7.0.0", - "@mattermost/types": "^7.0.0", "@silverbulletmd/common": "^0.0.8", "@silverbulletmd/plugs": "^0.0.8", "@silverbulletmd/web": "^0.0.8", @@ -22435,20 +22403,6 @@ } } }, - "@mattermost/client": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@mattermost/client/-/client-7.0.0.tgz", - "integrity": "sha512-ySzXez63Z2nzFhn2yBIe/FhWk/cWi75Xf0QXW51yQUurME/yhkilVY2yuAcbpVmOq0YhQM6WJOIKL4LKNI/Yyw==", - "requires": { - "form-data": "^4.0.0" - } - }, - "@mattermost/types": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@mattermost/types/-/types-7.0.0.tgz", - "integrity": "sha512-8aqU1lYzZqZinZoQmxhmFYM4me5+WdVE4GWUcvwx+6FlBxd9O/VQ6YeyCFZeYVnzrcOai9MVaZdyWp29S8GBCw==", - "requires": {} - }, "@mischnic/json-sourcemap": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@mischnic/json-sourcemap/-/json-sourcemap-0.1.0.tgz", @@ -27708,8 +27662,6 @@ "@jest/globals": "^27.5.1", "@lezer/generator": "1.0.0", "@lezer/lr": "1.0.0", - "@mattermost/client": "^7.0.0", - "@mattermost/types": "^7.0.0", "@silverbulletmd/common": "^0.0.8", "@silverbulletmd/plugs": "^0.0.8", "@silverbulletmd/web": "^0.0.8", diff --git a/packages/plugs/ghost/ghost.plug.yaml b/packages/plugs/ghost/ghost.plug.yaml deleted file mode 100644 index 98cbcd8d..00000000 --- a/packages/plugs/ghost/ghost.plug.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: ghost -functions: - publishCommand: - path: "./ghost.ts:publishCommand" - command: - name: "Ghost: Publish" - publish: - path: "./ghost.ts:publish" - env: server diff --git a/packages/plugs/ghost/ghost.ts b/packages/plugs/ghost/ghost.ts deleted file mode 100644 index 75a6c43e..00000000 --- a/packages/plugs/ghost/ghost.ts +++ /dev/null @@ -1,220 +0,0 @@ -import { readPage } from "@silverbulletmd/plugos-silverbullet-syscall/space"; -import { invokeFunction } from "@silverbulletmd/plugos-silverbullet-syscall/system"; -import { - getCurrentPage, - getText, -} from "@silverbulletmd/plugos-silverbullet-syscall/editor"; -import { cleanMarkdown } from "../markdown/util"; -import { parseMarkdown } from "@silverbulletmd/plugos-silverbullet-syscall/markdown"; -import { extractMeta } from "../query/data"; - -type GhostConfig = { - url: string; - adminKey: string; - postPrefix: string; - pagePrefix: string; -}; - -type Post = { - id: string; - uuid: string; - title: string; - slug: string; - mobiledoc: string; - status: "draft" | "published"; - visibility: string; - created_at: string; - upblished_at: string; - updated_at: string; - tags: Tag[]; - primary_tag: Tag; - url: string; - excerpt: string; -}; - -type Tag = { - id: string; - name: string; - slug: string; - description: string | null; -}; - -type MobileDoc = { - version: string; - atoms: any[]; - cards: Card[]; -}; - -type Card = any[]; - -function mobileDocToMarkdown(doc: string): string | null { - let mobileDoc = JSON.parse(doc) as MobileDoc; - if (mobileDoc.cards.length > 0 && mobileDoc.cards[0][0] === "markdown") { - return mobileDoc.cards[0][1].markdown; - } - return null; -} - -function markdownToMobileDoc(text: string): string { - return JSON.stringify({ - version: "0.3.1", - atoms: [], - cards: [["markdown", { markdown: text }]], - markups: [], - sections: [ - [10, 0], - [1, "p", []], - ], - }); -} - -class GhostAdmin { - private token?: string; - - constructor(private url: string, private key: string) {} - - async init() { - const [id, secret] = this.key.split(":"); - - this.token = await self.syscall( - "jwt.jwt", - secret, - id, - "HS256", - "5m", - "/v3/admin/" - ); - } - - async listPosts(): Promise { - let result = await fetch( - `${this.url}/ghost/api/v3/admin/posts?order=published_at+DESC`, - { - headers: { - Authorization: `Ghost ${this.token}`, - }, - } - ); - - return (await result.json()).posts; - } - - async listMarkdownPosts(): Promise { - let markdownPosts: Post[] = []; - for (let post of await this.listPosts()) { - let mobileDoc = JSON.parse(post.mobiledoc) as MobileDoc; - if (mobileDoc.cards.length > 0 && mobileDoc.cards[0][0] === "markdown") { - markdownPosts.push(post); - } - } - return markdownPosts; - } - - publishPost(post: Partial): Promise { - return this.publish("posts", post); - } - - publishPage(post: Partial): Promise { - return this.publish("pages", post); - } - - async publish(what: "pages" | "posts", post: Partial): Promise { - let oldPostQueryR = await fetch( - `${this.url}/ghost/api/v3/admin/${what}/slug/${post.slug}`, - { - headers: { - Authorization: `Ghost ${this.token}`, - "Content-Type": "application/json", - }, - } - ); - let oldPostQuery = await oldPostQueryR.json(); - if (!oldPostQuery[what]) { - // New! - if (!post.status) { - post.status = "draft"; - } - let result = await fetch(`${this.url}/ghost/api/v3/admin/${what}`, { - method: "POST", - headers: { - Authorization: `Ghost ${this.token}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - [what]: [post], - }), - }); - return (await result.json())[what][0]; - } else { - let oldPost: Post = oldPostQuery[what][0]; - post.updated_at = oldPost.updated_at; - let result = await fetch( - `${this.url}/ghost/api/v3/admin/${what}/${oldPost.id}`, - { - method: "PUT", - headers: { - Authorization: `Ghost ${this.token}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - [what]: [post], - }), - } - ); - return (await result.json())[what][0]; - } - } -} - -function postToMarkdown(post: Post): string { - let text = mobileDocToMarkdown(post.mobiledoc); - return `# ${post.title}\n${text}`; -} - -const postRegex = /#\s*([^\n]+)\n([^$]+)$/; - -async function markdownToPost(text: string): Promise> { - let match = postRegex.exec(text); - if (match) { - let [, title, content] = match; - return { - title, - mobiledoc: markdownToMobileDoc(await cleanMarkdown(content)), - }; - } - throw Error("Post should stat with a # header"); -} - -async function getConfig(): Promise { - let { text } = await readPage("ghost-config"); - let parsedContent = await parseMarkdown(text); - let pageMeta = await extractMeta(parsedContent); - return pageMeta as GhostConfig; -} - -export async function publishCommand() { - await invokeFunction( - "server", - "publish", - await getCurrentPage(), - await getText() - ); -} - -export async function publish(name: string, text: string) { - let config = await getConfig(); - let admin = new GhostAdmin(config.url, config.adminKey); - await admin.init(); - let post = await markdownToPost(text); - if (name.startsWith(config.postPrefix)) { - post.slug = name.substring(config.postPrefix.length + 1); - await admin.publishPost(post); - console.log("Done!"); - } else if (name.startsWith(config.pagePrefix)) { - post.slug = name.substring(config.pagePrefix.length + 1); - await admin.publishPage(post); - console.log("Done!"); - } else { - console.error("Not in either the post or page prefix"); - } -} diff --git a/packages/plugs/git/git.plug.yaml b/packages/plugs/git/git.plug.yaml deleted file mode 100644 index 34c7ea23..00000000 --- a/packages/plugs/git/git.plug.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: git -requiredPermissions: - - shell -functions: - snapshotCommand: - path: "./git.ts:snapshotCommand" - env: client - command: - name: "Git: Snapshot" - syncCommand: - path: "./git.ts:syncCommand" - env: client - command: - name: "Git: Sync" - commit: - path: "./git.ts:commit" - env: server - sync: - path: "./git.ts:sync" - env: server - diff --git a/packages/plugs/git/git.ts b/packages/plugs/git/git.ts deleted file mode 100644 index 542efc40..00000000 --- a/packages/plugs/git/git.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { run } from "@plugos/plugos-syscall/shell"; -import { - flashNotification, - prompt, -} from "@silverbulletmd/plugos-silverbullet-syscall/editor"; -import { invokeFunction } from "@silverbulletmd/plugos-silverbullet-syscall/system"; - -export async function commit(message?: string) { - if (!message) { - message = "Snapshot"; - } - console.log( - "Snapshotting the current space to git with commit message", - message - ); - await run("git", ["add", "./*.md"]); - try { - await run("git", ["commit", "-a", "-m", message]); - } catch (e) { - // We can ignore, this happens when there's no changes to commit - } - console.log("Done!"); -} - -export async function snapshotCommand() { - let revName = await prompt(`Revision name:`); - if (!revName) { - revName = "Snapshot"; - } - console.log("Revision name", revName); - await invokeFunction("server", "commit", revName); -} - -export async function syncCommand() { - await flashNotification("Syncing with git"); - await invokeFunction("server", "sync"); - await flashNotification("Git sync complete!"); -} - -export async function sync() { - console.log("Going to sync with git"); - await commit(); - console.log("Then pulling from remote"); - await run("git", ["pull"]); - console.log("And then pushing to remote"); - await run("git", ["push"]); - console.log("Done!"); -} diff --git a/packages/plugs/github/github.plug.yaml b/packages/plugs/github/github.plug.yaml deleted file mode 100644 index e561abf8..00000000 --- a/packages/plugs/github/github.plug.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: github -functions: - queryEvents: - path: ./github.ts:queryEvents - events: - - query:gh-events - queryIssues: - path: ./github.ts:queryPulls - events: - - query:gh-pulls diff --git a/packages/plugs/github/github.ts b/packages/plugs/github/github.ts deleted file mode 100644 index e147d43e..00000000 --- a/packages/plugs/github/github.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { applyQuery, QueryProviderEvent, renderQuery } from "../query/engine"; -import { readPage } from "@silverbulletmd/plugos-silverbullet-syscall/space"; -import { parseMarkdown } from "@silverbulletmd/plugos-silverbullet-syscall/markdown"; -import { extractMeta } from "../query/data"; - -type GithubEvent = { - id: string; - type: string; - actor: GithubUser; - repo: GithubRepo; - created_at: string; - payload: any; - org: GithubOrg; -}; - -type GithubUser = { - id: number; - login: string; - display_login: string; - url: string; -}; - -type GithubRepo = { - id: number; - name: string; - url: string; -}; - -type GithubOrg = { - id: number; - login: string; - url: string; -}; - -type ExposedEvent = { - id: string; - type: string; - username: string; - repo: string; -}; - -class GithubApi { - constructor(private token?: string) {} - - async apiCall(url: string, options: any = {}): Promise { - let res = await fetch(url, { - ...options, - headers: { - Authorization: this.token ? `token ${this.token}` : undefined, - }, - }); - if (res.status !== 200) { - throw new Error(await res.text()); - } - return res.json(); - } - - async listEvents(username: string): Promise { - return this.apiCall( - `https://api.github.com/users/${username}/events?per_page=100` - ); - } - - async listPulls( - repo: string, - state: string = "all", - sort: string = "updated" - ): Promise { - return this.apiCall( - `https://api.github.com/repos/${repo}/pulls?state=${state}&sort=${sort}&direction=desc&per_page=100` - ); - } - - static async fromConfig(): Promise { - return new GithubApi((await getConfig()).token); - } -} - -type GithubConfig = { - token?: string; -}; - -async function getConfig(): Promise { - try { - let { text } = await readPage("github-config"); - let parsedContent = await parseMarkdown(text); - let pageMeta = await extractMeta(parsedContent); - return pageMeta as GithubConfig; - } catch (e) { - console.error("No github-config page found, using default config"); - return {}; - } -} - -function mapEvent(event: GithubEvent): any { - // console.log("Event", event); - return { - ...event.payload, - id: event.id, - type: event.type, - username: event.actor.login, - repo: event.repo.name, - date: event.created_at.split("T")[0], - }; -} - -export async function queryEvents({ - query, -}: QueryProviderEvent): Promise { - let api = await GithubApi.fromConfig(); - let usernameFilter = query.filter.find((f) => f.prop === "username"); - if (!usernameFilter) { - throw Error("No 'username' filter specified, this is mandatory"); - } - let usernames: string[] = []; - if (usernameFilter.op === "=") { - usernames = [usernameFilter.value]; - } else if (usernameFilter.op === "in") { - usernames = usernameFilter.value; - } else { - throw new Error(`Unsupported operator ${usernameFilter.op}`); - } - let allEvents: GithubEvent[] = []; - for (let eventList of await Promise.all( - usernames.map((username) => api.listEvents(username)) - )) { - allEvents.push(...eventList); - } - // console.log("Usernames", usernames, "Event list lenght", allEvents[0]); - return applyQuery(query, allEvents.map(mapEvent)); -} - -function mapPull(pull: any): any { - // console.log("Pull", Object.keys(pull)); - return { - ...pull, - username: pull.user.login, - // repo: pull.repo.name, - createdAt: pull.created_at.split("T")[0], - updatedAt: pull.updated_at.split("T")[0], - }; -} - -export async function queryPulls({ - query, -}: QueryProviderEvent): Promise { - let api = await GithubApi.fromConfig(); - let repo = query.filter.find((f) => f.prop === "repo"); - if (!repo) { - throw Error("No 'repo' specified, this is mandatory"); - } - query.filter.splice(query.filter.indexOf(repo), 1); - let repos: string[] = []; - if (repo.op === "=") { - repos = [repo.value]; - } else if (repo.op === "in") { - repos = repo.value; - } else { - throw new Error(`Unsupported operator ${repo.op}`); - } - let allPulls: any[] = []; - for (let pullList of await Promise.all( - repos.map((repo) => api.listPulls(repo, "all", "updated")) - )) { - allPulls.push(...pullList); - } - allPulls = applyQuery(query, allPulls.map(mapPull)); - return allPulls; -} diff --git a/packages/plugs/mattermost/mattermost.plug.yaml b/packages/plugs/mattermost/mattermost.plug.yaml deleted file mode 100644 index 922a6d3c..00000000 --- a/packages/plugs/mattermost/mattermost.plug.yaml +++ /dev/null @@ -1,6 +0,0 @@ -name: mattermost -functions: - test: - path: mattermost.ts:savedPostsQueryProvider - events: - - query:mm-saved diff --git a/packages/plugs/mattermost/mattermost.ts b/packages/plugs/mattermost/mattermost.ts deleted file mode 100644 index 0bba9a54..00000000 --- a/packages/plugs/mattermost/mattermost.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Client4 } from "@mattermost/client"; -import { applyQuery, QueryProviderEvent } from "../query/engine"; -import { readPage } from "@silverbulletmd/plugos-silverbullet-syscall/space"; -import { parseMarkdown } from "@silverbulletmd/plugos-silverbullet-syscall/markdown"; -import { extractMeta } from "../query/data"; -import { niceDate } from "../core/dates"; -import { Post } from "@mattermost/types/lib/posts"; -import { ServerChannel } from "@mattermost/types/lib/channels"; -import { UserProfile } from "@mattermost/types/lib/users"; -import { Team } from "@mattermost/types/lib/teams"; - -type AugmentedPost = Post & { - // Dates we can use to filter - createdAt: string; - updatedAt: string; - editedAt: string; -}; - -// https://community.mattermost.com/private-core/pl/rbp7a7jtr3f89nzsefo6ftqt3o - -function mattermostDesktopUrlForPost( - url: string, - teamName: string, - postId: string -) { - return `${url.replace("https://", "mattermost://")}/${teamName}/pl/${postId}`; -} -type MattermostConfig = { - url: string; - token: string; - defaultTeam: string; -}; - -async function getConfig(): Promise { - let { text } = await readPage("mattermost-config"); - let parsedContent = await parseMarkdown(text); - let pageMeta = await extractMeta(parsedContent); - return pageMeta as MattermostConfig; -} - -function augmentPost(post: AugmentedPost) { - if (post.create_at) { - post.createdAt = niceDate(new Date(post.create_at)); - } - if (post.update_at) { - post.updatedAt = niceDate(new Date(post.update_at)); - } - if (post.edit_at) { - post.editedAt = niceDate(new Date(post.edit_at)); - } -} - -class CachingClient4 { - constructor(public client: Client4) {} - - private channelCache = new Map(); - async getChannelCached(channelId: string): Promise { - let channel = this.channelCache.get(channelId); - if (channel) { - return channel; - } - channel = await this.client.getChannel(channelId); - this.channelCache.set(channelId, channel!); - return channel!; - } - - private teamCache = new Map(); - async getTeamCached(teamId: string): Promise { - let team = this.teamCache.get(teamId); - if (team) { - return team; - } - team = await this.client.getTeam(teamId); - this.teamCache.set(teamId, team!); - return team!; - } - - private userCache = new Map(); - async getUserCached(userId: string): Promise { - let user = this.userCache.get(userId); - if (user) { - return user; - } - user = await this.client.getUser(userId); - this.userCache.set(userId, user!); - return user!; - } -} - -export async function savedPostsQueryProvider({ - query, -}: QueryProviderEvent): Promise { - let config = await getConfig(); - let client = new Client4(); - let cachingClient = new CachingClient4(client); - client.setUrl(config.url); - client.setToken(config.token); - let me = await client.getMe(); - let postCollection = await client.getFlaggedPosts(me.id); - let savedPosts: AugmentedPost[] = []; - for (let order of postCollection.order) { - let post = postCollection.posts[order]; - augmentPost(post); - savedPosts.push(post); - } - let resultSavedPosts = []; - savedPosts = applyQuery(query, savedPosts); - for (let savedPost of savedPosts) { - let channel = await cachingClient.getChannelCached(savedPost.channel_id); - let teamName = config.defaultTeam; - if (channel.team_id) { - let team = await cachingClient.getTeamCached(channel.team_id); - teamName = team.name; - } - resultSavedPosts.push({ - ...savedPost, - user: await cachingClient.getUserCached(savedPost.user_id), - channel: channel, - teamName: teamName, - url: mattermostDesktopUrlForPost(client.url, teamName, savedPost.id), - }); - } - return resultSavedPosts; -} diff --git a/packages/plugs/package.json b/packages/plugs/package.json index 646657ec..78c17e33 100644 --- a/packages/plugs/package.json +++ b/packages/plugs/package.json @@ -34,8 +34,6 @@ "@jest/globals": "^27.5.1", "@lezer/generator": "1.0.0", "@lezer/lr": "1.0.0", - "@mattermost/client": "^7.0.0", - "@mattermost/types": "^7.0.0", "@silverbulletmd/common": "^0.0.8", "@silverbulletmd/plugs": "^0.0.8", "@silverbulletmd/web": "^0.0.8",