discourse 2/3
This commit is contained in:
parent
8fd628f85f
commit
36f46ca292
5
packages/discourse-legacy/.gitignore
vendored
Normal file
5
packages/discourse-legacy/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/node_modules
|
||||
/coverage
|
||||
*.log
|
||||
.DS_Store
|
||||
tmp
|
||||
4
packages/discourse-legacy/.npmignore
Normal file
4
packages/discourse-legacy/.npmignore
Normal file
@ -0,0 +1,4 @@
|
||||
./docs
|
||||
./scripts
|
||||
./tests
|
||||
./incoming
|
||||
161
packages/discourse-legacy/README.md
Normal file
161
packages/discourse-legacy/README.md
Normal file
@ -0,0 +1,161 @@
|
||||
# Discourse library and CLI for OSR content
|
||||
|
||||
## Commands
|
||||
|
||||
### `info`
|
||||
|
||||
#### Print configuration and commands
|
||||
|
||||
```
|
||||
osr-discourse info
|
||||
```
|
||||
|
||||
### `deploy`
|
||||
|
||||
Create/Update post from directory, using OSR-Specs
|
||||
|
||||
**usage**
|
||||
|
||||
```sh
|
||||
|
||||
osr-discourse deploy --src="./*"
|
||||
|
||||
```
|
||||
|
||||
### `sync <file>`
|
||||
|
||||
Sync file
|
||||
|
||||
**usage**
|
||||
|
||||
```sh
|
||||
|
||||
osr-discourse sync <file>
|
||||
|
||||
--src="<filepath.HTML|MD|OSR / glob / pipe>"
|
||||
--cat=<category id>
|
||||
--owner="user_name|user_id"
|
||||
--config=<OSR Config Hash>
|
||||
--timestamp=<default=now>
|
||||
--download-assets=true|false
|
||||
--tags=<tag ids | tag names>
|
||||
|
||||
```
|
||||
|
||||
### `sync-kb`
|
||||
|
||||
Create/Update/Sync kb from directory
|
||||
|
||||
**usage**
|
||||
|
||||
```sh
|
||||
|
||||
osr-discourse sync --src="./*"
|
||||
|
||||
```
|
||||
|
||||
### `list`
|
||||
|
||||
List posts per category or search query
|
||||
|
||||
**usage**
|
||||
|
||||
```sh
|
||||
|
||||
osr-discourse list --query="discourse-query" --dst="output.[json|xls|csv]" --fields="[post-fields]"
|
||||
|
||||
```
|
||||
|
||||
### `oa-user-import`
|
||||
|
||||
Imports oa-users from dump file
|
||||
|
||||
**usage**
|
||||
|
||||
```sh
|
||||
|
||||
osr-discourse oa-user --src="raw.json"
|
||||
|
||||
```
|
||||
|
||||
### `ig-user-sync`
|
||||
|
||||
Imports IG users from dump file
|
||||
|
||||
**usage**
|
||||
|
||||
```sh
|
||||
|
||||
osr-discourse ig-user sync --src="raw.json"
|
||||
|
||||
```
|
||||
|
||||
### `osr-commons-sync`
|
||||
|
||||
Sync all osr-commons ( taxonomy )
|
||||
|
||||
**usage**
|
||||
|
||||
```sh
|
||||
|
||||
osr-discourse osr-sync --src="path to commons (JSON)"
|
||||
|
||||
```
|
||||
|
||||
### `pm`
|
||||
|
||||
Notify all users, using Discourse private message
|
||||
|
||||
**usage**
|
||||
|
||||
```sh
|
||||
|
||||
osr-discourse pm --src="path to message (MD|HTML)" --groups="osr groups"
|
||||
|
||||
```
|
||||
|
||||
### `invite`
|
||||
|
||||
Send invite to a list of users, common MC/OSR CSV format
|
||||
|
||||
**usage**
|
||||
|
||||
```sh
|
||||
|
||||
osr-discourse invite --src="path to message (MD|HTML)" --src="path to CSV"
|
||||
|
||||
```
|
||||
|
||||
## Library / API
|
||||
|
||||
## References
|
||||
|
||||
- [ts-json-schema-generator - issue - functions](https://github.com/loopingz/webda.io/blob/main/packages/shell/src/code/compiler.ts#L154-243)
|
||||
|
||||
### Todos
|
||||
|
||||
////////////////////////
|
||||
//
|
||||
// 1. Fetch Tags
|
||||
// 2. Populate Tags
|
||||
// 3. Download (oa-bot)
|
||||
// 4. Sync - Assets (osr-machines)
|
||||
// 5. Ensure/Find user
|
||||
//
|
||||
// Content
|
||||
//
|
||||
// Body (descr full)
|
||||
// each step
|
||||
// footer (refs)
|
||||
// set tags
|
||||
// set ts
|
||||
//
|
||||
// Post
|
||||
// -> sync lib
|
||||
// -> translate -> lib
|
||||
// -> digest
|
||||
// -> notifications
|
||||
// -> index
|
||||
// -> update ext refs
|
||||
// -> market place
|
||||
// -> sync externals (git, ...)
|
||||
3
packages/discourse-legacy/dist/_cli.d.ts
vendored
Normal file
3
packages/discourse-legacy/dist/_cli.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import { IOptions, IOptionsSync } from './types';
|
||||
export declare const defaults: () => void;
|
||||
export declare const sanitize: (argv: any) => IOptionsSync | IOptions | boolean;
|
||||
66
packages/discourse-legacy/dist/_cli.js
vendored
Normal file
66
packages/discourse-legacy/dist/_cli.js
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
import { sync as exists } from '@polymech/fs/exists';
|
||||
import { logger } from './';
|
||||
import * as path from 'path';
|
||||
const globBase = require('glob-base');
|
||||
export const defaults = () => {
|
||||
// default command
|
||||
const DefaultCommand = 'info';
|
||||
if (process.argv.length === 2) {
|
||||
process.argv.push(DefaultCommand);
|
||||
}
|
||||
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
|
||||
// currently no default handler, display only :
|
||||
process.on('unhandledRejection', (reason) => {
|
||||
console.error('Unhandled rejection, reason: ', reason);
|
||||
});
|
||||
};
|
||||
export const sanitize = (argv) => {
|
||||
let ret = {
|
||||
...argv
|
||||
};
|
||||
ret.src = argv.src;
|
||||
let srcInfo;
|
||||
let variables = {};
|
||||
/*
|
||||
if (ret.src) {
|
||||
ret.src = forward_slash(substitute(ret.alt,ret.src,variables))
|
||||
// in case a file with a glob pattern is provided, strip the glob
|
||||
// this is a special case, enabling shared scripts in Alt-Tap Salamand
|
||||
const glob_base = globBase(ret.src)
|
||||
const file = ret.src.replace(glob_base.glob, '').replace(/\/$/, '')
|
||||
|
||||
if(exists(file) && isFile(file)){
|
||||
ret.src = file
|
||||
}
|
||||
|
||||
srcInfo = pathInfo(resolve(ret.src, ret.alt, variables))
|
||||
|
||||
if (srcInfo && srcInfo.FILES && srcInfo.FILES.length) {
|
||||
ret.srcInfo = srcInfo
|
||||
for (const key in srcInfo) {
|
||||
if (Object.prototype.hasOwnProperty.call(srcInfo, key)) {
|
||||
variables['SRC_' + key] = srcInfo[key];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret.src = resolve(ret.src, ret.alt, variables)
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (argv.cwd) {
|
||||
ret.cwd = path.resolve(argv.cwd);
|
||||
if (!exists((ret.cwd))) {
|
||||
logger.error(`Invalid working directory ${argv.cwd}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret.cwd = process.cwd();
|
||||
}
|
||||
ret = {
|
||||
...ret,
|
||||
variables,
|
||||
srcInfo
|
||||
};
|
||||
return ret;
|
||||
};
|
||||
//# sourceMappingURL=_cli.js.map
|
||||
1
packages/discourse-legacy/dist/_cli.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/_cli.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"_cli.js","sourceRoot":"","sources":["../src/_cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAA;AAC3B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAO5B,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;AAErC,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,EAAE;IACzB,kBAAkB;IAClB,MAAM,cAAc,GAAG,MAAM,CAAC;IAC9B,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QAC3B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;KACrC;IAED,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,GAAG,GAAG,CAAC;IAElD,+CAA+C;IAC/C,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAc,EAAE,EAAE;QAChD,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAS,EAAqC,EAAE;IAErE,IAAI,GAAG,GAAQ;QACX,GAAG,IAAI;KACV,CAAA;IAED,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAA;IAClB,IAAI,OAAO,CAAA;IACX,IAAI,SAAS,GAAG,EAAE,CAAA;IAElB;;;;;;;;;;;;;;;;;;;;;;;;;MAyBE;IAEF,IAAI,IAAI,CAAC,GAAG,EAAE;QACV,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE;YACpB,MAAM,CAAC,KAAK,CAAC,6BAA6B,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;SACxD;KACJ;SAAM;QACH,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;KAC1B;IAED,GAAG,GAAG;QACF,GAAG,GAAG;QACN,SAAS;QACT,OAAO;KACV,CAAA;IAED,OAAO,GAAG,CAAA;AACd,CAAC,CAAA"}
|
||||
2
packages/discourse-legacy/dist/commands/import-oa-howtos.d.ts
vendored
Normal file
2
packages/discourse-legacy/dist/commands/import-oa-howtos.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import * as CLI from 'yargs';
|
||||
export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
|
||||
49
packages/discourse-legacy/dist/commands/import-oa-howtos.js
vendored
Normal file
49
packages/discourse-legacy/dist/commands/import-oa-howtos.js
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
import { defaults } from '../_cli';
|
||||
import { logger } from '../index';
|
||||
import { Instance } from '../lib/discourse';
|
||||
import { read_howtos, filter_valid } from '../lib/oa/commons';
|
||||
import { importHowtos, updateHowtos } from '../lib/oa/howtos';
|
||||
import * as path from 'path';
|
||||
import { resolve } from '@polymech/commons';
|
||||
const KB_ROOT = '${KB_ROOT}';
|
||||
import { OA_LATEST } from '@polymech/commons';
|
||||
const defaultOptions = (yargs) => {
|
||||
return yargs.option('debug', {
|
||||
default: true,
|
||||
describe: 'debug messages',
|
||||
type: 'boolean'
|
||||
}).option('src', {
|
||||
default: OA_LATEST,
|
||||
type: 'string',
|
||||
}).option('track', {
|
||||
default: '${OA_ROOT}/oa-data/howtos/latest_track.json',
|
||||
type: 'string',
|
||||
}).option('env_key', {
|
||||
default: 'OSR-CONFIG',
|
||||
describe: 'Environment key to the config path.'
|
||||
});
|
||||
};
|
||||
let options = (yargs) => defaultOptions(yargs);
|
||||
export const register = (cli) => {
|
||||
return cli.command('import-howtos', 'Import oa-howtos', options, async (argv) => {
|
||||
defaults();
|
||||
if (argv.help) {
|
||||
return;
|
||||
}
|
||||
let options = argv;
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
options.debug && logger.debug(`CLI Args In`, argv);
|
||||
const discourse = Instance();
|
||||
const _opts = {
|
||||
src: path.resolve(resolve(options.src)),
|
||||
track: path.resolve(resolve(options.track))
|
||||
};
|
||||
let howtos = read_howtos(_opts.src);
|
||||
howtos = filter_valid(howtos);
|
||||
await importHowtos(discourse, _opts, howtos);
|
||||
await updateHowtos(discourse, _opts, howtos);
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=import-oa-howtos.js.map
|
||||
1
packages/discourse-legacy/dist/commands/import-oa-howtos.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/commands/import-oa-howtos.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"import-oa-howtos.js","sourceRoot":"","sources":["../../src/commands/import-oa-howtos.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAY,MAAM,SAAS,CAAA;AAE5C,OAAO,EAAE,MAAM,EAAe,MAAM,UAAU,CAAA;AAE9C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAe3C,OAAO,EAEH,WAAW,EAEX,YAAY,EACf,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EACH,YAAY,EAAE,YAAY,EAC7B,MAAM,kBAAkB,CAAA;AAQzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAG3C,MAAM,OAAO,GAAG,YAAY,CAAA;AAQ5B,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAE7C,MAAM,cAAc,GAAG,CAAC,KAAe,EAAE,EAAE;IACvC,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE;QACzB,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,gBAAgB;QAC1B,IAAI,EAAE,SAAS;KAClB,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE;QACb,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,QAAQ;KACjB,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE;QACf,OAAO,EAAE,6CAA6C;QACtD,IAAI,EAAE,QAAQ;KACjB,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE;QACjB,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,qCAAqC;KAClD,CAAC,CAAA;AACN,CAAC,CAAA;AAED,IAAI,OAAO,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;AAExD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAa,EAAE,EAAE;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,kBAAkB,EAAE,OAAO,EAAE,KAAK,EAAE,IAAmB,EAAE,EAAE;QAC3F,QAAQ,EAAE,CAAA;QACV,IAAI,IAAI,CAAC,IAAI,EAAE;YAAE,OAAM;SAAE;QACzB,IAAI,OAAO,GAAI,IAAwB,CAAA;QAEvC,IAAI,CAAC,OAAO,EAAE;YACV,OAAM;SACT;QACD,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,IAAI,CAAC,CAAA;QAElD,MAAM,SAAS,GAAG,QAAQ,EAAE,CAAA;QAE5B,MAAM,KAAK,GAAG;YACV,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACvC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SAClC,CAAA;QAEb,IAAI,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACnC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAC7B,MAAM,YAAY,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;QAC5C,MAAM,YAAY,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"}
|
||||
2
packages/discourse-legacy/dist/commands/import-oa-users.d.ts
vendored
Normal file
2
packages/discourse-legacy/dist/commands/import-oa-users.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import * as CLI from 'yargs';
|
||||
export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
|
||||
84
packages/discourse-legacy/dist/commands/import-oa-users.js
vendored
Normal file
84
packages/discourse-legacy/dist/commands/import-oa-users.js
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
import { defaults, sanitize } from '../_cli';
|
||||
import { parse } from '../options';
|
||||
import { logger } from '../index';
|
||||
import { Instance } from '../lib/discourse';
|
||||
import { sync as write } from '@polymech/fs/write';
|
||||
import { read_users, filter_invalid, filter_email_missing, filter_email_only, importUsers, filter_valid, oa_user_email, getDataPath, updateUsers, indexUsers } from '../lib/oa/users';
|
||||
import * as path from 'path';
|
||||
import { resolve } from '@polymech/commons';
|
||||
const defaultOptions = (yargs) => {
|
||||
return yargs.option('debug', {
|
||||
default: false,
|
||||
describe: 'debug messages',
|
||||
type: 'boolean'
|
||||
}).option('src', {
|
||||
default: '${OA_ROOT}/data/latest.json',
|
||||
type: 'string',
|
||||
}).option('track', {
|
||||
default: '${OSR_ROOT}/osr-directory/pp/merged.json',
|
||||
type: 'string',
|
||||
}).option('env_key', {
|
||||
default: 'OSR-CONFIG',
|
||||
describe: 'Environment key to the config path.'
|
||||
});
|
||||
};
|
||||
let options = (yargs) => defaultOptions(yargs);
|
||||
export const register = (cli) => {
|
||||
return cli.command('import-users <verb>', 'Import oa-users', options, async (argv) => {
|
||||
defaults();
|
||||
if (argv.help) {
|
||||
return;
|
||||
}
|
||||
const args = argv;
|
||||
let options = sanitize(argv);
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
options.debug && logger.debug(`CLI Args In`, argv);
|
||||
let opts = parse(options, args);
|
||||
const discourse = Instance();
|
||||
const _opts = {
|
||||
verb: argv.verb,
|
||||
src: path.resolve(resolve(options.src)),
|
||||
track: path.resolve(resolve(options.track))
|
||||
};
|
||||
let users = read_users(_opts.src);
|
||||
users = filter_valid(users);
|
||||
//////////////////////////
|
||||
//
|
||||
// store invalid
|
||||
let usersInvalid = read_users(_opts.src);
|
||||
usersInvalid = filter_email_only(usersInvalid);
|
||||
usersInvalid = filter_invalid(usersInvalid);
|
||||
logger.debug('write invalidUsers.json : ', getDataPath('/invalidUsers.json'));
|
||||
write(getDataPath('/invalidUsers.json'), usersInvalid.map((u) => {
|
||||
return {
|
||||
...u.detail,
|
||||
id: u._id,
|
||||
email: oa_user_email(u)
|
||||
};
|
||||
}));
|
||||
let usersInvalidEmail = read_users(_opts.src);
|
||||
usersInvalidEmail = filter_email_missing(usersInvalidEmail);
|
||||
logger.debug('write invalidUsersEMail.json : ', getDataPath('/invalidUsersEMail.json'));
|
||||
write(getDataPath('./invalidUsersEMail.json'), usersInvalidEmail.map((u) => {
|
||||
return {
|
||||
...u.detail,
|
||||
id: u._id
|
||||
};
|
||||
}));
|
||||
logger.debug('invalid users email : ', usersInvalidEmail.length);
|
||||
logger.debug('invalid users : ', usersInvalid.length);
|
||||
if (opts.verb == 'index') {
|
||||
await indexUsers(discourse, options, users);
|
||||
}
|
||||
if (opts.verb == 'import') {
|
||||
await importUsers(discourse, options, users);
|
||||
}
|
||||
if (opts.verb == 'update') {
|
||||
await updateUsers(discourse, options, users);
|
||||
}
|
||||
return;
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=import-oa-users.js.map
|
||||
1
packages/discourse-legacy/dist/commands/import-oa-users.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/commands/import-oa-users.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"import-oa-users.js","sourceRoot":"","sources":["../../src/commands/import-oa-users.ts"],"names":[],"mappings":"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"}
|
||||
2
packages/discourse-legacy/dist/commands/info.d.ts
vendored
Normal file
2
packages/discourse-legacy/dist/commands/info.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import * as CLI from 'yargs';
|
||||
export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
|
||||
23
packages/discourse-legacy/dist/commands/info.js
vendored
Normal file
23
packages/discourse-legacy/dist/commands/info.js
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
import { CONFIG_DEFAULT } from '@polymech/commons';
|
||||
import { logger } from '../index';
|
||||
const defaultOptions = (yargs) => {
|
||||
return yargs.option('debug', {
|
||||
default: 'false',
|
||||
describe: 'debug messages'
|
||||
}).option('env_key', {
|
||||
default: 'OSR-CONFIG',
|
||||
describe: 'Environment key to the config path'
|
||||
});
|
||||
};
|
||||
let options = (yargs) => defaultOptions(yargs);
|
||||
export const register = (cli) => {
|
||||
return cli.command('info', 'info', options, async (argv) => {
|
||||
if (argv.help) {
|
||||
return;
|
||||
}
|
||||
const args = argv;
|
||||
const src = CONFIG_DEFAULT(args.env_key);
|
||||
logger.debug(`Reading OSR Config with key "${argv.env_key}"`, src);
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=info.js.map
|
||||
1
packages/discourse-legacy/dist/commands/info.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/commands/info.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,MAAM,cAAc,GAAG,CAAC,KAAe,EAAE,EAAE;IACvC,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE;QACzB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,gBAAgB;KAC7B,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE;QACjB,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,oCAAoC;KACjD,CAAC,CAAA;AACN,CAAC,CAAA;AAED,IAAI,OAAO,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;AAEzD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAa,EAAE,EAAE;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAmB,EAAE,EAAE;QACtE,IAAI,IAAI,CAAC,IAAI,EAAE;YAAE,OAAM;SAAE;QACzB,MAAM,IAAI,GAAQ,IAAI,CAAA;QACtB,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACxC,MAAM,CAAC,KAAK,CAAC,gCAAgC,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,CAAC,CAAA;IACtE,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"}
|
||||
2
packages/discourse-legacy/dist/commands/query.d.ts
vendored
Normal file
2
packages/discourse-legacy/dist/commands/query.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import * as CLI from 'yargs';
|
||||
export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
|
||||
52
packages/discourse-legacy/dist/commands/query.js
vendored
Normal file
52
packages/discourse-legacy/dist/commands/query.js
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
import { defaults, sanitize } from '../_cli';
|
||||
import { parse } from '../options';
|
||||
import { logger } from '../index';
|
||||
import { Instance } from '../lib/discourse';
|
||||
const defaultOptions = (yargs) => {
|
||||
return yargs.option('debug', {
|
||||
default: false,
|
||||
describe: 'debug messages',
|
||||
type: 'boolean'
|
||||
}).option('short', {
|
||||
default: 'true',
|
||||
describe: 'Emit short info only',
|
||||
type: 'boolean'
|
||||
}).option('disabled', {
|
||||
default: 'false',
|
||||
describe: 'Enumerate disabled products',
|
||||
type: 'boolean'
|
||||
}).option('dry', {
|
||||
default: 'false',
|
||||
describe: 'Process files for debug purposes only.'
|
||||
}).option('env_key', {
|
||||
default: 'OSR-CONFIG',
|
||||
describe: 'Environment key to the config path.'
|
||||
});
|
||||
};
|
||||
let options = (yargs) => defaultOptions(yargs);
|
||||
export const register = (cli) => {
|
||||
return cli.command('query <verb>', 'Search namespace', options, async (argv) => {
|
||||
defaults();
|
||||
if (argv.help) {
|
||||
return;
|
||||
}
|
||||
const args = argv;
|
||||
let options = sanitize(argv);
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
options.debug && logger.debug(`CLI Args In`, argv);
|
||||
let opts = parse(options, args);
|
||||
if (!opts.verb) {
|
||||
logger.error('No verb specified');
|
||||
return;
|
||||
}
|
||||
const discourse = Instance();
|
||||
if (opts.verb == 'tags') {
|
||||
const items = await discourse.search('Sheetpress - Cell', 'tags:sheetpress');
|
||||
logger.info('items', items);
|
||||
}
|
||||
return;
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=query.js.map
|
||||
1
packages/discourse-legacy/dist/commands/query.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/commands/query.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE3C,MAAM,cAAc,GAAG,CAAC,KAAe,EAAE,EAAE;IACvC,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE;QACzB,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,gBAAgB;QAC1B,IAAI,EAAE,SAAS;KAClB,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE;QACf,OAAO,EAAE,MAAM;QACf,QAAQ,EAAE,sBAAsB;QAChC,IAAI,EAAE,SAAS;KAClB,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE;QAClB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,6BAA6B;QACvC,IAAI,EAAE,SAAS;KAClB,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE;QACb,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,wCAAwC;KACrD,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE;QACjB,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,qCAAqC;KAClD,CAAC,CAAA;AACN,CAAC,CAAA;AAED,IAAI,OAAO,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;AAExD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAa,EAAE,EAAE;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,kBAAkB,EAAE,OAAO,EAAE,KAAK,EAAE,IAAmB,EAAE,EAAE;QAC1F,QAAQ,EAAE,CAAC;QACX,IAAI,IAAI,CAAC,IAAI,EAAE;YAAE,OAAM;SAAE;QACzB,MAAM,IAAI,GAAQ,IAAI,CAAA;QAEtB,IAAI,OAAO,GAAG,QAAQ,CAAC,IAAW,CAAa,CAAA;QAE/C,IAAI,CAAC,OAAO,EAAE;YACV,OAAM;SACT;QACD,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,IAAI,CAAC,CAAA;QAClD,IAAI,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;QAE/B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YACZ,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;YACjC,OAAO;SACV;QACD,MAAM,SAAS,GAAG,QAAQ,EAAE,CAAA;QAC5B,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,EAAE;YACrB,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,mBAAmB,EAAC,iBAAiB,CAAC,CAAC;YAC5E,MAAM,CAAC,IAAI,CAAC,OAAO,EAAC,KAAK,CAAC,CAAA;SAC7B;QACD,OAAM;IACV,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"}
|
||||
4
packages/discourse-legacy/dist/commands/sync-component.d.ts
vendored
Normal file
4
packages/discourse-legacy/dist/commands/sync-component.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import * as CLI from 'yargs';
|
||||
import { IOptionsSyncComponent } from '../types';
|
||||
export declare const parse: (argv: any) => IOptionsSyncComponent | boolean;
|
||||
export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
|
||||
119
packages/discourse-legacy/dist/commands/sync-component.js
vendored
Normal file
119
packages/discourse-legacy/dist/commands/sync-component.js
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
import * as path from 'path';
|
||||
import { forward_slash, pathInfo } from "@polymech/commons";
|
||||
import { resolve, isFile } from '@polymech/commons';
|
||||
import { sync as exists } from '@polymech/fs/exists';
|
||||
import { CAT_TEST, DEFAULT_IMPORT_OWNER } from '../lib/discourse/constants';
|
||||
import { defaults } from '../_cli';
|
||||
import { logger } from '../index';
|
||||
import { syncComponent } from '../lib/sync/component';
|
||||
import { PFilterValid } from '@plastichub/osr-fs-utils';
|
||||
const globBase = require('glob-base');
|
||||
export const parse = (argv) => {
|
||||
let ret = {
|
||||
...argv
|
||||
};
|
||||
let srcInfo;
|
||||
let variables = {};
|
||||
ret.src = argv.src;
|
||||
ret.source = resolve(forward_slash(ret.source), ret.alt, variables);
|
||||
ret.root = resolve(forward_slash(ret.root), ret.alt, variables);
|
||||
ret.product_root = resolve(forward_slash(ret.product_root), ret.alt, variables);
|
||||
if (ret.src) {
|
||||
ret.src = resolve(ret.src, ret.alt, variables);
|
||||
// in case a file with a glob pattern is provided, strip the glob
|
||||
// this is a special case, enabling shared scripts in Alt-Tap Salamand
|
||||
const glob_base = globBase(ret.src);
|
||||
const file = ret.src.replace(glob_base.glob, '').replace(/\/$/, '');
|
||||
// case : single file
|
||||
if (exists(file) && isFile(file)) {
|
||||
ret.src = file;
|
||||
}
|
||||
const src = resolve(forward_slash(ret.src), ret.alt, variables);
|
||||
srcInfo = pathInfo(src);
|
||||
// case : glob pattern
|
||||
if (srcInfo && srcInfo.FILES && srcInfo.FILES.length) {
|
||||
ret.srcInfo = srcInfo;
|
||||
for (const key in srcInfo) {
|
||||
if (Object.prototype.hasOwnProperty.call(srcInfo, key)) {
|
||||
variables['SRC_' + key] = srcInfo[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret.src = resolve(ret.src, ret.alt, variables);
|
||||
}
|
||||
}
|
||||
if (argv.cwd) {
|
||||
ret.cwd = path.resolve(argv.cwd);
|
||||
if (!exists((ret.cwd))) {
|
||||
logger.error(`Invalid working directory ${argv.cwd}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret.cwd = process.cwd();
|
||||
}
|
||||
ret = {
|
||||
...ret,
|
||||
variables,
|
||||
srcInfo
|
||||
};
|
||||
return ret;
|
||||
};
|
||||
const defaultOptions = (yargs) => {
|
||||
return yargs
|
||||
//standard options
|
||||
.option('alt', { type: 'boolean', default: false, describe: 'alt token (%)' })
|
||||
//discourse
|
||||
.option('yaml', { type: 'boolean', default: false, describe: 'Parse options from YAML header' })
|
||||
.option('skip', { type: 'boolean', default: true, describe: 'Skip existing' })
|
||||
.option('uploadLocal', { type: 'boolean', default: true, describe: 'Upload local images to Discourse' })
|
||||
.option('uploadRemote', { type: 'boolean', default: true, describe: 'Upload remote images to Discourse' })
|
||||
.option('title', { type: 'string', default: 'Title of the Discourse post' })
|
||||
.option('cat', { default: CAT_TEST, type: 'number' })
|
||||
.option('timestamp', { type: 'number', default: Date.now() })
|
||||
.option('owner', { type: 'number', default: DEFAULT_IMPORT_OWNER })
|
||||
.option('config', { type: 'string', default: 'discourse_admin' })
|
||||
//osrl
|
||||
.option('src', {
|
||||
default: '${OSR_ROOT}/osr-machines/injection/**/config.json',
|
||||
type: 'string',
|
||||
describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
|
||||
})
|
||||
.option('src2', {
|
||||
default: '${OSR_ROOT}/osr-machines/sheetpress/cassandra-light/config.json',
|
||||
type: 'string',
|
||||
describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
|
||||
})
|
||||
.option('env', { type: 'string', default: 'forum' })
|
||||
.option('profile', { type: 'string', default: "${OSR_ROOT}/osr-templates/discourse/base.json" })
|
||||
.option('format', { type: 'string', default: 'md' })
|
||||
.option('source', { type: 'string', default: "${OSR_ROOT}/osr-templates/discourse/root.html" })
|
||||
.option('language', { type: 'string', default: 'osr' })
|
||||
.option('plugins', { type: 'string', default: '${root}/osr/plugins' })
|
||||
.option('root', { type: 'string', default: process.cwd() })
|
||||
.option('product_root', { type: 'string', default: '${PRODUCT_ROOT}/products' })
|
||||
.option('cwd', { type: 'string', default: process.cwd() })
|
||||
.option('module', { type: 'string', default: 'osr-lib-components' })
|
||||
.option('filter', { type: 'string', default: PFilterValid.library_component })
|
||||
.option('cache', { type: 'boolean', default: true })
|
||||
.option('env_key', { type: 'string', default: 'OSR-CONFIG', describe: 'Environment key to the config path.' });
|
||||
};
|
||||
let options = (yargs) => defaultOptions(yargs);
|
||||
export const register = (cli) => {
|
||||
return cli.command('sync-component', 'Sync OSR Component', options, async (argv) => {
|
||||
defaults();
|
||||
if (argv.help) {
|
||||
return;
|
||||
}
|
||||
let options = parse(argv);
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
logger.setSettings({ minLevel: argv.logLevel });
|
||||
// options.debug && logger.debug(`CLI Args In`, argv)
|
||||
logger.debug('Options', options);
|
||||
let ret = syncComponent(options);
|
||||
return ret;
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=sync-component.js.map
|
||||
1
packages/discourse-legacy/dist/commands/sync-component.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/commands/sync-component.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
4
packages/discourse-legacy/dist/commands/sync-directory.d.ts
vendored
Normal file
4
packages/discourse-legacy/dist/commands/sync-directory.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import * as CLI from 'yargs';
|
||||
import { IOptionsSyncComponent } from '../types';
|
||||
export declare const parse: (argv: any) => IOptionsSyncComponent | boolean;
|
||||
export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
|
||||
118
packages/discourse-legacy/dist/commands/sync-directory.js
vendored
Normal file
118
packages/discourse-legacy/dist/commands/sync-directory.js
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
import * as path from 'path';
|
||||
import { forward_slash, pathInfo } from "@polymech/commons";
|
||||
import { resolve, isFile } from '@polymech/commons';
|
||||
import { sync as exists } from '@polymech/fs/exists';
|
||||
import { CAT_TEST, DEFAULT_IMPORT_OWNER } from '../lib/discourse/constants';
|
||||
import { defaults } from '../_cli';
|
||||
import { logger } from '../index';
|
||||
import { syncComponent } from '../lib/sync/component';
|
||||
import { PFilterValid } from '@plastichub/osr-fs-utils';
|
||||
const globBase = require('glob-base');
|
||||
export const parse = (argv) => {
|
||||
let ret = {
|
||||
...argv
|
||||
};
|
||||
ret.src = argv.src;
|
||||
let srcInfo;
|
||||
let variables = {};
|
||||
ret.source = resolve(forward_slash(ret.source), ret.alt, variables);
|
||||
ret.root = resolve(forward_slash(ret.root), ret.alt, variables);
|
||||
if (ret.src) {
|
||||
ret.src = resolve(ret.src, ret.alt, variables);
|
||||
// in case a file with a glob pattern is provided, strip the glob
|
||||
// this is a special case, enabling shared scripts in Alt-Tap Salamand
|
||||
const glob_base = globBase(ret.src);
|
||||
const file = ret.src.replace(glob_base.glob, '').replace(/\/$/, '');
|
||||
// case : single file
|
||||
if (exists(file) && isFile(file)) {
|
||||
ret.src = file;
|
||||
}
|
||||
const src = resolve(forward_slash(ret.src), ret.alt, variables);
|
||||
srcInfo = pathInfo(src);
|
||||
// case : glob pattern
|
||||
if (srcInfo && srcInfo.FILES && srcInfo.FILES.length) {
|
||||
ret.srcInfo = srcInfo;
|
||||
for (const key in srcInfo) {
|
||||
if (Object.prototype.hasOwnProperty.call(srcInfo, key)) {
|
||||
variables['SRC_' + key] = srcInfo[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret.src = resolve(ret.src, ret.alt, variables);
|
||||
}
|
||||
}
|
||||
if (argv.cwd) {
|
||||
ret.cwd = path.resolve(argv.cwd);
|
||||
if (!exists((ret.cwd))) {
|
||||
logger.error(`Invalid working directory ${argv.cwd}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret.cwd = process.cwd();
|
||||
}
|
||||
ret = {
|
||||
...ret,
|
||||
variables,
|
||||
srcInfo
|
||||
};
|
||||
return ret;
|
||||
};
|
||||
const defaultOptions = (yargs) => {
|
||||
return yargs
|
||||
//standard options
|
||||
.option('debug', { type: 'boolean', default: true, describe: 'debug messages' })
|
||||
.option('verbose', { type: 'boolean', default: true, describe: 'even more debug messages' })
|
||||
.option('alt', { type: 'boolean', default: false, describe: 'alt token (%)' })
|
||||
//discourse
|
||||
.option('yaml', { type: 'boolean', default: false, describe: 'Parse options from YAML header' })
|
||||
.option('uploadLocal', { type: 'boolean', default: true, describe: 'Upload local images to Discourse' })
|
||||
.option('uploadRemote', { type: 'boolean', default: true, describe: 'Upload remote images to Discourse' })
|
||||
.option('title', { type: 'string', default: 'Title of the Discourse post' })
|
||||
.option('cat', { default: CAT_TEST, type: 'number' })
|
||||
.option('timestamp', { type: 'number', default: Date.now() })
|
||||
.option('owner', { type: 'number', default: DEFAULT_IMPORT_OWNER })
|
||||
.option('config', { type: 'string', default: 'discourse_admin' })
|
||||
//osrl
|
||||
.option('src2', {
|
||||
default: '${OSR_ROOT}/osr-machines/injection/**/config.json',
|
||||
type: 'string',
|
||||
describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
|
||||
})
|
||||
.option('src', {
|
||||
default: '${OSR_ROOT}/osr-machines/sheetpress/cassandra-light/config.json',
|
||||
type: 'string',
|
||||
describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
|
||||
})
|
||||
.option('env', { type: 'string', default: 'forum' })
|
||||
.option('profile', { type: 'string', default: "${OSR_ROOT}/osr-templates/discourse/base.json" })
|
||||
.option('format', { type: 'string', default: 'md' })
|
||||
.option('source', { type: 'string', default: "${OSR_ROOT}/osr-templates/discourse/root.html" })
|
||||
.option('language', { type: 'string', default: 'osr' })
|
||||
.option('plugins', { type: 'string', default: '${root}/osr/plugins' })
|
||||
.option('root', { type: 'string', default: process.cwd() })
|
||||
.option('product_root', { type: 'string', default: '${PRODUCT_ROOT}/products' })
|
||||
.option('cwd', { type: 'string', default: process.cwd() })
|
||||
.option('module', { type: 'string', default: 'osr-lib-components' })
|
||||
.option('filter', { type: 'string', default: PFilterValid.library_component })
|
||||
.option('cache', { type: 'boolean', default: true })
|
||||
.option('env_key', { type: 'string', default: 'OSR-CONFIG', describe: 'Environment key to the config path.' });
|
||||
};
|
||||
let options = (yargs) => defaultOptions(yargs);
|
||||
export const register = (cli) => {
|
||||
return cli.command('sync-component', 'Sync OSR Component', options, async (argv) => {
|
||||
defaults();
|
||||
if (argv.help) {
|
||||
return;
|
||||
}
|
||||
let options = parse(argv);
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
// options.debug && logger.debug(`CLI Args In`, argv)
|
||||
// logger.debug('Options', options)
|
||||
let ret = syncComponent(options);
|
||||
return ret;
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=sync-directory.js.map
|
||||
1
packages/discourse-legacy/dist/commands/sync-directory.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/commands/sync-directory.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
packages/discourse-legacy/dist/commands/sync-file.d.ts
vendored
Normal file
2
packages/discourse-legacy/dist/commands/sync-file.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import * as CLI from 'yargs';
|
||||
export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
|
||||
51
packages/discourse-legacy/dist/commands/sync-file.js
vendored
Normal file
51
packages/discourse-legacy/dist/commands/sync-file.js
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
import { defaults, sanitize } from '../_cli';
|
||||
import { logger } from '../index';
|
||||
import { syncYAML } from '../lib/sync/file';
|
||||
import { CAT_TEST, DEFAULT_IMPORT_OWNER } from '../lib/discourse/constants';
|
||||
const defaultOptions = (yargs) => {
|
||||
return yargs
|
||||
.option('debug', { type: 'boolean', default: true, describe: 'debug messages' })
|
||||
.option('verbose', { type: 'boolean', default: true, describe: 'even more debug messages' })
|
||||
.option('yaml', { type: 'boolean', default: true, describe: 'Parse options from YAML header' })
|
||||
.option('alt', { type: 'boolean', default: false, describe: 'alt token (%)' })
|
||||
.option('uploadLocal', { type: 'boolean', default: true, describe: 'Upload local images to Discourse' })
|
||||
.option('uploadRemote', { type: 'boolean', default: true, describe: 'Upload remote images to Discourse' })
|
||||
.option('src', {
|
||||
default: './tests/**/*.md',
|
||||
type: 'string',
|
||||
describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
|
||||
})
|
||||
.option('title', { type: 'string', default: 'Title of the Discourse post' })
|
||||
.option('config', { type: 'string', default: 'osr_admin' })
|
||||
.option('cat', { default: CAT_TEST, type: 'number' })
|
||||
.option('timestamp', { type: 'number', default: Date.now() })
|
||||
.option('owner', { type: 'number', default: DEFAULT_IMPORT_OWNER })
|
||||
.option('config', { type: 'string', default: 'discourse_admin' })
|
||||
.option('env', { type: 'string', default: 'test-import' })
|
||||
.option('profile', { type: 'string', default: "${OSR_ROOT}/osr-profiles/osr/base.json" })
|
||||
.option('format', { type: 'string', default: 'html' })
|
||||
.option('root', { type: 'string', default: process.cwd() })
|
||||
.option('cwd', { type: 'string', default: process.cwd() })
|
||||
.option('cache', { type: 'boolean', default: true })
|
||||
.option('env_key', { type: 'string', default: 'OSR-CONFIG', describe: 'Environment key to the config path.' });
|
||||
};
|
||||
let options = (yargs) => defaultOptions(yargs);
|
||||
export const register = (cli) => {
|
||||
return cli.command('sync <verb>', 'Sync file', options, async (argv) => {
|
||||
defaults();
|
||||
if (argv.help) {
|
||||
return;
|
||||
}
|
||||
let options = sanitize(argv);
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
options.debug && logger.debug(`CLI Args In`, argv);
|
||||
if (!options.verb) {
|
||||
logger.error('No verb specified');
|
||||
return;
|
||||
}
|
||||
return syncYAML(options);
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=sync-file.js.map
|
||||
1
packages/discourse-legacy/dist/commands/sync-file.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/commands/sync-file.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"sync-file.js","sourceRoot":"","sources":["../../src/commands/sync-file.ts"],"names":[],"mappings":"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"}
|
||||
1
packages/discourse-legacy/dist/constants.d.ts
vendored
Normal file
1
packages/discourse-legacy/dist/constants.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare const MODULE_NAME = "OSR-DISCOURSE";
|
||||
2
packages/discourse-legacy/dist/constants.js
vendored
Normal file
2
packages/discourse-legacy/dist/constants.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export const MODULE_NAME = `OSR-DISCOURSE`;
|
||||
//# sourceMappingURL=constants.js.map
|
||||
1
packages/discourse-legacy/dist/constants.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/constants.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAA"}
|
||||
8
packages/discourse-legacy/dist/index.d.ts
vendored
Normal file
8
packages/discourse-legacy/dist/index.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
export * from './constants';
|
||||
export * from './types';
|
||||
export * from './lib';
|
||||
export * from './lib/oa/types';
|
||||
export { Logger } from 'tslog';
|
||||
export declare const logger: any;
|
||||
import { IObjectLiteral } from "@polymech/core";
|
||||
export declare const substitute: (alt: boolean, template: string, vars?: IObjectLiteral) => any;
|
||||
70
packages/discourse-legacy/dist/index.js
vendored
Normal file
70
packages/discourse-legacy/dist/index.js
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
export * from './constants';
|
||||
export * from './types';
|
||||
export * from './lib';
|
||||
export * from './lib/oa/types';
|
||||
import { logger as _logger } from '@polymech/core/debug';
|
||||
import { MODULE_NAME } from './constants';
|
||||
export { Logger } from 'tslog';
|
||||
let loggers = {};
|
||||
/*
|
||||
const _logger = new Logger({
|
||||
prettyLogTemplate: "{{yyyy}}.{{mm}}.{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}}\t{{logLevelName}}\t[{{filePathWithLine}}{{name}}]\t",
|
||||
prettyErrorTemplate: "\n{{errorName}} {{errorMessage}}\nerror stack:\n{{errorStack}}",
|
||||
prettyErrorStackTemplate: " • {{fileName}}\t{{method}}\n\t{{filePathWithLine}}",
|
||||
prettyErrorParentNamesSeparator: ":",
|
||||
prettyErrorLoggerNameDelimiter: "\t",
|
||||
stylePrettyLogs: true,
|
||||
prettyLogTimeZone: "UTC",
|
||||
prettyLogStyles: {
|
||||
logLevelName: {
|
||||
"*": ["bold", "black", "bgWhiteBright", "dim"],
|
||||
SILLY: ["bold", "white"],
|
||||
TRACE: ["bold", "whiteBright"],
|
||||
DEBUG: ["bold", "green"],
|
||||
INFO: ["bold", "blue"],
|
||||
WARN: ["bold", "yellow"],
|
||||
ERROR: ["bold", "red"],
|
||||
FATAL: ["bold", "redBright"],
|
||||
},
|
||||
dateIsoStr: "white",
|
||||
filePathWithLine: "white",
|
||||
name: ["white", "bold"],
|
||||
nameWithDelimiterPrefix: ["white", "bold"],
|
||||
nameWithDelimiterSuffix: ["white", "bold"],
|
||||
errorName: ["bold", "bgRedBright", "whiteBright"],
|
||||
fileName: ["yellow"],
|
||||
fileNameWithLine: "white",
|
||||
},
|
||||
});
|
||||
*/
|
||||
/*
|
||||
export const __logger = (name: string = MODULE_NAME, options: ISettingsParam = {}): Logger => {
|
||||
if (!loggers[name]) {
|
||||
const logger: Logger = new Logger({
|
||||
name: name,
|
||||
type: 'pretty',
|
||||
...options
|
||||
});
|
||||
// const trans = (transportLogger: LogObj & ILogObjMet)
|
||||
(logger as any).attachTransport((logObj) => {
|
||||
debugger
|
||||
//transports.push(logObj);
|
||||
});
|
||||
|
||||
logger.debug('test')
|
||||
|
||||
loggers[name] = logger;
|
||||
}
|
||||
return loggers[name]
|
||||
}*/
|
||||
export const logger = _logger(MODULE_NAME);
|
||||
/*
|
||||
export const log = (msg: string, ...args: any) => logger().info(msg, ...args);
|
||||
export const info = (msg: string, ...args: any) => logger().info(msg, ...args);
|
||||
export const error = (msg: string, ...args: any) => logger().error(msg, ...args);
|
||||
export const warn = (msg: string, ...args: any) => logger().warn(msg, ...args);
|
||||
export const debug = (msg: string, ...args: any) => logger().debug(msg, ...args);
|
||||
*/
|
||||
import { substitute as _substitute, substituteAlt as _substituteAlt } from "@polymech/core/strings";
|
||||
export const substitute = (alt, template, vars = {}) => alt ? _substituteAlt(template, vars) : _substitute(template, vars);
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
packages/discourse-legacy/dist/index.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,cAAc,OAAO,CAAA;AACrB,cAAc,gBAAgB,CAAA;AAE9B,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAE9B,IAAI,OAAO,GAAG,EAAE,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8BI;AACJ;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,MAAM,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;AAE1C;;;;;;EAME;AAGF,OAAO,EAAE,UAAU,IAAI,WAAW,EAAE,aAAa,IAAI,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAInG,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAY,EAAE,QAAgB,EAAE,OAAuB,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA"}
|
||||
9
packages/discourse-legacy/dist/lib/discourse/cache.d.ts
vendored
Normal file
9
packages/discourse-legacy/dist/lib/discourse/cache.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
/// <reference types="node" resolution-mode="require"/>
|
||||
import { IDiscourseUser } from '../../';
|
||||
export declare const fileAsBuffer: (path: string) => Buffer;
|
||||
export declare const cacheCategories: (options: any, discourse: Discourser) => Promise<any>;
|
||||
export declare const cacheTopics: (options: any, discourse: Discourser) => Promise<void>;
|
||||
export declare const _getForumUsers: (d: Discourser, page: any, detail: any) => any;
|
||||
export declare const getForumUsers: (d: any, detail: any) => Promise<IDiscourseUser[]>;
|
||||
export declare const cacheUsers: (options: any, discourse: Discourser) => Promise<IDiscourseUser[]>;
|
||||
export declare const cacheTags: (options: any, discourse: Discourser) => Promise<any>;
|
||||
112
packages/discourse-legacy/dist/lib/discourse/cache.js
vendored
Normal file
112
packages/discourse-legacy/dist/lib/discourse/cache.js
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
import { Promise as BPromise } from 'bluebird';
|
||||
import { sync as read } from '@polymech/fs/read';
|
||||
import { sync as exists } from '@polymech/fs/exists';
|
||||
import { sync as write } from '@polymech/fs/write';
|
||||
import { resolve } from '@polymech/commons';
|
||||
import { DISCOURSE_CATEGORY_CACHE, DISCOURSE_TAGS_CACHE, DISCOURSE_USER_CACHE, } from '../discourse/constants';
|
||||
import * as path from 'path';
|
||||
const escapeHtml = require('escape-html');
|
||||
const pretty = require('pretty');
|
||||
export const fileAsBuffer = (path) => read(path, 'buffer') || Buffer.from("-");
|
||||
import { get_cached, set_cached } from '@plastichub/osr-cache/lib';
|
||||
import { OSR_CACHE } from '@polymech/commons';
|
||||
import { MODULE_NAME } from '../../constants';
|
||||
export const cacheCategories = async (options, discourse) => {
|
||||
const osr_cache = OSR_CACHE();
|
||||
const cPath = path.resolve(resolve(DISCOURSE_CATEGORY_CACHE));
|
||||
const cached = exists(cPath) ? await get_cached(cPath, {}, MODULE_NAME) : null;
|
||||
if (osr_cache && cached && options.cache !== false) {
|
||||
return JSON.parse(cached);
|
||||
}
|
||||
let cats = await discourse.getCategories({
|
||||
include_subcategories: true
|
||||
});
|
||||
write(cPath, cats);
|
||||
if (osr_cache && options.cache !== false) {
|
||||
await set_cached(cPath, {}, MODULE_NAME, cats);
|
||||
}
|
||||
return cats;
|
||||
};
|
||||
export const cacheTopics = async (options, discourse) => {
|
||||
};
|
||||
let uPage = 1;
|
||||
let usersAll = [];
|
||||
export const _getForumUsers = async (d, page, detail) => {
|
||||
const uPath = path.resolve(resolve(DISCOURSE_USER_CACHE));
|
||||
if (uPage == 1) {
|
||||
usersAll = [];
|
||||
}
|
||||
let users = await d.getUsers(page);
|
||||
if (users.length) {
|
||||
usersAll = usersAll.concat(users);
|
||||
uPage++;
|
||||
return _getForumUsers(d, uPage, detail);
|
||||
}
|
||||
else {
|
||||
uPage = 1;
|
||||
write(uPath, usersAll);
|
||||
let fUsers = read(uPath, 'json') || [];
|
||||
const add = async (u) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let fUser = fUsers.find((fu) => u.id == fu.id);
|
||||
if (!fUser) {
|
||||
fUsers.push(u);
|
||||
fUser = u;
|
||||
}
|
||||
if (fUser.detail) {
|
||||
console.log('Retrieve User Detail ' + u.name);
|
||||
setTimeout(() => {
|
||||
d.getUser(fUser.id).then((detail) => {
|
||||
if (detail) {
|
||||
fUser.detail = detail;
|
||||
}
|
||||
write(uPath, fUsers);
|
||||
resolve(fUser);
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
else {
|
||||
resolve(fUser);
|
||||
}
|
||||
});
|
||||
};
|
||||
return await BPromise.resolve(usersAll).map((u) => {
|
||||
return add(u);
|
||||
}, { concurrency: 1 });
|
||||
}
|
||||
};
|
||||
export const getForumUsers = async (d, detail) => {
|
||||
return _getForumUsers(d, uPage, detail);
|
||||
};
|
||||
export const cacheUsers = async (options, discourse) => {
|
||||
const osr_cache = OSR_CACHE();
|
||||
const uPath = path.resolve(resolve(DISCOURSE_USER_CACHE));
|
||||
const cached = exists(uPath) ? await get_cached(uPath, {}, MODULE_NAME) : null;
|
||||
if (osr_cache && options.cache !== false && exists(uPath)) {
|
||||
return read(uPath, 'json');
|
||||
}
|
||||
if (osr_cache && cached && options.cache !== false) {
|
||||
return JSON.parse(cached);
|
||||
}
|
||||
let users = await getForumUsers(discourse, false);
|
||||
write(uPath, users);
|
||||
if (osr_cache && options.cache !== false) {
|
||||
await set_cached(uPath, {}, MODULE_NAME, users);
|
||||
}
|
||||
return users;
|
||||
};
|
||||
export const cacheTags = async (options, discourse) => {
|
||||
const osr_cache = OSR_CACHE();
|
||||
const tPath = path.resolve(resolve(DISCOURSE_TAGS_CACHE));
|
||||
const cached = exists(tPath) ? await get_cached(tPath, {}, MODULE_NAME) : null;
|
||||
if (osr_cache && cached && options.cache !== false) {
|
||||
return JSON.parse(cached);
|
||||
}
|
||||
let tags = await discourse.getTags();
|
||||
write(tPath, tags);
|
||||
if (osr_cache && options.cache !== false) {
|
||||
await set_cached(tPath, {}, MODULE_NAME, tags);
|
||||
}
|
||||
return tags;
|
||||
};
|
||||
//# sourceMappingURL=cache.js.map
|
||||
1
packages/discourse-legacy/dist/lib/discourse/cache.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/discourse/cache.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/lib/discourse/cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,EAAE,IAAI,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,IAAI,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAqB3C,OAAO,EAEH,wBAAwB,EACxB,oBAAoB,EAEpB,oBAAoB,GAGvB,MAAM,wBAAwB,CAAA;AAK/B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAO5B,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;AACzC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEhC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAW,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAEhG,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAI7C,OAAO,EACH,WAAW,EACd,MAAM,iBAAiB,CAAA;AAGxB,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,OAAY,EAAE,SAAqB,EAAE,EAAE;IAEzE,MAAM,SAAS,GAAG,SAAS,EAAE,CAAA;IAE7B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAA;IAE7D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAE9E,IAAI,SAAS,IAAI,MAAM,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE;QAChD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;KAC5B;IAED,IAAI,IAAI,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC;QACrC,qBAAqB,EAAE,IAAI;KAC9B,CAAC,CAAA;IAEF,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAElB,IAAI,SAAS,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE;QACtC,MAAM,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,CAAA;KACjD;IAED,OAAO,IAAI,CAAA;AACf,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,OAAY,EAAE,SAAqB,EAAE,EAAE;AAEzE,CAAC,CAAA;AAED,IAAI,KAAK,GAAG,CAAC,CAAA;AACb,IAAI,QAAQ,GAAG,EAAE,CAAA;AAEjB,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,CAAa,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;IAEhE,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAA;IAEzD,IAAI,KAAK,IAAI,CAAC,EAAE;QACZ,QAAQ,GAAG,EAAE,CAAA;KAChB;IACD,IAAI,KAAK,GAAQ,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IACvC,IAAI,KAAK,CAAC,MAAM,EAAE;QACd,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACjC,KAAK,EAAE,CAAA;QACP,OAAO,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;KAC1C;SAAM;QACH,KAAK,GAAG,CAAC,CAAA;QAET,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QAEtB,IAAI,MAAM,GAAqB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,EAAS,CAAA;QAE/D,MAAM,GAAG,GAAG,KAAK,EAAE,CAAiB,EAAE,EAAE;YACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACnC,IAAI,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;gBAC9C,IAAI,CAAC,KAAK,EAAE;oBACR,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;oBACd,KAAK,GAAG,CAAC,CAAA;iBACZ;gBAED,IAAI,KAAK,CAAC,MAAM,EAAE;oBACd,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAA;oBAC7C,UAAU,CAAC,GAAG,EAAE;wBACZ,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;4BAChC,IAAI,MAAM,EAAE;gCACR,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;6BACxB;4BACD,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;4BACpB,OAAO,CAAC,KAAK,CAAC,CAAA;wBAClB,CAAC,CAAC,CAAA;oBACN,CAAC,EAAE,GAAG,CAAC,CAAA;iBACV;qBAAM;oBACH,OAAO,CAAC,KAAK,CAAC,CAAA;iBACjB;YACL,CAAC,CAAC,CAAA;QACN,CAAC,CAAA;QACD,OAAO,MAAM,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAiB,EAAE,EAAE;YAC9D,OAAO,GAAG,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAA;KAEzB;AACL,CAAC,CAAA;AACD,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,CAAC,EAAE,MAAM,EAA6B,EAAE;IACxE,OAAO,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;AAC3C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,OAAO,EAAE,SAAqB,EAA6B,EAAE;IAE1F,MAAM,SAAS,GAAG,SAAS,EAAE,CAAA;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAA;IAEzD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAE9E,IAAI,SAAS,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE;QACvD,OAAO,IAAI,CAAC,KAAK,EAAE,MAAM,CAAQ,CAAA;KACpC;IAED,IAAI,SAAS,IAAI,MAAM,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE;QAChD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;KAC5B;IAED,IAAI,KAAK,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;IAEjD,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IAEnB,IAAI,SAAS,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE;QACtC,MAAM,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,CAAA;KAClD;IAED,OAAO,KAAK,CAAA;AAEhB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,OAAO,EAAE,SAAqB,EAAE,EAAE;IAC9D,MAAM,SAAS,GAAG,SAAS,EAAE,CAAA;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAA;IAEzD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAE9E,IAAI,SAAS,IAAI,MAAM,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE;QAChD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;KAC5B;IAED,IAAI,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,CAAA;IACpC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAElB,IAAI,SAAS,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE;QACtC,MAAM,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,CAAA;KACjD;IAED,OAAO,IAAI,CAAA;AACf,CAAC,CAAA"}
|
||||
70
packages/discourse-legacy/dist/lib/discourse/constants.d.ts
vendored
Normal file
70
packages/discourse-legacy/dist/lib/discourse/constants.d.ts
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
export type EDiscourseConfigKey = 'discourse' | 'discourse_admin';
|
||||
export declare const SYNC_TRACK_FILENAME = "discourse-sync.json";
|
||||
export declare const OSR_CACHE_ROOT = "${OSR_CACHE}";
|
||||
export declare const OSR_DISCOURSE_CACHE = "${OSR_CACHE}/discourse";
|
||||
export declare const DISCOURSE_CATEGORY_CACHE = "${OSR_CACHE}/discourse/cats.json";
|
||||
export declare const DISCOURSE_TOPICS_CACHE = "${OSR_CACHE}/discourse/topics.json";
|
||||
export declare const DISCOURSE_TAGS_CACHE = "${OSR_CACHE}/discourse/tags.json";
|
||||
export declare const DISCOURSE_USER_CACHE = "${OSR_CACHE}/discourse/users.json";
|
||||
export declare const OA_DIRECTORY_OVERVIEW_TOPIC = 28873;
|
||||
export declare const OA_USER_IMPORT_GROUP = 43;
|
||||
export declare const KB_USERS = "${KB_ROOT}/static/users";
|
||||
export declare const DATA_PATH = "${OSR_ROOT}/osr-directory/pp";
|
||||
export declare const LATEST_TRACK = "${OSR_ROOT}/osr-directory/pp/merged.json";
|
||||
export declare const LATEST_TEST = "./latest_test.json";
|
||||
export declare const FETCH_DUSERS = false;
|
||||
export declare const F_USERS_NOW = "./fusers.json";
|
||||
export declare const F_USERS_ALL = "./fusers-all.json";
|
||||
export declare const DEFAULT_PASSWORD: () => string;
|
||||
export declare const HOWTOS_ASSETS_URL: () => string;
|
||||
export declare const MACHINES_ASSETS_URL: () => string;
|
||||
export declare const CAT_TEST = 65;
|
||||
export declare const TAGS_TEST = "plastic, meta";
|
||||
export declare const DEFAULT_IMPORT_OWNER = 1;
|
||||
export declare const D_ROOT_CAT = 97;
|
||||
export declare const D_ROOT_AFRICA = 79;
|
||||
export declare const D_ROOT_ASIA = 60;
|
||||
export declare const D_ROOT_EUROPE = 59;
|
||||
export declare const D_ROOT_AUSTRALIA = 76;
|
||||
export declare const D_ROOT_NAMERICA = 101;
|
||||
export declare const D_ROOT_SAMERICA = 102;
|
||||
export declare const D_ROOT_OCEANIA = 103;
|
||||
export declare const HT_CAT_ROOT = 54;
|
||||
export declare const HT_CAT_GUIDES = 86;
|
||||
export declare const HT_CAT_MACHINES = 87;
|
||||
export declare const HT_CAT_PRODUCTS = 88;
|
||||
export declare const HT_CAT_MOULDS = 89;
|
||||
export declare const HT_CAT_IDS: {
|
||||
HT_CAT_ROOT: number;
|
||||
HT_CAT_GUIDES: number;
|
||||
HT_CAT_MACHINES: number;
|
||||
HT_CAT_PRODUCTS: number;
|
||||
HT_CAT_MOULDS: number;
|
||||
};
|
||||
export declare const HT_CATS: {
|
||||
Guides: number;
|
||||
Machines: number;
|
||||
Products: number;
|
||||
Moulds: number;
|
||||
};
|
||||
export declare const MACHINE_CAT_INJECTION = 50;
|
||||
export declare const MACHINE_CAT_EXTRUSION = 51;
|
||||
export declare const MACHINE_CAT_SHREDDER = 52;
|
||||
export declare const MACHINE_CAT_SHEETPRESS = 63;
|
||||
export declare const MACHINE_CAT_3DPRINT = 70;
|
||||
export declare const MACHINE_CAT_MOULDS = 71;
|
||||
export declare const MACHINE_CAT_IDS: {
|
||||
MACHINE_CAT_INJECTION: number;
|
||||
MACHINE_CAT_EXTRUSION: number;
|
||||
MACHINE_CAT_SHREDDER: number;
|
||||
MACHINE_CAT_SHEETPRESS: number;
|
||||
MACHINE_CAT_3DPRINT: number;
|
||||
MACHINE_CAT_MOULDS: number;
|
||||
};
|
||||
export declare const MACHINE_CATS: {
|
||||
Injection: number;
|
||||
Extrusion: number;
|
||||
Sheetpress: number;
|
||||
'3DPrint': number;
|
||||
Moulds: number;
|
||||
};
|
||||
94
packages/discourse-legacy/dist/lib/discourse/constants.js
vendored
Normal file
94
packages/discourse-legacy/dist/lib/discourse/constants.js
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Keys
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Paths
|
||||
//
|
||||
export const SYNC_TRACK_FILENAME = 'discourse-sync.json';
|
||||
export const OSR_CACHE_ROOT = '${OSR_CACHE}';
|
||||
export const OSR_DISCOURSE_CACHE = '${OSR_CACHE}/discourse';
|
||||
export const DISCOURSE_CATEGORY_CACHE = '${OSR_CACHE}/discourse/cats.json';
|
||||
export const DISCOURSE_TOPICS_CACHE = '${OSR_CACHE}/discourse/topics.json';
|
||||
export const DISCOURSE_TAGS_CACHE = '${OSR_CACHE}/discourse/tags.json';
|
||||
export const DISCOURSE_USER_CACHE = '${OSR_CACHE}/discourse/users.json';
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OA - User Import
|
||||
//
|
||||
export const OA_DIRECTORY_OVERVIEW_TOPIC = 28873;
|
||||
export const OA_USER_IMPORT_GROUP = 43;
|
||||
export const KB_USERS = '${KB_ROOT}/static/users';
|
||||
export const DATA_PATH = '${OSR_ROOT}/osr-directory/pp';
|
||||
export const LATEST_TRACK = '${OSR_ROOT}/osr-directory/pp/merged.json';
|
||||
export const LATEST_TEST = './latest_test.json';
|
||||
export const FETCH_DUSERS = false;
|
||||
export const F_USERS_NOW = './fusers.json';
|
||||
export const F_USERS_ALL = './fusers-all.json';
|
||||
export const DEFAULT_PASSWORD = () => '4g0&KPN$e*Un';
|
||||
export const HOWTOS_ASSETS_URL = () => `https://kb.osr-plastic.org/howtos/`;
|
||||
export const MACHINES_ASSETS_URL = () => `https://assets.osr-plastic.org/machines/`;
|
||||
export const CAT_TEST = 65;
|
||||
export const TAGS_TEST = 'plastic, meta';
|
||||
export const DEFAULT_IMPORT_OWNER = 1;
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OA - Directory Import
|
||||
//
|
||||
export const D_ROOT_CAT = 97;
|
||||
export const D_ROOT_AFRICA = 79;
|
||||
export const D_ROOT_ASIA = 60;
|
||||
export const D_ROOT_EUROPE = 59;
|
||||
export const D_ROOT_AUSTRALIA = 76;
|
||||
export const D_ROOT_NAMERICA = 101;
|
||||
export const D_ROOT_SAMERICA = 102;
|
||||
export const D_ROOT_OCEANIA = 103;
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OA - Howto Import
|
||||
//
|
||||
export const HT_CAT_ROOT = 54;
|
||||
export const HT_CAT_GUIDES = 86;
|
||||
export const HT_CAT_MACHINES = 87;
|
||||
export const HT_CAT_PRODUCTS = 88;
|
||||
export const HT_CAT_MOULDS = 89;
|
||||
export const HT_CAT_IDS = {
|
||||
HT_CAT_ROOT,
|
||||
HT_CAT_GUIDES,
|
||||
HT_CAT_MACHINES,
|
||||
HT_CAT_PRODUCTS,
|
||||
HT_CAT_MOULDS
|
||||
};
|
||||
export const HT_CATS = {
|
||||
'Guides': HT_CAT_GUIDES,
|
||||
'Machines': HT_CAT_MACHINES,
|
||||
'Products': HT_CAT_PRODUCTS,
|
||||
'Moulds': HT_CAT_MOULDS
|
||||
};
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// OA - Library Import
|
||||
//
|
||||
export const MACHINE_CAT_INJECTION = 50;
|
||||
export const MACHINE_CAT_EXTRUSION = 51;
|
||||
export const MACHINE_CAT_SHREDDER = 52;
|
||||
export const MACHINE_CAT_SHEETPRESS = 63;
|
||||
export const MACHINE_CAT_3DPRINT = 70;
|
||||
export const MACHINE_CAT_MOULDS = 71;
|
||||
export const MACHINE_CAT_IDS = {
|
||||
MACHINE_CAT_INJECTION,
|
||||
MACHINE_CAT_EXTRUSION,
|
||||
MACHINE_CAT_SHREDDER,
|
||||
MACHINE_CAT_SHEETPRESS,
|
||||
MACHINE_CAT_3DPRINT,
|
||||
MACHINE_CAT_MOULDS
|
||||
};
|
||||
export const MACHINE_CATS = {
|
||||
'Injection': MACHINE_CAT_INJECTION,
|
||||
'Extrusion': MACHINE_CAT_EXTRUSION,
|
||||
'Sheetpress': MACHINE_CAT_SHEETPRESS,
|
||||
'3DPrint': MACHINE_CAT_3DPRINT,
|
||||
'Moulds': HT_CAT_MOULDS
|
||||
};
|
||||
//# sourceMappingURL=constants.js.map
|
||||
1
packages/discourse-legacy/dist/lib/discourse/constants.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/discourse/constants.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/discourse/constants.ts"],"names":[],"mappings":"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"}
|
||||
181
packages/discourse-legacy/dist/lib/discourse/index.d.ts
vendored
Normal file
181
packages/discourse-legacy/dist/lib/discourse/index.d.ts
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
import { IDiscourseConfig } from '@polymech/commons/types';
|
||||
export declare const logger: any;
|
||||
import PromisePool from 'native-promise-pool';
|
||||
export declare const escape: (path: string) => string;
|
||||
import { TPostStatus, TPostStatusUpdate, UserPreferencesUpdate } from './types';
|
||||
import { Category, CategoriesResponse, PostsResponse, PostResponse, TopicResponse, TopicItem, CategoryResponse, PostItem, PostUpdateItem, IDiscourserConfig, Thread, PostModifier, FetchConfig, FetchOptions, ISearchResult, ICreateUserResponse, IUserDetail, TagsResponse, Tag, TopicUpdateBasicTopic } from './types';
|
||||
import { IDiscourseUser } from '@polymech/commons';
|
||||
import { IDImage } from '../oa/index';
|
||||
/**
|
||||
* Discourser is an API Client for the [Discourse API](https://docs.discourse.org)
|
||||
* It special features are:
|
||||
* - TypeScript Types
|
||||
* - Respecting Rate Limits
|
||||
* - Optional Heavy Caching
|
||||
* - Post Modifiers (can be used for global find and replace across all posts on the forum)
|
||||
*/
|
||||
export declare class Discourser {
|
||||
readonly host: string;
|
||||
readonly key: string;
|
||||
readonly username: string;
|
||||
readonly cache?: string;
|
||||
readonly useCache?: boolean;
|
||||
readonly dry: boolean;
|
||||
readonly pool: PromisePool<any>;
|
||||
/**
|
||||
* Construct our Discourser instance
|
||||
* See {@link IDiscourserConfig} for available configuration.
|
||||
*/
|
||||
constructor(config: IDiscourserConfig);
|
||||
/** Get the URL of a topic */
|
||||
getTopicURL(topic: TopicItem | TopicResponse | number): string;
|
||||
/** Fetch a discourse API URL, with rate limit concurrency and optional caching */
|
||||
fetch<T>({ url, useCache, request }: FetchConfig): Promise<T>;
|
||||
/** Fetch a discourse API URL, with rate limit retries */
|
||||
private _post;
|
||||
/** Fetch a discourse API URL, with rate limit retries */
|
||||
private _fetch;
|
||||
/**
|
||||
* API Helper for {@link .search}
|
||||
* https://docs.discourse.org/#tag/Search/operation/search
|
||||
*/
|
||||
search(query: string, params?: string, opts?: FetchOptions): Promise<ISearchResult>;
|
||||
/**
|
||||
* API Helper for {@link .getTags}
|
||||
*/
|
||||
protected getTagsResponse(opts?: FetchOptions): Promise<TagsResponse>;
|
||||
/**
|
||||
* Fetch the whole information, for all categories of the forum
|
||||
*/
|
||||
getTags(opts?: FetchOptions): Promise<Tag[]>;
|
||||
createTag(name: any): Promise<any>;
|
||||
/**
|
||||
* API Helper for {@link .getCategories}
|
||||
*/
|
||||
protected getCategoriesResponse(opts?: FetchOptions): Promise<CategoriesResponse>;
|
||||
/**
|
||||
* Fetch the whole information, for all categories of the forum
|
||||
*/
|
||||
getCategories(opts?: FetchOptions): Promise<Category[]>;
|
||||
/**
|
||||
* API Helper for {@link .getTopicItemsOfCategory}
|
||||
* Discourse does not provide an API for fetching category information for a specific category.
|
||||
* Instead, all that it provides is a way of getting the topics for a specific category.
|
||||
*/
|
||||
protected getCategoryResponse(categoryID: number, opts?: FetchOptions): Promise<CategoryResponse>;
|
||||
/**
|
||||
* Fetch the partial information, for all topics of a specific category
|
||||
*/
|
||||
getTopicItemsOfCategory(categoryID: number, opts?: FetchOptions): Promise<TopicItem[]>;
|
||||
/**
|
||||
* Fetch the partial information, for all topics of specific categoires
|
||||
*/
|
||||
getTopicItemsOfCategories(categoryIDs: number[], opts?: FetchOptions): Promise<TopicItem[]>;
|
||||
/**
|
||||
* Fetch the partial information, for all topics of the forum
|
||||
*/
|
||||
getTopicItems(opts?: FetchOptions): Promise<TopicItem[]>;
|
||||
/**
|
||||
* Fetch the whole information, for a specific topic of the forum
|
||||
*/
|
||||
getTopic(id: number, opts?: FetchOptions): Promise<TopicResponse>;
|
||||
/**
|
||||
* Fetch the whole information, for all topics, or specific topics, of the forum
|
||||
*/
|
||||
getTopics(topicIDs?: number[] | null, opts?: FetchOptions): Promise<TopicItem[] | TopicResponse[]>;
|
||||
updateTopicVisibility(topicID: number, listed?: boolean, visible?: TPostStatus): Promise<TPostStatusUpdate>;
|
||||
updateTopicTimestamp(topicID: number, timestamp: Date | string | number, token: string): Promise<any>;
|
||||
/**
|
||||
* API Helper for {@link .getPostItemsOfTopic}
|
||||
*/
|
||||
protected getPostItemsOfTopicResponse(topicID: number, opts?: FetchOptions): Promise<PostsResponse>;
|
||||
_createUser(name: any, email: any, pUserGroup: any): Promise<ICreateUserResponse>;
|
||||
getUsers(page: any): Promise<IDiscourseUser>;
|
||||
getUser(id: any): Promise<IUserDetail>;
|
||||
/**
|
||||
* Fetch the partial information, for all posts of a specific topic
|
||||
*/
|
||||
getPostItemsOfTopic(topicID: number, opts?: FetchOptions): Promise<PostItem[]>;
|
||||
/**
|
||||
* Fetch the partial information, for all posts of specific topics
|
||||
*/
|
||||
getPostItemsOfTopics(topicIDs: number[], opts?: FetchOptions): Promise<PostItem[]>;
|
||||
/**
|
||||
* Fetch the partial information, for all posts of a specific category
|
||||
*/
|
||||
getPostItemsOfCategory(categoryID: number, opts?: FetchOptions): Promise<PostItem[]>;
|
||||
/**
|
||||
* Fetch the partial information, for all posts of specific categories
|
||||
*/
|
||||
getPostItemsOfCategories(categoryIDs: number[], opts?: FetchOptions): Promise<PostItem[]>;
|
||||
/**
|
||||
* Fetch the partial information, for all posts of the forum
|
||||
*/
|
||||
getPostItems(opts?: FetchOptions): Promise<PostItem[]>;
|
||||
/**
|
||||
* Fetch the whole information, for a specific post of the forum
|
||||
*/
|
||||
getPost(id: number, opts?: FetchOptions): Promise<PostResponse>;
|
||||
createReply(postId: any, raw: any, category: any): Promise<unknown>;
|
||||
changeOwner(postId: string | number, topicId: string | number, owner: string): Promise<unknown>;
|
||||
createUser(data: any): Promise<ICreateUserResponse>;
|
||||
getUserByUsername(username: any): Promise<IUserDetail>;
|
||||
setUserAvatar(user_name: any, upload_id: any): Promise<PostResponse[]>;
|
||||
updateUser(user_name: any, args: any): Promise<PostResponse[]>;
|
||||
updateGroup(user_name: any, group: any): Promise<any>;
|
||||
upload(userId: any, file: any): Promise<IDImage[]>;
|
||||
uploadFile(userId: any, file: any): Promise<PostResponse[]>;
|
||||
/**
|
||||
* Fetch the whole information, for all posts, or specific posts, of the forum
|
||||
*/
|
||||
getPosts(postIDs?: number[] | null, opts?: FetchOptions): Promise<PostResponse[]>;
|
||||
createPost(title: string, raw: string, category: number): Promise<unknown>;
|
||||
/**
|
||||
* Update a post with the content
|
||||
* @param postID the identifier of the post to update
|
||||
* @param content the new raw content for the post
|
||||
* @param reason the reason, if provided, for modifying the post
|
||||
* @param old if the old raw content is provided, then the update verified that you are working with the latest post content before applying the update
|
||||
*/
|
||||
updatePost(postID: number, content: string, reason?: string, old?: string): Promise<PostUpdateItem>;
|
||||
/**
|
||||
* Update post meta
|
||||
*/
|
||||
updateTopic(postId: number, category_id: number, title: string, tags?: string[]): Promise<TopicUpdateBasicTopic>;
|
||||
rebakePost(postID: number): Promise<any>;
|
||||
/**
|
||||
* Modify a post using a modifier
|
||||
*/
|
||||
modifyPost(post: PostResponse, modifier: PostModifier): Promise<PostUpdateItem | null>;
|
||||
/**
|
||||
* Modify a post (via its post identifier) using a modifier
|
||||
*/
|
||||
modifyPostID(post: number, modifier: PostModifier): Promise<any>;
|
||||
/**
|
||||
* Modify a post (via fetching the whole post from the partial post identifier) using a modifier
|
||||
*/
|
||||
modifyPostItem(post: PostItem, modifier: PostModifier): Promise<any>;
|
||||
/**
|
||||
* Run the post modifier on all specified posts
|
||||
*/
|
||||
modifyPosts(posts: PostResponse[], modifier: PostModifier): Promise<PostUpdateItem[]>;
|
||||
/**
|
||||
* Fetch the partial information, for all posts of a specific topic
|
||||
* Alias of {@link .getPostItemsOfTopic}.
|
||||
*/
|
||||
getThread(topicID: number, opts?: FetchOptions): Promise<Thread>;
|
||||
/**
|
||||
* Fetch the partial information, for all posts of specific topics, grouped by topic
|
||||
*/
|
||||
getThreads(topicIDs: number[], opts?: FetchOptions): Promise<Thread[]>;
|
||||
/**
|
||||
* Fetch the partial information, for all posts of specific categories, grouped by topic
|
||||
*/
|
||||
getThreadsOfCategory(categoryID: number, opts?: FetchOptions): Promise<Thread[]>;
|
||||
/**
|
||||
* Fetch the partial information, for all posts of specific categories, grouped by category, then topic
|
||||
*/
|
||||
getThreadsOfCategories(categoryIDs: number[], opts?: FetchOptions): Promise<Thread[][]>;
|
||||
updateUserProfile(userId: any, prefs: UserPreferencesUpdate): Promise<any>;
|
||||
}
|
||||
export declare const Instance: (config?: IDiscourseConfig, key?: EDiscourseConfigKey) => Discourser;
|
||||
935
packages/discourse-legacy/dist/lib/discourse/index.js
vendored
Normal file
935
packages/discourse-legacy/dist/lib/discourse/index.js
vendored
Normal file
@ -0,0 +1,935 @@
|
||||
import { MODULE_NAME } from '../../constants';
|
||||
import { CONFIG_DEFAULT } from '@polymech/commons';
|
||||
import { logger as _logger } from '@polymech/core/debug';
|
||||
export const logger = _logger(MODULE_NAME);
|
||||
import { sync as write } from '@polymech/fs/write';
|
||||
import { sync as read } from '@polymech/fs/write';
|
||||
import { sync as exists } from '@polymech/fs/exists';
|
||||
import PromisePool from 'native-promise-pool';
|
||||
import { join } from 'path';
|
||||
import axios from 'axios';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as FormData from 'form-data';
|
||||
const https = require('https');
|
||||
const request = require("request");
|
||||
const fetch = require('isomorphic-unfetch');
|
||||
export const escape = (path) => path.replace(/[^\w]/g, '-').replace(/-+/, '-');
|
||||
import { generate } from 'generate-password';
|
||||
/**
|
||||
* Discourser is an API Client for the [Discourse API](https://docs.discourse.org)
|
||||
* It special features are:
|
||||
* - TypeScript Types
|
||||
* - Respecting Rate Limits
|
||||
* - Optional Heavy Caching
|
||||
* - Post Modifiers (can be used for global find and replace across all posts on the forum)
|
||||
*/
|
||||
export class Discourser {
|
||||
host;
|
||||
key;
|
||||
username;
|
||||
cache;
|
||||
useCache;
|
||||
dry;
|
||||
pool;
|
||||
/**
|
||||
* Construct our Discourser instance
|
||||
* See {@link IDiscourserConfig} for available configuration.
|
||||
*/
|
||||
constructor(config) {
|
||||
this.host = config.host;
|
||||
this.key = config.key;
|
||||
this.username = config.username;
|
||||
this.cache = config.cache;
|
||||
this.useCache = config.useCache;
|
||||
this.dry = config.dry || false;
|
||||
this.pool = new PromisePool(config.rateLimitConcurrency || 60);
|
||||
}
|
||||
/** Get the URL of a topic */
|
||||
getTopicURL(topic) {
|
||||
if (typeof topic === 'number') {
|
||||
return `${this.host}/t/${topic}`;
|
||||
}
|
||||
return `${this.host}/t/${topic.slug}/${topic.id}`;
|
||||
}
|
||||
/** Fetch a discourse API URL, with rate limit concurrency and optional caching */
|
||||
async fetch({ url, useCache, request }) {
|
||||
// check if cache is enabled
|
||||
useCache = false;
|
||||
const cache = this.cache &&
|
||||
(request?.method || 'get') === 'get' &&
|
||||
join(this.cache, escape(url));
|
||||
// check if we should and can read from cache
|
||||
if (cache &&
|
||||
this.useCache !== false &&
|
||||
useCache !== false &&
|
||||
(exists(cache))) {
|
||||
const result = read(cache, 'json');
|
||||
return result;
|
||||
}
|
||||
// fetch
|
||||
const result = await this.pool.open(() => this._fetch({ url, request }));
|
||||
// write to cache if cache is enabled
|
||||
if (cache) {
|
||||
write(cache, result);
|
||||
}
|
||||
// return the result
|
||||
return result;
|
||||
}
|
||||
/** Fetch a discourse API URL, with rate limit retries */
|
||||
async _post(url, data) {
|
||||
const opts = {
|
||||
headers: {
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username,
|
||||
},
|
||||
};
|
||||
let d = data;
|
||||
const res = await axios.post(url, d, {
|
||||
headers: opts.headers
|
||||
});
|
||||
// fetch text then parse as json, so that when errors occur we can output what it was
|
||||
// rather than being stuck with errors like these:
|
||||
// FetchError: invalid json response body at https://discuss.bevry.me/posts/507.json reason: Unexpected token < in JSON at position 0
|
||||
const text = await res.data;
|
||||
// check if there are errors
|
||||
if (typeof data.errors !== 'undefined') {
|
||||
// check if the error is a rate limit
|
||||
const wait = data.extras?.wait_seconds;
|
||||
if (wait != null) {
|
||||
// if it was, try later
|
||||
// return await retry(wait + 1)
|
||||
}
|
||||
// otherwise fail
|
||||
// logger.debug({ data, url, opts })
|
||||
return Promise.reject(new Error(`fetch of [${url}] received failed response:\n${data}`));
|
||||
}
|
||||
return text;
|
||||
}
|
||||
/** Fetch a discourse API URL, with rate limit retries */
|
||||
async _fetch({ url, request }) {
|
||||
const httpsAgent = new https.Agent({
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
const opts = {
|
||||
...request,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username,
|
||||
...request?.headers
|
||||
},
|
||||
rejectUnauthorized: false,
|
||||
agent: httpsAgent
|
||||
};
|
||||
const retry = (seconds) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => this._fetch({ url, request })
|
||||
.then(resolve)
|
||||
.catch(reject), (seconds || 60) * 1000);
|
||||
});
|
||||
};
|
||||
try {
|
||||
const res = await fetch(url, opts);
|
||||
// fetch text then parse as json, so that when errors occur we can output what it was
|
||||
// rather than being stuck with errors like these:
|
||||
// FetchError: invalid json response body at https://discuss.bevry.me/posts/507.json reason: Unexpected token < in JSON at position 0
|
||||
const text = await res.text();
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(text);
|
||||
}
|
||||
catch (err) {
|
||||
// check if it was cloudflare reporting that the server has been hit too hard
|
||||
if (text.includes('Please try again in a few minutes')) {
|
||||
logger.debug('server has stalled, trying again in a minute');
|
||||
return await retry(60);
|
||||
}
|
||||
// otherwise log the error page and die
|
||||
// logger.debug({ text, url , opts })
|
||||
return Promise.reject(logger.error(text, url, opts, err) &&
|
||||
new Error(`fetch of [${url}] received invalid response:\n${text}`));
|
||||
}
|
||||
// check if there are errors
|
||||
if (typeof data.errors !== 'undefined') {
|
||||
// check if the error is a rate limit
|
||||
const wait = data.extras?.wait_seconds;
|
||||
if (wait != null) {
|
||||
// if it was, try later
|
||||
return await retry(wait + 1);
|
||||
}
|
||||
// otherwise fail
|
||||
// logger.debug({ data, url, opts })
|
||||
return Promise.reject(new Error(`fetch of [${url}] received failed response:\n${data}`));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
catch (err) {
|
||||
// logger.debug({ err, url, opts })
|
||||
return Promise.reject(logger.error(`fetch of [${url}] failed with error`, err));
|
||||
}
|
||||
}
|
||||
// =================================
|
||||
// Search
|
||||
/**
|
||||
* API Helper for {@link .search}
|
||||
* https://docs.discourse.org/#tag/Search/operation/search
|
||||
*/
|
||||
async search(query, params = '', opts = {}) {
|
||||
let url = `${this.host}/search.json?q=${encodeURIComponent(query)} ${encodeURIComponent(params)}`;
|
||||
return await this.fetch({ url, ...opts });
|
||||
}
|
||||
// =================================
|
||||
// Tags
|
||||
/**
|
||||
* API Helper for {@link .getTags}
|
||||
*/
|
||||
async getTagsResponse(opts = {}) {
|
||||
const url = `${this.host}/tags.json`;
|
||||
return await this.fetch({ url, ...opts });
|
||||
}
|
||||
/**
|
||||
* Fetch the whole information, for all categories of the forum
|
||||
*/
|
||||
async getTags(opts = {}) {
|
||||
const response = await this.getTagsResponse(opts);
|
||||
const tags = response.tags;
|
||||
return tags;
|
||||
}
|
||||
async createTag(name) {
|
||||
const url = `${this.host}/tag_groups.json`;
|
||||
try {
|
||||
return await this._post(url, {
|
||||
name
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
debugger;
|
||||
}
|
||||
}
|
||||
// =================================
|
||||
// CATEGORIES
|
||||
/**
|
||||
* API Helper for {@link .getCategories}
|
||||
*/
|
||||
async getCategoriesResponse(opts = {}) {
|
||||
const url = `${this.host}/categories.json` +
|
||||
(opts.include_subcategories ? '?include_subcategories=true' : '');
|
||||
return await this.fetch({ url, ...opts });
|
||||
}
|
||||
/**
|
||||
* Fetch the whole information, for all categories of the forum
|
||||
*/
|
||||
async getCategories(opts = {}) {
|
||||
const response = await this.getCategoriesResponse(opts);
|
||||
const categories = response.category_list.categories;
|
||||
return categories;
|
||||
}
|
||||
/**
|
||||
* API Helper for {@link .getTopicItemsOfCategory}
|
||||
* Discourse does not provide an API for fetching category information for a specific category.
|
||||
* Instead, all that it provides is a way of getting the topics for a specific category.
|
||||
*/
|
||||
async getCategoryResponse(categoryID, opts = {}) {
|
||||
const url = `${this.host}/c/${categoryID}.json` +
|
||||
(opts.page !== 0 ? `?page=${opts.page}` : '');
|
||||
return await this.fetch({ url, ...opts });
|
||||
}
|
||||
// =================================
|
||||
// TOPICS
|
||||
/**
|
||||
* Fetch the partial information, for all topics of a specific category
|
||||
*/
|
||||
async getTopicItemsOfCategory(categoryID, opts = {}) {
|
||||
// prepare and fetch
|
||||
let page = opts.page || 0;
|
||||
const response = await this.getCategoryResponse(categoryID, {
|
||||
...opts,
|
||||
page,
|
||||
});
|
||||
let topics = response.topic_list.topics;
|
||||
// fetch the next page
|
||||
if (topics.length === response.topic_list.per_page) {
|
||||
page += 1;
|
||||
const more = await this.getTopicItemsOfCategory(categoryID, {
|
||||
...opts,
|
||||
page,
|
||||
});
|
||||
topics.push(...more);
|
||||
}
|
||||
// if we are the first page, then output count as we now have all of them
|
||||
if (page === 0) {
|
||||
const ids = topics.map((i) => i.id);
|
||||
}
|
||||
topics = topics.filter((t) => t.visible === true);
|
||||
return topics;
|
||||
}
|
||||
/**
|
||||
* Fetch the partial information, for all topics of specific categoires
|
||||
*/
|
||||
async getTopicItemsOfCategories(categoryIDs, opts = {}) {
|
||||
// fetch topic items for specific categories
|
||||
try {
|
||||
const topicsOfCategories = await Promise.all(categoryIDs.map((id) => this.getTopicItemsOfCategory(id, opts)));
|
||||
// @ts-ignore
|
||||
return topicsOfCategories.flat();
|
||||
}
|
||||
catch (error) {
|
||||
logger.error(error);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Fetch the partial information, for all topics of the forum
|
||||
*/
|
||||
async getTopicItems(opts = {}) {
|
||||
const categories = await this.getCategories();
|
||||
const categoryIDs = categories.map((i) => i.id);
|
||||
return this.getTopicItemsOfCategories(categoryIDs, opts);
|
||||
}
|
||||
/**
|
||||
* Fetch the whole information, for a specific topic of the forum
|
||||
*/
|
||||
getTopic(id, opts = {}) {
|
||||
const url = `${this.host}/t/${id}.json`;
|
||||
return this.fetch({ url, ...opts });
|
||||
}
|
||||
/**
|
||||
* Fetch the whole information, for all topics, or specific topics, of the forum
|
||||
*/
|
||||
async getTopics(topicIDs, opts = {}) {
|
||||
// if no topics, use all topics
|
||||
if (!topicIDs) {
|
||||
const topics = await this.getTopicItems(opts);
|
||||
topicIDs = topics.map((i) => i.id);
|
||||
}
|
||||
// fetch whole topics
|
||||
return Promise.all(topicIDs.map((id) => this.getTopic(id, opts)));
|
||||
}
|
||||
async updateTopicVisibility(topicID, listed = true, visible = 'visible') {
|
||||
const url = `${this.host}/t/${topicID}/status`;
|
||||
let ret = await fetch(url, {
|
||||
"headers": {
|
||||
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
},
|
||||
"body": `status=${visible}&enabled=${listed}`,
|
||||
"method": "PUT"
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
async updateTopicTimestamp(topicID, timestamp, token) {
|
||||
let time;
|
||||
if (typeof timestamp === 'number') {
|
||||
time = timestamp;
|
||||
}
|
||||
else if (typeof timestamp === 'number') {
|
||||
time = Number(timestamp);
|
||||
}
|
||||
else if (timestamp instanceof Date) {
|
||||
// ms to seconds
|
||||
time = timestamp.getTime() / 1000;
|
||||
}
|
||||
else {
|
||||
return Promise.reject(new Error('invalid timestamp format'));
|
||||
}
|
||||
const url = `${this.host}/t/${topicID}/change-timestamp`;
|
||||
let ret = await fetch(url, {
|
||||
"headers": {
|
||||
"accept-language": "en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7,es;q=0.6,fr;q=0.5",
|
||||
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"x-csrf-token": token,
|
||||
"x-requested-with": "XMLHttpRequest",
|
||||
"cookie": "_bypass_cache=true; _ga_MBZGKNMDWC=GS1.1.1685892974.20.1.1685893082.0.0.0; _ga_P4SR15V1XR=GS1.1.1687459978.51.1.1687460537.0.0.0; _ga_H8W78Y3P2B=GS1.1.1687604701.23.0.1687604701.0.0.0; _ga=GA1.1.401826746.1678337758; _t=xQ05qW5JFxLM9Pq0lIwG6ez74Z1q2OLpak0DzRx8VdFYE5eI3oJXhLURPrdm2zIcHmYcBj9q%2BKdHhGz5N6j9mXitYzcMwkXHL3K9GYKdO4gJ8tBQimpmd1HFaRhB9Ml9aJ8WviqQWDZDOYwEUKFcWw3wbAalfQtbdIbUSX8gH9sG6DLFU3HiEg7tWModRy%2BoFrTm6QOalDuajRW3nBazau%2FiY8ZCVm2g30Y10CBDfqJHL1ztV8XM4kEIeulLNTzGVtSb7uuO1OcjZRSb--aDgCPEalq7SIpnH5--HWCNf5readaeij3oDl9b9w%3D%3D; __profilin=p%3Dt%2Ca%3Deef38e031f99cc8240f3518e1b8811cf; _forum_session=RkEWuzKI1QXBYCnP6KRamD8mweZ3h9%2B6G%2Fi23gAWUgy8gp8FuiyQD5lKU0Fbx3FzzaM4SiQcvnIiEAnb5P4OYjlvstqwWlfRp%2B9is7iX8StwYGiYsncHQ5LrzSbV3y9mR7sj%2F8JZ8evQOe2ZZjZB3iEkppsGrmyFrw5PsUgSphRTZm70SKIw96JrW17yK4hhLqtk%2BaQPgNu4oJl42YfXAr%2FCBldcBUKXFeHppYmv61WECV0531hCo7GcA4t06B9QpSr%2BeoiM1Ok9tpQrAlZf36Ka4lVCTyXXu3SNvbtvfd9tZMJCWDYv69jdMsezuOaEP870pk9qYPaL4x6nAY5EXO3u9usCggqQ1B1EydCK9uMy7ZUCIo9wONw7QOIgEQ%3D%3D--GMqYSb2H7xXVDky6--R9gVciBqwC0IL9LefywrFw%3D%3D; _ga_GVR8PEPG6C=GS1.1.1687710574.106.1.1687710599.0.0.0",
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
},
|
||||
"body": `timestamp=${time}`,
|
||||
"method": "PUT"
|
||||
});
|
||||
if (ret && ret.status === 200) {
|
||||
return true;
|
||||
}
|
||||
return;
|
||||
/*
|
||||
let data = new FormData();
|
||||
data.append('timestamp', time);
|
||||
|
||||
try {
|
||||
let ret = await axios.put(url, data, {
|
||||
headers: {
|
||||
//'Accept-Language': 'en-US,en;q=0.8',
|
||||
//'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
//'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
}
|
||||
});
|
||||
debugger
|
||||
} catch (error) {
|
||||
debugger
|
||||
}
|
||||
|
||||
|
||||
return
|
||||
*/
|
||||
/*
|
||||
var options = {
|
||||
method: 'PUT',
|
||||
url: url,
|
||||
headers:
|
||||
{
|
||||
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
},
|
||||
body: `timestamp=${time}`
|
||||
};
|
||||
|
||||
new Promise((resolve, reject) => {
|
||||
request(options, function (error, response, body) {
|
||||
if (error) {
|
||||
throw new Error(error);
|
||||
} else {
|
||||
resolve(body);
|
||||
}
|
||||
});
|
||||
});
|
||||
*/
|
||||
/*
|
||||
var options = {
|
||||
method: 'POST',
|
||||
url: url,
|
||||
headers:
|
||||
{
|
||||
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
},
|
||||
body
|
||||
}
|
||||
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
request(options, function (error, response, body) {
|
||||
if (error) {
|
||||
throw new Error(error);
|
||||
} else {
|
||||
resolve(body);
|
||||
}
|
||||
});
|
||||
});
|
||||
*/
|
||||
// prepare the request
|
||||
const request = {
|
||||
timestamp: time,
|
||||
};
|
||||
// send the update
|
||||
logger.debug('updating', topicID, 'topic timestamp with', request);
|
||||
//const url = `${this.host}/t/${topicID}/change-timestamp`
|
||||
const response = await this.fetch({
|
||||
url,
|
||||
request: {
|
||||
method: 'put',
|
||||
body: `timestamp=${time}`,
|
||||
headers: {
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username,
|
||||
"content-type": "application/x-www-form-urlencoded; charset=UTF-8"
|
||||
}
|
||||
}
|
||||
});
|
||||
// check it
|
||||
if (response.success !== 'OK') {
|
||||
return Promise.reject(new Error(`timestamp update of topic ${topicID} failed:\n${{
|
||||
url,
|
||||
request,
|
||||
response,
|
||||
}}`));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
// =================================
|
||||
// POSTS
|
||||
/**
|
||||
* API Helper for {@link .getPostItemsOfTopic}
|
||||
*/
|
||||
async getPostItemsOfTopicResponse(topicID, opts = {}) {
|
||||
const url = `${this.host}/t/${topicID}/posts.json`;
|
||||
const response = await this.fetch({ url, ...opts });
|
||||
return response;
|
||||
}
|
||||
async _createUser(name, email, pUserGroup) {
|
||||
const pwd = generate({
|
||||
length: 10,
|
||||
numbers: true
|
||||
});
|
||||
let user = await this.createUser({
|
||||
"name": name,
|
||||
"email": email,
|
||||
"password": pwd,
|
||||
"username": name,
|
||||
"active": true,
|
||||
"approved": true,
|
||||
"user_fields[1]": true
|
||||
});
|
||||
if (user && user.user_id) {
|
||||
await this.updateGroup(name, pUserGroup);
|
||||
return { ...user, password: pwd };
|
||||
}
|
||||
else {
|
||||
if (user && user.message && user.message == 'Username must be unique\nPrimary email has already been taken') {
|
||||
return null;
|
||||
}
|
||||
else if (user && user.message && user.message == 'Your account is activated and ready to use.') {
|
||||
if (user.user_id) {
|
||||
return { ...user, password: pwd };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
console.log('cant create user ' + name, user);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
async getUsers(page) {
|
||||
const url = `${this.host}/admin/users/list/active.json?page=` + page;
|
||||
const response = await this.fetch({ url });
|
||||
return response;
|
||||
}
|
||||
async getUser(id) {
|
||||
const url = `${this.host}/admin/users/${id}.json`;
|
||||
const response = await this.fetch({ url });
|
||||
return response;
|
||||
}
|
||||
/**
|
||||
* Fetch the partial information, for all posts of a specific topic
|
||||
*/
|
||||
async getPostItemsOfTopic(topicID, opts = {}) {
|
||||
const response = await this.getPostItemsOfTopicResponse(topicID, opts);
|
||||
const posts = response.post_stream.posts;
|
||||
const ids = posts.map((i) => i.id);
|
||||
return posts;
|
||||
}
|
||||
/**
|
||||
* Fetch the partial information, for all posts of specific topics
|
||||
*/
|
||||
async getPostItemsOfTopics(topicIDs, opts = {}) {
|
||||
// fetch post items for specific topics
|
||||
const postItemsOfTopics = await Promise.all(topicIDs.map((id) => this.getPostItemsOfTopic(id, opts)));
|
||||
// @ts-ignore
|
||||
return postItemsOfTopics.flat();
|
||||
}
|
||||
/**
|
||||
* Fetch the partial information, for all posts of a specific category
|
||||
*/
|
||||
async getPostItemsOfCategory(categoryID, opts = {}) {
|
||||
// fetch topics for the category
|
||||
const topics = await this.getTopicItemsOfCategory(categoryID, opts);
|
||||
const topicIDs = topics.map((i) => i.id);
|
||||
// fetch
|
||||
const posts = await this.getPostItemsOfTopics(topicIDs);
|
||||
const ids = posts.map((i) => i.id);
|
||||
return posts;
|
||||
}
|
||||
/**
|
||||
* Fetch the partial information, for all posts of specific categories
|
||||
*/
|
||||
async getPostItemsOfCategories(categoryIDs, opts = {}) {
|
||||
// fetch post items for specific categories
|
||||
const postItemsOfCategories = await Promise.all(categoryIDs.map((id) => this.getPostItemsOfCategory(id, opts)));
|
||||
// @ts-ignore
|
||||
return postItemsOfCategories.flat();
|
||||
}
|
||||
/**
|
||||
* Fetch the partial information, for all posts of the forum
|
||||
*/
|
||||
async getPostItems(opts = {}) {
|
||||
const categories = await this.getCategories();
|
||||
const categoryIDs = categories.map((i) => i.id);
|
||||
return this.getPostItemsOfCategories(categoryIDs, opts);
|
||||
}
|
||||
/**
|
||||
* Fetch the whole information, for a specific post of the forum
|
||||
*/
|
||||
getPost(id, opts = {}) {
|
||||
const url = `${this.host}/posts/${id}.json`;
|
||||
return this.fetch({ url, ...opts });
|
||||
}
|
||||
async createReply(postId, raw, category) {
|
||||
const url = `${this.host}/posts.json`;
|
||||
let data = new FormData();
|
||||
data.append('topic_id', '' + postId);
|
||||
data.append('raw', raw);
|
||||
data.append('nested_post', 'true');
|
||||
data.append('category', category);
|
||||
var options = {
|
||||
method: 'POST',
|
||||
url: url,
|
||||
headers: {
|
||||
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
},
|
||||
"body": `raw=${raw}&unlist_topic=false&category=${category}&topic_id=${postId}&is_warning=false&archetype=regular&featured_link=&shared_draft=false&nested_post=true`,
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
request(options, function (error, response, body) {
|
||||
if (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
else {
|
||||
resolve(body);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
async changeOwner(postId, topicId, owner) {
|
||||
const url = `${this.host}/t/${topicId}/change-owner.json`;
|
||||
var options = {
|
||||
method: 'POST',
|
||||
url: url,
|
||||
headers: {
|
||||
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
},
|
||||
body: `post_ids%5B%5D=${postId}&username=${owner}`
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
request(options, function (error, response, body) {
|
||||
if (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
else {
|
||||
resolve(body);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
async createUser(data) {
|
||||
const url = `${this.host}/users`;
|
||||
return await this._post(url, data);
|
||||
}
|
||||
async getUserByUsername(username) {
|
||||
const url = `${this.host}/u/${username}.json`;
|
||||
const response = await this.fetch({ url });
|
||||
return response.user;
|
||||
}
|
||||
async setUserAvatar(user_name, upload_id) {
|
||||
// fetch whole posts
|
||||
const url = `${this.host}/u/${user_name}/preferences/avatar/pick.json`;
|
||||
return await axios.put(url, {
|
||||
upload_id,
|
||||
username: user_name,
|
||||
type: 'uploaded'
|
||||
}, {
|
||||
headers: {
|
||||
'accept': 'application/json',
|
||||
'Accept-Language': 'en-US,en;q=0.8',
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
}
|
||||
});
|
||||
}
|
||||
async updateUser(user_name, args) {
|
||||
const url = `${this.host}/u/${user_name}.json`;
|
||||
return await axios.put(url, {
|
||||
...args
|
||||
}, {
|
||||
headers: {
|
||||
'accept': 'application/json',
|
||||
'Accept-Language': 'en-US,en;q=0.8',
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
}
|
||||
});
|
||||
}
|
||||
async updateGroup(user_name, group) {
|
||||
// fetch whole posts
|
||||
const url = `${this.host}/groups/${group}/members.json`;
|
||||
const t = axios.put(url, {
|
||||
usernames: user_name,
|
||||
notify_users: false
|
||||
}, {
|
||||
headers: {
|
||||
'accept': 'application/json',
|
||||
'Accept-Language': 'en-US,en;q=0.8',
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
}
|
||||
});
|
||||
t.then((d) => {
|
||||
}).catch((e) => {
|
||||
//debugger;
|
||||
});
|
||||
return t;
|
||||
}
|
||||
async upload(userId, file) {
|
||||
// fetch whole posts
|
||||
const url = `${this.host}/uploads.json`;
|
||||
let data = new FormData();
|
||||
const fsData = path.parse(file);
|
||||
data.append('file', file, fsData.base);
|
||||
data.append('user_id', userId);
|
||||
data.append('upload_type', 'avatar');
|
||||
data.append('file', fs.createReadStream(file));
|
||||
return await axios.post(url, data, {
|
||||
headers: {
|
||||
'accept': 'application/json',
|
||||
'Accept-Language': 'en-US,en;q=0.8',
|
||||
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
}
|
||||
});
|
||||
}
|
||||
async uploadFile(userId, file) {
|
||||
// fetch whole posts
|
||||
const url = `${this.host}/uploads.json`;
|
||||
let data = new FormData();
|
||||
const fsData = path.parse(file);
|
||||
data.append('file', file, fsData.base);
|
||||
data.append('user_id', userId);
|
||||
data.append('upload_type', 'composer');
|
||||
data.append('file', fs.createReadStream(file));
|
||||
return await axios.post(url, data, {
|
||||
headers: {
|
||||
'accept': 'application/json',
|
||||
'Accept-Language': 'en-US,en;q=0.8',
|
||||
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
}
|
||||
});
|
||||
}
|
||||
// =================================
|
||||
// POSTS: UPDATING
|
||||
/**
|
||||
* Fetch the whole information, for all posts, or specific posts, of the forum
|
||||
*/
|
||||
async getPosts(postIDs, opts = {}) {
|
||||
// if no posts, use all
|
||||
if (!postIDs) {
|
||||
const posts = await this.getPostItems(opts);
|
||||
postIDs = posts.map((i) => i.id);
|
||||
}
|
||||
// fetch whole posts
|
||||
return await Promise.all(postIDs.map((id) => this.getPost(id, opts)));
|
||||
}
|
||||
async createPost(title, raw, category) {
|
||||
// fetch whole posts
|
||||
const url = `${this.host}/posts`;
|
||||
return new Promise((resolve) => {
|
||||
return this._post(url, { raw, title, category }).then((d) => {
|
||||
resolve(d);
|
||||
}).catch((e) => {
|
||||
resolve(e.response.data);
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Update a post with the content
|
||||
* @param postID the identifier of the post to update
|
||||
* @param content the new raw content for the post
|
||||
* @param reason the reason, if provided, for modifying the post
|
||||
* @param old if the old raw content is provided, then the update verified that you are working with the latest post content before applying the update
|
||||
*/
|
||||
async updatePost(postID, content, reason = 'api update', old) {
|
||||
// prepare the request
|
||||
const data = {
|
||||
post: {
|
||||
raw: content,
|
||||
edit_reason: reason,
|
||||
},
|
||||
};
|
||||
if (old) {
|
||||
data.post.raw_old = old;
|
||||
}
|
||||
// send the update
|
||||
const url = `${this.host}/posts/${postID}.json`;
|
||||
const response = await this.fetch({
|
||||
url,
|
||||
request: {
|
||||
method: 'put',
|
||||
body: JSON.stringify(data),
|
||||
},
|
||||
});
|
||||
// return the response
|
||||
return response.post;
|
||||
}
|
||||
/**
|
||||
* Update post meta
|
||||
*/
|
||||
async updateTopic(postId, category_id, title, tags) {
|
||||
const data = {
|
||||
title,
|
||||
tags: tags || [],
|
||||
featuredLink: null,
|
||||
category_id
|
||||
};
|
||||
const url = `${this.host}/t/${postId}.json`;
|
||||
const response = await this.fetch({
|
||||
url,
|
||||
request: {
|
||||
method: 'put',
|
||||
body: JSON.stringify(data),
|
||||
},
|
||||
});
|
||||
return response.basic_topic;
|
||||
}
|
||||
async rebakePost(postID) {
|
||||
const url = `${this.host}/posts/${postID}/rebake`;
|
||||
logger.debug('rebaking', postID);
|
||||
const response = await this.fetch({
|
||||
url,
|
||||
request: {
|
||||
method: 'put'
|
||||
}
|
||||
});
|
||||
logger.debug('rebaked', postID);
|
||||
return response;
|
||||
}
|
||||
/**
|
||||
* Modify a post using a modifier
|
||||
*/
|
||||
async modifyPost(post, modifier) {
|
||||
// check if we received a post item, instead of a post response
|
||||
if (post.raw == null) {
|
||||
post = await this.getPost(post.id);
|
||||
}
|
||||
// check
|
||||
if (!post.raw) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
// replace
|
||||
const { result, reason } = modifier(post);
|
||||
if (result === post.raw) {
|
||||
// if (post.cooked) {
|
||||
// const { result, reason } = modifier(post.cooked)
|
||||
// if (result !== post.cooked) {
|
||||
// logger.debug(
|
||||
// 'replace did have an effect on cooked post',
|
||||
// postID,
|
||||
// 'so rebaking it'
|
||||
// )
|
||||
// return await this.rebakePost(postID)
|
||||
// }
|
||||
// }
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
// dry
|
||||
if (this.dry) {
|
||||
return Promise.resolve({
|
||||
...post,
|
||||
result,
|
||||
reason,
|
||||
});
|
||||
}
|
||||
// update
|
||||
try {
|
||||
return await this.updatePost(post.id, result, reason, post.raw);
|
||||
}
|
||||
catch (err) {
|
||||
if (err.message.includes('That post was edited by another user and your changes can no longer be saved.')) {
|
||||
return this.modifyPost(await this.getPost(post.id, { useCache: false }), modifier);
|
||||
}
|
||||
logger.error(err);
|
||||
return Promise.reject(`modifying post ${post.id} failed`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Modify a post (via its post identifier) using a modifier
|
||||
*/
|
||||
async modifyPostID(post, modifier) {
|
||||
return this.modifyPost(await this.getPost(post), modifier);
|
||||
}
|
||||
/**
|
||||
* Modify a post (via fetching the whole post from the partial post identifier) using a modifier
|
||||
*/
|
||||
async modifyPostItem(post, modifier) {
|
||||
return this.modifyPost(await this.getPost(post.id), modifier);
|
||||
}
|
||||
/**
|
||||
* Run the post modifier on all specified posts
|
||||
*/
|
||||
async modifyPosts(posts, modifier) {
|
||||
const updates = await Promise.all(posts.map((post) => this.modifyPost(post, modifier)));
|
||||
const updated = updates.filter((i) => i);
|
||||
return updated;
|
||||
}
|
||||
// =================================
|
||||
// THREADS
|
||||
/**
|
||||
* Fetch the partial information, for all posts of a specific topic
|
||||
* Alias of {@link .getPostItemsOfTopic}.
|
||||
*/
|
||||
async getThread(topicID, opts = {}) {
|
||||
const topic = await this.getTopic(topicID, opts);
|
||||
const [post, ...replies] = await this.getPostItemsOfTopic(topicID, opts);
|
||||
return {
|
||||
topic,
|
||||
post,
|
||||
replies,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Fetch the partial information, for all posts of specific topics, grouped by topic
|
||||
*/
|
||||
async getThreads(topicIDs, opts = {}) {
|
||||
return await Promise.all(topicIDs.map((id) => this.getThread(id, opts)));
|
||||
}
|
||||
/**
|
||||
* Fetch the partial information, for all posts of specific categories, grouped by topic
|
||||
*/
|
||||
async getThreadsOfCategory(categoryID, opts = {}) {
|
||||
// fetch topics for the category
|
||||
const topics = await this.getTopicItemsOfCategory(categoryID, opts);
|
||||
const topicIDs = topics.map((i) => i.id);
|
||||
// return threads
|
||||
return await this.getThreads(topicIDs);
|
||||
}
|
||||
/**
|
||||
* Fetch the partial information, for all posts of specific categories, grouped by category, then topic
|
||||
*/
|
||||
async getThreadsOfCategories(categoryIDs, opts = {}) {
|
||||
return await Promise.all(categoryIDs.map((id) => this.getThreadsOfCategory(id, opts)));
|
||||
}
|
||||
async updateUserProfile(userId, prefs) {
|
||||
const url = `${this.host}/u/${userId}.json`;
|
||||
let data = new FormData();
|
||||
data.append('bio_raw', prefs.bio_raw);
|
||||
prefs.location && data.append('location', prefs.location);
|
||||
prefs.website && data.append('website', prefs.website);
|
||||
return await axios.put(url, data, {
|
||||
headers: {
|
||||
'accept': 'application/json',
|
||||
'Accept-Language': 'en-US,en;q=0.8',
|
||||
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
'Api-Key': this.key,
|
||||
'Api-Username': this.username
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
export const Instance = (config, key = 'discourse_admin') => {
|
||||
return new Discourser(config || CONFIG_DEFAULT()[key]);
|
||||
/*
|
||||
|
||||
d.getTopicItemsOfCategories([cat]).then(posts => {
|
||||
//console.log('posts', posts)
|
||||
let content = "<ul>"
|
||||
posts = posts.map((p) => {
|
||||
const url = `${config.discourse.host}/t/${p.id}`;
|
||||
const title = `${p.fancy_title}`;
|
||||
return `<li><a href="${url}">${title}</a></li>`;
|
||||
}).join('\n');
|
||||
content += posts + "</ul>";
|
||||
resolve(content);
|
||||
|
||||
});
|
||||
*/
|
||||
};
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
packages/discourse-legacy/dist/lib/discourse/index.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/discourse/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
697
packages/discourse-legacy/dist/lib/discourse/types.d.ts
vendored
Normal file
697
packages/discourse-legacy/dist/lib/discourse/types.d.ts
vendored
Normal file
@ -0,0 +1,697 @@
|
||||
export interface Failure {
|
||||
success: 'OK';
|
||||
}
|
||||
export interface Success {
|
||||
failed: 'FAILED';
|
||||
}
|
||||
export type Response = Failure & Success;
|
||||
export interface Action {
|
||||
can_act: boolean;
|
||||
id: number;
|
||||
count?: number;
|
||||
hidden?: boolean;
|
||||
}
|
||||
export interface Poster {
|
||||
description: string;
|
||||
extras: string;
|
||||
user_id: number;
|
||||
}
|
||||
export interface Person {
|
||||
avatar_template: string;
|
||||
id: number;
|
||||
username: string;
|
||||
}
|
||||
export interface Participant extends Person {
|
||||
post_count: number;
|
||||
}
|
||||
export interface Link {
|
||||
url: string;
|
||||
internal: boolean;
|
||||
reflection: boolean;
|
||||
title: string;
|
||||
clicks: number;
|
||||
}
|
||||
/**
|
||||
* Update a Topic Timestamp
|
||||
* https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}~1change-timestamp/put
|
||||
*/
|
||||
export interface TopicUpdateTimestampRequest {
|
||||
timestamp: number;
|
||||
}
|
||||
export type TopicUpdateTimestampResponse = Response;
|
||||
/**
|
||||
* Update a Post
|
||||
* https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/put
|
||||
*/
|
||||
export interface PostUpdateResponse {
|
||||
post: PostUpdateItem;
|
||||
}
|
||||
export interface TopicUpdateBasicTopic {
|
||||
fancy_title: string;
|
||||
id: number;
|
||||
posts_count: number;
|
||||
slug: string;
|
||||
title: string;
|
||||
}
|
||||
export interface TopicUpdateResponse {
|
||||
basic_topic: TopicUpdateBasicTopic;
|
||||
}
|
||||
export interface PostUpdateItem {
|
||||
actions_summary: Array<Action>;
|
||||
admin: boolean;
|
||||
avatar_template: string;
|
||||
avg_time: object;
|
||||
can_delete: boolean;
|
||||
can_edit: boolean;
|
||||
can_recover: boolean;
|
||||
can_view_edit_history: boolean;
|
||||
can_wiki: boolean;
|
||||
cooked: string;
|
||||
created_at: string;
|
||||
deleted_at: object;
|
||||
display_username: string;
|
||||
draft_sequence: number;
|
||||
edit_reason: object;
|
||||
hidden_reason_id: object;
|
||||
hidden: boolean;
|
||||
id: number;
|
||||
incoming_link_count: number;
|
||||
moderator: boolean;
|
||||
name: string;
|
||||
post_number: number;
|
||||
post_type: number;
|
||||
primary_group_flair_bg_color: object;
|
||||
primary_group_flair_color: object;
|
||||
primary_group_flair_url: object;
|
||||
primary_group_name: object;
|
||||
quote_count: number;
|
||||
reads: number;
|
||||
reply_count: number;
|
||||
reply_to_post_number: object;
|
||||
score: number;
|
||||
staff: boolean;
|
||||
topic_id: number;
|
||||
topic_slug: string;
|
||||
trust_level: number;
|
||||
updated_at: string;
|
||||
user_deleted: boolean;
|
||||
user_id: number;
|
||||
user_title: object;
|
||||
username: string;
|
||||
version: number;
|
||||
wiki: boolean;
|
||||
yours: boolean;
|
||||
}
|
||||
export interface PostUpdateRequest {
|
||||
post: {
|
||||
raw: string;
|
||||
raw_old?: string;
|
||||
edit_reason?: string;
|
||||
cooked?: string;
|
||||
};
|
||||
}
|
||||
export interface TagsResponse {
|
||||
tags: Tag[];
|
||||
extras: TagsExtras;
|
||||
}
|
||||
export interface TagsExtras {
|
||||
categories: any[];
|
||||
}
|
||||
export interface Tag {
|
||||
count: number;
|
||||
description: null;
|
||||
id: string;
|
||||
name: string;
|
||||
pm_only: boolean;
|
||||
target_tag: null;
|
||||
text: string;
|
||||
}
|
||||
/** https://docs.discourse.org/#tag/Categories/paths/~1categories.json/get */
|
||||
export interface CategoriesResponse {
|
||||
category_list: {
|
||||
can_create_category: boolean;
|
||||
can_create_topic: boolean;
|
||||
categories: Category[];
|
||||
draft_key: string;
|
||||
draft_sequence: number;
|
||||
draft: boolean;
|
||||
};
|
||||
}
|
||||
export interface Category {
|
||||
background_url: string;
|
||||
can_edit: boolean;
|
||||
color: string;
|
||||
description_excerpt: string;
|
||||
description_text: string;
|
||||
description: string;
|
||||
has_children: boolean;
|
||||
id: number;
|
||||
logo_url: string;
|
||||
name: string;
|
||||
notification_level: string;
|
||||
permission: number;
|
||||
position: number;
|
||||
post_count: number;
|
||||
read_restricted: boolean;
|
||||
slug: string;
|
||||
text_color: string;
|
||||
topic_count: number;
|
||||
topic_template: string;
|
||||
topic_url: string;
|
||||
topics_all_time: number;
|
||||
topics_day: number;
|
||||
topics_month: number;
|
||||
topics_week: number;
|
||||
topics_year: number;
|
||||
}
|
||||
/**
|
||||
* Get Single Topic
|
||||
* https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}.json/get
|
||||
*/
|
||||
export interface TopicResponse {
|
||||
actions_summary: Array<Action>;
|
||||
archetype: string;
|
||||
archived: boolean;
|
||||
bookmarked: object;
|
||||
category_id: number;
|
||||
chunk_size: number;
|
||||
closed: boolean;
|
||||
created_at: string;
|
||||
deleted_at: object;
|
||||
deleted_by: object;
|
||||
details: TopicDetails;
|
||||
draft_key: string;
|
||||
draft_sequence: object;
|
||||
draft: object;
|
||||
fancy_title: string;
|
||||
has_summary: boolean;
|
||||
highest_post_number: number;
|
||||
id: number;
|
||||
last_posted_at: object;
|
||||
like_count: number;
|
||||
participant_count: number;
|
||||
pinned_at: string;
|
||||
pinned_globally: boolean;
|
||||
pinned_until: object;
|
||||
pinned: boolean;
|
||||
posts_count: number;
|
||||
reply_count: number;
|
||||
slug: string;
|
||||
tags: string[];
|
||||
title: string;
|
||||
unpinned: object;
|
||||
user_id: number;
|
||||
views: number;
|
||||
visible: boolean;
|
||||
word_count: object;
|
||||
post_stream: {
|
||||
posts: Array<PostItem>;
|
||||
stream: Array<object>;
|
||||
};
|
||||
timeline_lookup: [
|
||||
{
|
||||
'0': Array<object>;
|
||||
}
|
||||
];
|
||||
}
|
||||
export interface TopicDetails {
|
||||
auto_close_at: object;
|
||||
auto_close_based_on_last_post: boolean;
|
||||
auto_close_hours: object;
|
||||
can_flag_topic: boolean;
|
||||
created_by: Person;
|
||||
last_poster: Person;
|
||||
notification_level: number;
|
||||
participants: Array<Participant>;
|
||||
suggested_topics: Array<TopicItem>;
|
||||
}
|
||||
export interface TopicItem {
|
||||
archetype: string;
|
||||
archived: boolean;
|
||||
bookmarked: object;
|
||||
bumped_at: string;
|
||||
bumped: boolean;
|
||||
category_id: number;
|
||||
closed: boolean;
|
||||
created_at: string;
|
||||
excerpt: string;
|
||||
fancy_title: string;
|
||||
has_summary: boolean;
|
||||
highest_post_number: number;
|
||||
id: number;
|
||||
image_url: string;
|
||||
last_posted_at: string;
|
||||
last_poster_username: string;
|
||||
like_count: number;
|
||||
liked: object;
|
||||
pinned_globally: boolean;
|
||||
pinned: boolean;
|
||||
posters: Array<Poster>;
|
||||
posts_count: number;
|
||||
reply_count: number;
|
||||
slug: string;
|
||||
title: string;
|
||||
unpinned: boolean;
|
||||
unseen: boolean;
|
||||
views: number;
|
||||
visible: boolean;
|
||||
}
|
||||
/**
|
||||
* Get Topics for Category
|
||||
* https://docs.discourse.org/#tag/Categories/paths/~1c~1{id}.json/get
|
||||
*/
|
||||
export interface CategoryResponse {
|
||||
users: Person[];
|
||||
topic_list: {
|
||||
can_create_topic: boolean;
|
||||
draft: boolean;
|
||||
draft_key: string;
|
||||
draft_sequence: number;
|
||||
per_page: number;
|
||||
topics: Array<TopicItem>;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Whole Post Information
|
||||
* As returned by getting a single Post
|
||||
* https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/get
|
||||
*/
|
||||
export interface PostResponse {
|
||||
actions_summary: Array<Action>;
|
||||
admin: boolean;
|
||||
avatar_template: string;
|
||||
avg_time: object;
|
||||
can_delete: boolean;
|
||||
can_edit: boolean;
|
||||
can_recover: boolean;
|
||||
can_view_edit_history: boolean;
|
||||
can_wiki: boolean;
|
||||
cooked: string;
|
||||
created_at: string;
|
||||
deleted_at: object;
|
||||
display_username: string;
|
||||
edit_reason: object;
|
||||
hidden_reason_id: object;
|
||||
hidden: boolean;
|
||||
id: number;
|
||||
incoming_link_count: number;
|
||||
moderator: boolean;
|
||||
name: string;
|
||||
post_number: number;
|
||||
post_type: number;
|
||||
primary_group_flair_bg_color: object;
|
||||
primary_group_flair_color: object;
|
||||
primary_group_flair_url: object;
|
||||
primary_group_name: object;
|
||||
quote_count: number;
|
||||
raw: string;
|
||||
reads: number;
|
||||
reply_count: number;
|
||||
reply_to_post_number: object;
|
||||
score: number;
|
||||
staff: boolean;
|
||||
topic_id: number;
|
||||
topic_slug: string;
|
||||
trust_level: number;
|
||||
updated_at: string;
|
||||
user_deleted: boolean;
|
||||
user_id: number;
|
||||
user_title: object;
|
||||
username: string;
|
||||
version: number;
|
||||
wiki: boolean;
|
||||
yours: boolean;
|
||||
}
|
||||
export interface ICreateUserResponse {
|
||||
success: boolean;
|
||||
active: boolean;
|
||||
message: string;
|
||||
user_id: number;
|
||||
password: string;
|
||||
}
|
||||
/**
|
||||
* Get the Posts of a Topic
|
||||
* https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}~1posts.json/get
|
||||
*/
|
||||
export interface PostsResponse {
|
||||
post_stream: {
|
||||
posts: Array<PostItem>;
|
||||
};
|
||||
id: number;
|
||||
}
|
||||
/**
|
||||
* Partial Post Information
|
||||
* As returned by a listing
|
||||
*/
|
||||
export interface PostItem {
|
||||
accepted_answer: boolean;
|
||||
actions_summary: Array<Action>;
|
||||
admin: boolean;
|
||||
avatar_template: string;
|
||||
can_accept_answer: boolean;
|
||||
can_delete: boolean;
|
||||
can_edit: boolean;
|
||||
can_recover: boolean;
|
||||
can_unaccept_answer: boolean;
|
||||
can_view_edit_history: boolean;
|
||||
can_wiki: boolean;
|
||||
cooked: string;
|
||||
created_at: string;
|
||||
deleted_at: null;
|
||||
display_username: string;
|
||||
edit_reason: null;
|
||||
hidden: boolean;
|
||||
id: number;
|
||||
incoming_link_count: number;
|
||||
link_counts: Array<Link>;
|
||||
moderator: boolean;
|
||||
name: string;
|
||||
post_number: number;
|
||||
post_type: number;
|
||||
primary_group_flair_bg_color: null | object;
|
||||
primary_group_flair_color: null | object;
|
||||
primary_group_flair_url: null | object;
|
||||
primary_group_name: null | object;
|
||||
quote_count: number;
|
||||
read: boolean;
|
||||
readers_count: number;
|
||||
reads: number;
|
||||
reply_count: number;
|
||||
reply_to_post_number: null | number;
|
||||
reviewable_id: number;
|
||||
reviewable_score_count: number;
|
||||
reviewable_score_pending_count: number;
|
||||
score: number;
|
||||
staff: boolean;
|
||||
topic_id: number;
|
||||
topic_slug: string;
|
||||
trust_level: number;
|
||||
updated_at: string;
|
||||
user_deleted: boolean;
|
||||
user_id: number;
|
||||
user_title: null | object;
|
||||
username: string;
|
||||
version: number;
|
||||
wiki: boolean;
|
||||
yours: boolean;
|
||||
}
|
||||
export type Thread = {
|
||||
topic: TopicResponse;
|
||||
post: PostItem;
|
||||
replies: PostItem[];
|
||||
};
|
||||
/** When finding and replacing, determine replacements using a method that matches this */
|
||||
export type PostModifier = (post: PostResponse) => {
|
||||
result: string;
|
||||
reason?: string;
|
||||
};
|
||||
/** Configuration for Discourser */
|
||||
export interface IDiscourserConfig {
|
||||
/** the discourse hostname to connect to, including protocol */
|
||||
host: string;
|
||||
/** the API key to connect with */
|
||||
key: string;
|
||||
/** the username to behave as */
|
||||
username: string;
|
||||
/** the cache directory to use, if we are caching */
|
||||
cache?: string;
|
||||
/** Whether or not we should read from the cache */
|
||||
useCache?: boolean;
|
||||
/** whether or not updates should be dry (non-applying) */
|
||||
dry?: boolean;
|
||||
/** how many concurrency requests to send to the server at once */
|
||||
rateLimitConcurrency?: number;
|
||||
}
|
||||
export interface FetchOptions {
|
||||
/** Whether or not we should read from the cache */
|
||||
useCache?: boolean;
|
||||
/** Only applicable to fetching topics of category */
|
||||
page?: number;
|
||||
/** Any thing to init the fetch call with? */
|
||||
request?: RequestInit;
|
||||
include_subcategories?: boolean;
|
||||
}
|
||||
export interface FetchConfig extends FetchOptions {
|
||||
url: string;
|
||||
}
|
||||
export interface PostConfig extends FetchOptions {
|
||||
url: string;
|
||||
data: any;
|
||||
}
|
||||
export interface ISearchPost {
|
||||
id: number;
|
||||
name: string;
|
||||
username: string;
|
||||
avatar_template: string;
|
||||
created_at: Date;
|
||||
like_count: number;
|
||||
blurb: string;
|
||||
post_number: number;
|
||||
topic_id: number;
|
||||
}
|
||||
export interface ISearchTagsDescriptions {
|
||||
}
|
||||
export interface ISearchTopic {
|
||||
id: number;
|
||||
title: string;
|
||||
fancy_title: string;
|
||||
slug: string;
|
||||
posts_count: number;
|
||||
reply_count: number;
|
||||
highest_post_number: number;
|
||||
created_at: Date;
|
||||
last_posted_at: Date;
|
||||
bumped: boolean;
|
||||
bumped_at: Date;
|
||||
archetype: string;
|
||||
unseen: boolean;
|
||||
pinned: boolean;
|
||||
unpinned?: any;
|
||||
excerpt: string;
|
||||
visible: boolean;
|
||||
closed: boolean;
|
||||
archived: boolean;
|
||||
bookmarked?: any;
|
||||
liked?: any;
|
||||
tags: any[];
|
||||
tags_descriptions: ISearchTagsDescriptions;
|
||||
category_id: number;
|
||||
has_accepted_answer: boolean;
|
||||
}
|
||||
export interface IGroupedSearchResult {
|
||||
more_posts?: any;
|
||||
more_users?: any;
|
||||
more_categories?: any;
|
||||
term: string;
|
||||
search_log_id: number;
|
||||
more_full_page_results?: any;
|
||||
can_create_topic: boolean;
|
||||
error?: any;
|
||||
post_ids: number[];
|
||||
user_ids: any[];
|
||||
category_ids: any[];
|
||||
tag_ids: any[];
|
||||
group_ids: any[];
|
||||
}
|
||||
export interface ISearchResult {
|
||||
posts: ISearchPost[];
|
||||
topics: ISearchTopic[];
|
||||
users: any[];
|
||||
categories: any[];
|
||||
tags: any[];
|
||||
groups: any[];
|
||||
grouped_search_result: IGroupedSearchResult;
|
||||
}
|
||||
export interface IUserDetail {
|
||||
id: number;
|
||||
username: string;
|
||||
name: string;
|
||||
avatar_template: string;
|
||||
email: string;
|
||||
secondary_emails: any[];
|
||||
active: boolean;
|
||||
admin: boolean;
|
||||
moderator: boolean;
|
||||
last_seen_at: string;
|
||||
last_emailed_at: string;
|
||||
created_at: string;
|
||||
last_seen_age: number;
|
||||
last_emailed_age: number;
|
||||
created_at_age: number;
|
||||
trust_level: number;
|
||||
manual_locked_trust_level: any;
|
||||
flag_level: number;
|
||||
title: string;
|
||||
time_read: number;
|
||||
staged: boolean;
|
||||
days_visited: number;
|
||||
posts_read_count: number;
|
||||
topics_entered: number;
|
||||
post_count: number;
|
||||
associated_accounts: AssociatedAccount[];
|
||||
can_send_activation_email: boolean;
|
||||
can_activate: boolean;
|
||||
can_deactivate: boolean;
|
||||
ip_address: string;
|
||||
registration_ip_address: string;
|
||||
can_grant_admin: boolean;
|
||||
can_revoke_admin: boolean;
|
||||
can_grant_moderation: boolean;
|
||||
can_revoke_moderation: boolean;
|
||||
can_impersonate: boolean;
|
||||
like_count: number;
|
||||
like_given_count: number;
|
||||
topic_count: number;
|
||||
post_edits_count: number;
|
||||
flags_given_count: number;
|
||||
flags_received_count: number;
|
||||
private_topics_count: number;
|
||||
can_delete_all_posts: boolean;
|
||||
can_be_deleted: boolean;
|
||||
can_be_anonymized: boolean;
|
||||
can_be_merged: boolean;
|
||||
full_suspend_reason: any;
|
||||
silence_reason: any;
|
||||
penalty_counts: PenaltyCounts;
|
||||
next_penalty: string;
|
||||
primary_group_id: any;
|
||||
badge_count: number;
|
||||
warnings_received_count: number;
|
||||
user_fields: UserFields;
|
||||
bounce_score: number;
|
||||
reset_bounce_score_after: any;
|
||||
can_view_action_logs: boolean;
|
||||
can_disable_second_factor: boolean;
|
||||
can_delete_sso_record: boolean;
|
||||
api_key_count: number;
|
||||
external_ids: ExternalIds;
|
||||
single_sign_on_record: any;
|
||||
approved_by: ApprovedBy;
|
||||
suspended_by: any;
|
||||
silenced_by: any;
|
||||
tl3_requirements: Tl3Requirements;
|
||||
groups: Group[];
|
||||
}
|
||||
export interface AssociatedAccount {
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
export interface PenaltyCounts {
|
||||
silenced: number;
|
||||
suspended: number;
|
||||
}
|
||||
export interface UserFields {
|
||||
"1": string;
|
||||
"2": string;
|
||||
"3": string;
|
||||
"4": string;
|
||||
"5": string;
|
||||
}
|
||||
export interface ExternalIds {
|
||||
google_oauth2: string;
|
||||
}
|
||||
export interface ApprovedBy {
|
||||
id: number;
|
||||
username: string;
|
||||
name: string;
|
||||
avatar_template: string;
|
||||
}
|
||||
export interface Tl3Requirements {
|
||||
time_period: number;
|
||||
requirements_met: boolean;
|
||||
requirements_lost: boolean;
|
||||
trust_level_locked: boolean;
|
||||
on_grace_period: boolean;
|
||||
days_visited: number;
|
||||
min_days_visited: number;
|
||||
num_topics_replied_to: number;
|
||||
min_topics_replied_to: number;
|
||||
topics_viewed: number;
|
||||
min_topics_viewed: number;
|
||||
posts_read: number;
|
||||
min_posts_read: number;
|
||||
topics_viewed_all_time: number;
|
||||
min_topics_viewed_all_time: number;
|
||||
posts_read_all_time: number;
|
||||
min_posts_read_all_time: number;
|
||||
num_flagged_posts: number;
|
||||
max_flagged_posts: number;
|
||||
num_flagged_by_users: number;
|
||||
max_flagged_by_users: number;
|
||||
num_likes_given: number;
|
||||
min_likes_given: number;
|
||||
num_likes_received: number;
|
||||
min_likes_received: number;
|
||||
num_likes_received_days: number;
|
||||
min_likes_received_days: number;
|
||||
num_likes_received_users: number;
|
||||
min_likes_received_users: number;
|
||||
penalty_counts: PenaltyCounts2;
|
||||
}
|
||||
export interface PenaltyCounts2 {
|
||||
silenced: number;
|
||||
suspended: number;
|
||||
total: number;
|
||||
}
|
||||
export interface Group {
|
||||
id: number;
|
||||
automatic: boolean;
|
||||
name: string;
|
||||
display_name?: string;
|
||||
user_count: number;
|
||||
mentionable_level: number;
|
||||
messageable_level: number;
|
||||
visibility_level: number;
|
||||
primary_group: boolean;
|
||||
title: any;
|
||||
grant_trust_level?: number;
|
||||
incoming_email: any;
|
||||
has_messages: boolean;
|
||||
flair_url: any;
|
||||
flair_bg_color?: string;
|
||||
flair_color?: string;
|
||||
bio_raw?: string;
|
||||
bio_cooked?: string;
|
||||
bio_excerpt?: string;
|
||||
public_admission: boolean;
|
||||
public_exit: boolean;
|
||||
allow_membership_requests: boolean;
|
||||
full_name?: string;
|
||||
default_notification_level: number;
|
||||
membership_request_template: any;
|
||||
members_visibility_level: number;
|
||||
can_see_members: boolean;
|
||||
can_admin_group: boolean;
|
||||
publish_read_state: boolean;
|
||||
can_edit_group?: boolean;
|
||||
}
|
||||
export type TPostStatus = 'visible' | 'archived' | 'pinned' | 'closed';
|
||||
export interface TPostStatusUpdate {
|
||||
success: string;
|
||||
topic_status_update: any;
|
||||
}
|
||||
export interface UserPreferencesUpdate {
|
||||
bio_raw?: string;
|
||||
website?: string;
|
||||
location?: string;
|
||||
custom_fields?: CustomFields;
|
||||
timezone?: string;
|
||||
default_calendar?: string;
|
||||
profile_background_upload_url?: string;
|
||||
card_background_upload_url?: string;
|
||||
}
|
||||
export interface CustomFields {
|
||||
geo_location: GeoLocation;
|
||||
}
|
||||
export interface GeoLocation {
|
||||
lat: string;
|
||||
lon: string;
|
||||
address: string;
|
||||
countrycode: string;
|
||||
city: string;
|
||||
state: string;
|
||||
country: string;
|
||||
postalcode: string;
|
||||
boundingbox: string[];
|
||||
type: string;
|
||||
}
|
||||
4
packages/discourse-legacy/dist/lib/discourse/types.js
vendored
Normal file
4
packages/discourse-legacy/dist/lib/discourse/types.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
// Attempt at TypeScript Types for the Discourse API
|
||||
// https://docs.discourse.org
|
||||
export {};
|
||||
//# sourceMappingURL=types.js.map
|
||||
1
packages/discourse-legacy/dist/lib/discourse/types.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/discourse/types.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/discourse/types.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,6BAA6B"}
|
||||
5
packages/discourse-legacy/dist/lib/git/index.d.ts
vendored
Normal file
5
packages/discourse-legacy/dist/lib/git/index.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
export declare function git_status(cwd: any, dir: any): Promise<any>;
|
||||
export declare function git_log(cwd: any, dir: any): Promise<{
|
||||
files: any;
|
||||
last: any;
|
||||
}>;
|
||||
34
packages/discourse-legacy/dist/lib/git/index.js
vendored
Normal file
34
packages/discourse-legacy/dist/lib/git/index.js
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
import { logger } from '../../index';
|
||||
const GIT_CHANGELOG_MESSAGE_PREFIX = '';
|
||||
import * as simpleGit from 'simple-git/promise';
|
||||
import * as moment from 'moment';
|
||||
export async function git_status(cwd, dir) {
|
||||
const git = simpleGit(cwd);
|
||||
let statusSummary = null;
|
||||
try {
|
||||
statusSummary = await git.log(['--stat', dir]);
|
||||
}
|
||||
catch (e) {
|
||||
logger.error('Error Git', e);
|
||||
}
|
||||
return statusSummary;
|
||||
}
|
||||
export async function git_log(cwd, dir) {
|
||||
const stats = await git_status(cwd, dir);
|
||||
logger.info(`Reading Git log at ${cwd}/${dir}`);
|
||||
let changelogs = stats.all.filter((e) => e.message.trim().toLowerCase().startsWith(GIT_CHANGELOG_MESSAGE_PREFIX.toLowerCase()));
|
||||
if (!changelogs.length) {
|
||||
return { files: [], last: stats.latest };
|
||||
}
|
||||
let pretty = changelogs.map((e) => {
|
||||
return {
|
||||
files: e.diff.files.map((f) => { return { path: f.file }; }),
|
||||
msg: e.message.toLowerCase().replace(GIT_CHANGELOG_MESSAGE_PREFIX.toLowerCase(), '').trim(),
|
||||
hash: e.hash,
|
||||
date: moment(e.date).format('LLLL')
|
||||
};
|
||||
});
|
||||
return { files: pretty, last: stats.latest };
|
||||
}
|
||||
;
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
packages/discourse-legacy/dist/lib/git/index.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/git/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/git/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAA;AAElC,MAAM,4BAA4B,GAAG,EAAE,CAAA;AAIvC,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAC;AAEhD,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAG,EAAE,GAAG;IAErC,MAAM,GAAG,GAAc,SAAS,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,aAAa,GAAO,IAAI,CAAC;IAC7B,IAAI;QACA,aAAa,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;KAClD;IACD,OAAO,CAAC,EAAE;QACN,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;KAChC;IACD,OAAO,aAAa,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAG,EAAE,GAAG;IAClC,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACzC,MAAM,CAAC,IAAI,CAAC,sBAAsB,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC;IAChD,IAAI,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,4BAA4B,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAChI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;QACpB,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAC,KAAK,CAAC,MAAM,EAAE,CAAA;KAC1C;IACD,IAAI,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC9B,OAAO;YACH,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA,CAAC,CAAC,CAAC;YAC3D,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,4BAA4B,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE;YAC3F,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;SACtC,CAAA;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AACjD,CAAC;AAAA,CAAC"}
|
||||
2
packages/discourse-legacy/dist/lib/index.d.ts
vendored
Normal file
2
packages/discourse-legacy/dist/lib/index.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './discourse';
|
||||
export * from './discourse/types';
|
||||
3
packages/discourse-legacy/dist/lib/index.js
vendored
Normal file
3
packages/discourse-legacy/dist/lib/index.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './discourse';
|
||||
export * from './discourse/types';
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
packages/discourse-legacy/dist/lib/index.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA"}
|
||||
7
packages/discourse-legacy/dist/lib/markdown/Pattern.d.ts
vendored
Normal file
7
packages/discourse-legacy/dist/lib/markdown/Pattern.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import { RegExCallback } from './types';
|
||||
export declare class Pattern {
|
||||
regex: RegExp;
|
||||
replacement: RegExCallback;
|
||||
constructor(regex: RegExp, replacement: any);
|
||||
apply(raw: string): string;
|
||||
}
|
||||
12
packages/discourse-legacy/dist/lib/markdown/Pattern.js
vendored
Normal file
12
packages/discourse-legacy/dist/lib/markdown/Pattern.js
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
export class Pattern {
|
||||
regex;
|
||||
replacement;
|
||||
constructor(regex, replacement) {
|
||||
this.regex = regex;
|
||||
this.replacement = replacement;
|
||||
}
|
||||
apply(raw) {
|
||||
return raw.replace(this.regex, this.replacement);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=Pattern.js.map
|
||||
1
packages/discourse-legacy/dist/lib/markdown/Pattern.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/markdown/Pattern.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Pattern.js","sourceRoot":"","sources":["../../../src/lib/markdown/Pattern.ts"],"names":[],"mappings":"AACA,MAAM,OAAO,OAAO;IAClB,KAAK,CAAS;IACd,WAAW,CAAe;IAC1B,YAAY,KAAa,EAAE,WAAgB;QACzC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAA;IAChC,CAAC;IAED,KAAK,CAAC,GAAW;QACf,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;IAClD,CAAC;CACF"}
|
||||
7
packages/discourse-legacy/dist/lib/markdown/Rule.d.ts
vendored
Normal file
7
packages/discourse-legacy/dist/lib/markdown/Rule.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import { Pattern } from './Pattern';
|
||||
export declare class Rule {
|
||||
name: string;
|
||||
patterns: Pattern[];
|
||||
constructor(name: string, patterns: Pattern[]);
|
||||
apply(raw: string): string;
|
||||
}
|
||||
12
packages/discourse-legacy/dist/lib/markdown/Rule.js
vendored
Normal file
12
packages/discourse-legacy/dist/lib/markdown/Rule.js
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
export class Rule {
|
||||
name;
|
||||
patterns;
|
||||
constructor(name, patterns) {
|
||||
this.name = name;
|
||||
this.patterns = patterns;
|
||||
}
|
||||
apply(raw) {
|
||||
return this.patterns.reduce((result, pattern) => pattern.apply(result), raw);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=Rule.js.map
|
||||
1
packages/discourse-legacy/dist/lib/markdown/Rule.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/markdown/Rule.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"Rule.js","sourceRoot":"","sources":["../../../src/lib/markdown/Rule.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,IAAI;IACf,IAAI,CAAS;IACb,QAAQ,CAAY;IACpB,YAAY,IAAY,EAAE,QAAmB;QAC3C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,GAAW;QACf,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CACzB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAC1C,GAAG,CACJ,CAAC;IACJ,CAAC;CACF"}
|
||||
14
packages/discourse-legacy/dist/lib/markdown/index.d.ts
vendored
Normal file
14
packages/discourse-legacy/dist/lib/markdown/index.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import { Rule } from './Rule';
|
||||
import { RMarkOptions } from './types';
|
||||
export declare const RE_IMAGES: RegExp;
|
||||
export declare const RE_LINKS: RegExp;
|
||||
export declare class RMark {
|
||||
constructor(options: RMarkOptions);
|
||||
private rules;
|
||||
addRuleBefore(rule: Rule, before: string): RMark;
|
||||
addRule(rule: Rule): RMark;
|
||||
render(raw: string): string;
|
||||
}
|
||||
export { Rule } from './Rule';
|
||||
export { Pattern } from './Pattern';
|
||||
export declare const toHTML: (content: any) => any;
|
||||
98
packages/discourse-legacy/dist/lib/markdown/index.js
vendored
Normal file
98
packages/discourse-legacy/dist/lib/markdown/index.js
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
import { Rule } from './Rule';
|
||||
import { Pattern } from './Pattern';
|
||||
export const RE_IMAGES = /\!\[([^\]]+)\]\((\S+)\)/g;
|
||||
export const RE_LINKS = /\[([^\n]+)\]\(([^\n]+)\)/g;
|
||||
import * as markdown from 'markdown-it';
|
||||
const defaultRules = [
|
||||
new Rule('header', [
|
||||
new Pattern(/^#{6}\s?([^\n]+)/gm, '<h6>$1</h6>'),
|
||||
new Pattern(/^#{5}\s?([^\n]+)/gm, '<h5>$1</h5>'),
|
||||
new Pattern(/^#{4}\s?([^\n]+)/gm, '<h4>$1</h4>'),
|
||||
new Pattern(/^#{3}\s?([^\n]+)/gm, '<h3>$1</h3>'),
|
||||
new Pattern(/^#{2}\s?([^\n]+)/gm, '<h2>$1</h2>'),
|
||||
new Pattern(/^#{1}\s?([^\n]+)/gm, '<h1>$1</h1>'),
|
||||
]),
|
||||
new Rule('bold', [
|
||||
new Pattern(/\*\*\s?([^\n]+)\*\*/g, '<b>$1</b>'),
|
||||
new Pattern(/\_\_\s?([^\n]+)\_\_/g, '<b>$1</b>'),
|
||||
]),
|
||||
new Rule('italic', [
|
||||
new Pattern(/\*\s?([^\n]+)\*/g, '<i>$1</i>'),
|
||||
new Pattern(/\_\s?([^\n]+)\_/g, '<i>$1</i>'),
|
||||
]),
|
||||
new Rule('image', [
|
||||
new Pattern(/\!\[([^\]]+)\]\((\S+)\)/g, '<img src="$2" alt="$1" />'),
|
||||
]),
|
||||
new Rule('link', [
|
||||
new Pattern(/\[([^\n]+)\]\(([^\n]+)\)/g, '<a href2="$2" target="_blank" rel="noopener">$1</a>'),
|
||||
]),
|
||||
new Rule('paragraph', [
|
||||
// this regex can't skip processed HTML
|
||||
new Pattern(/([^\n]+\n?)/g, '\n<p>$1</p>\n'),
|
||||
// another possible regex that can't skip processed HTML
|
||||
// new Pattern(/(?:^|\n)([^\n\<]+(?:\n[^\n\>]+)*)(?:\n|$)/gm, '\n<p>$1</p>\n'),
|
||||
])
|
||||
];
|
||||
const defaultRulesDiscourse = (images, links) => {
|
||||
return [
|
||||
new Rule('image', [
|
||||
new Pattern(RE_LINKS, images)
|
||||
]) /*,
|
||||
new Rule('link', [
|
||||
new Pattern(
|
||||
RE_LINKS,
|
||||
links
|
||||
)
|
||||
])*/
|
||||
];
|
||||
};
|
||||
export class RMark {
|
||||
constructor(options) {
|
||||
this.rules = defaultRulesDiscourse(options.images, options.links);
|
||||
}
|
||||
rules;
|
||||
addRuleBefore(rule, before) {
|
||||
const index = this.rules.findIndex((r) => r.name === before);
|
||||
if (index !== -1) {
|
||||
this.rules.splice(index, 0, rule);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
addRule(rule) {
|
||||
this.addRuleBefore(rule, 'paragraph');
|
||||
return this;
|
||||
}
|
||||
render(raw) {
|
||||
let result = raw;
|
||||
this.rules.forEach((rule) => {
|
||||
result = rule.apply(result);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
export { Rule } from './Rule';
|
||||
export { Pattern } from './Pattern';
|
||||
// export const find = (content:string, reg:RegExp) => content.match(reg)
|
||||
export const toHTML = (content) => {
|
||||
const md = new markdown({
|
||||
html: true,
|
||||
breaks: true
|
||||
});
|
||||
return md.render(content);
|
||||
};
|
||||
function image_urls(input) {
|
||||
const regex = /https?:\/\/(?:[a-z0-9\-]+\.)+[a-z]{2,}(?:\/[^\/#\s]*)*\.(?:jpe?g|gif|png|webp)/g;
|
||||
const matches = input.match(regex);
|
||||
return matches || [];
|
||||
}
|
||||
function image_urls_local(input) {
|
||||
const regex = /\/(?:[^\/#\s]+\/)*[^\/#\s]+\.(?:jpe?g|gif|png|webp)/g;
|
||||
const matches = input.match(regex);
|
||||
return matches || [];
|
||||
}
|
||||
function findUploadImageUrls(input) {
|
||||
const regex = /upload:\/\/[^\s]+?\.(?:jpe?g|gif|png)/gi;
|
||||
const matches = input.match(regex);
|
||||
return matches || [];
|
||||
}
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
packages/discourse-legacy/dist/lib/markdown/index.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/markdown/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/markdown/index.ts"],"names":[],"mappings":"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"}
|
||||
1
packages/discourse-legacy/dist/lib/markdown/index.test.d.ts
vendored
Normal file
1
packages/discourse-legacy/dist/lib/markdown/index.test.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export {};
|
||||
112
packages/discourse-legacy/dist/lib/markdown/index.test.js
vendored
Normal file
112
packages/discourse-legacy/dist/lib/markdown/index.test.js
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
import { Pattern, RMark, Rule } from './index';
|
||||
const sampleText = `# Header 1
|
||||
## Header 2
|
||||
### Header 3
|
||||
#### Header 4
|
||||
##### Header 5
|
||||
###### Header 6
|
||||
|
||||
**Bold**
|
||||
*Italic*
|
||||
|
||||
[Link](https://github.com/tlylt/rmark)
|
||||

|
||||
|
||||
This is **Bold** and this is *Italic*.
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ornare erat facilisis odio viverra gravida. Phasellus in finibus libero. Duis eget pellentesque arcu, ut lobortis mi. Praesent vitae nulla sed leo dignissim finibus eget hendrerit arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vestibulum enim nibh, eu pellentesque tellus fermentum venenatis. Nam consectetur sem a magna mattis, sed luctus purus tincidunt. Nam faucibus tellus sed ligula molestie pulvinar. Mauris facilisis felis ex, eu tempor justo commodo et. Aenean lobortis dignissim diam eget tempor.
|
||||
|
||||
Sed pellentesque nulla sit amet tincidunt sagittis. Phasellus eget justo nulla. Cras nisi odio, lobortis nec ante eget, commodo euismod
|
||||
turpis. Cras id orci dolor. Etiam auctor, nisl luctus volutpat lacinia, turpis orci euismod magna, pharetra eleifend massa metus aliquet
|
||||
`;
|
||||
const sampleHtml = `
|
||||
<p><h1>Header 1</h1>
|
||||
</p>
|
||||
|
||||
<p><h2>Header 2</h2>
|
||||
</p>
|
||||
|
||||
<p><h3>Header 3</h3>
|
||||
</p>
|
||||
|
||||
<p><h4>Header 4</h4>
|
||||
</p>
|
||||
|
||||
<p><h5>Header 5</h5>
|
||||
</p>
|
||||
|
||||
<p><h6>Header 6</h6>
|
||||
</p>
|
||||
|
||||
|
||||
<p><b>Bold</b>
|
||||
</p>
|
||||
|
||||
<p><i>Italic</i>
|
||||
</p>
|
||||
|
||||
|
||||
<p><a href="https://github.com/tlylt/rmark" target="_blank" rel="noopener">Link</a>
|
||||
</p>
|
||||
|
||||
<p><img src="https://raw.githubusercontent.com/tlylt/rmark/main/static/logo.svg" alt="Image" />
|
||||
</p>
|
||||
|
||||
|
||||
<p>This is <b>Bold</b> and this is <i>Italic</i>.
|
||||
</p>
|
||||
|
||||
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ornare erat facilisis odio viverra gravida. Phasellus in finibus libero. Duis eget pellentesque arcu, ut lobortis mi. Praesent vitae nulla sed leo dignissim finibus eget hendrerit arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vestibulum enim nibh, eu pellentesque tellus fermentum venenatis. Nam consectetur sem a magna mattis, sed luctus purus tincidunt. Nam faucibus tellus sed ligula molestie pulvinar. Mauris facilisis felis ex, eu tempor justo commodo et. Aenean lobortis dignissim diam eget tempor.
|
||||
</p>
|
||||
|
||||
|
||||
<p>Sed pellentesque nulla sit amet tincidunt sagittis. Phasellus eget justo nulla. Cras nisi odio, lobortis nec ante eget, commodo euismod
|
||||
</p>
|
||||
|
||||
<p>turpis. Cras id orci dolor. Etiam auctor, nisl luctus volutpat lacinia, turpis orci euismod magna, pharetra eleifend massa metus aliquet
|
||||
</p>
|
||||
`;
|
||||
describe('testing index file', () => {
|
||||
test('empty string should render nothing', () => {
|
||||
expect(new RMark().render('')).toBe('');
|
||||
});
|
||||
test('should render paragraph', () => {
|
||||
expect(new RMark().render('Lorem ipsum dolor sit amet, consectetur adipiscing elit.')).toBe('\n<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>\n');
|
||||
});
|
||||
test('should render header', () => {
|
||||
expect(new RMark().render('# Header 1')).toBe('\n<p><h1>Header 1</h1></p>\n');
|
||||
expect(new RMark().render('## Header 2')).toBe('\n<p><h2>Header 2</h2></p>\n');
|
||||
expect(new RMark().render('### Header 3')).toBe('\n<p><h3>Header 3</h3></p>\n');
|
||||
expect(new RMark().render('#### Header 4')).toBe('\n<p><h4>Header 4</h4></p>\n');
|
||||
expect(new RMark().render('##### Header 5')).toBe('\n<p><h5>Header 5</h5></p>\n');
|
||||
expect(new RMark().render('###### Header 6')).toBe('\n<p><h6>Header 6</h6></p>\n');
|
||||
});
|
||||
test('should render bold', () => {
|
||||
expect(new RMark().render('**Bold**')).toBe('\n<p><b>Bold</b></p>\n');
|
||||
expect(new RMark().render('__Bold__')).toBe('\n<p><b>Bold</b></p>\n');
|
||||
expect(new RMark().render('This is **Bold**')).toBe('\n<p>This is <b>Bold</b></p>\n');
|
||||
});
|
||||
test('should render italic', () => {
|
||||
expect(new RMark().render('*Italic*')).toBe('\n<p><i>Italic</i></p>\n');
|
||||
expect(new RMark().render('_Italic_')).toBe('\n<p><i>Italic</i></p>\n');
|
||||
});
|
||||
test('should render image', () => {
|
||||
expect(new RMark().render('')).toBe('\n<p><img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" alt="Image" /></p>\n');
|
||||
});
|
||||
test('should render link', () => {
|
||||
expect(new RMark().render('[Link](https://github.com)')).toBe('\n<p><a href="https://github.com" target="_blank" rel="noopener">Link</a></p>\n');
|
||||
});
|
||||
test('should render paragraph with multiple lines', () => {
|
||||
expect(new RMark().render(sampleText)).toBe(sampleHtml);
|
||||
});
|
||||
test('should work with adding rules', () => {
|
||||
const rmark = new RMark();
|
||||
rmark.addRule(new Rule('horizontal', [
|
||||
new Pattern(/^(-{3})/gm, '<hr />'),
|
||||
new Pattern(/^(_{3})/gm, '<hr />'),
|
||||
]));
|
||||
expect(rmark.render('---')).toBe('\n<p><hr /></p>\n');
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=index.test.js.map
|
||||
1
packages/discourse-legacy/dist/lib/markdown/index.test.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/markdown/index.test.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/lib/markdown/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/C,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;CAmBlB,CAAC;AAEF,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+ClB,CAAC;AAEF,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,IAAI,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACnC,MAAM,CACJ,IAAI,KAAK,EAAE,CAAC,MAAM,CAChB,0DAA0D,CAC3D,CACF,CAAC,IAAI,CACJ,qEAAqE,CACtE,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAC3C,8BAA8B,CAC/B,CAAC;QACF,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAC5C,8BAA8B,CAC/B,CAAC;QACF,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAC7C,8BAA8B,CAC/B,CAAC;QACF,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAC9C,8BAA8B,CAC/B,CAAC;QACF,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAC/C,8BAA8B,CAC/B,CAAC;QACF,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAChD,8BAA8B,CAC/B,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACtE,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACtE,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CACjD,gCAAgC,CACjC,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACxE,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC/B,MAAM,CACJ,IAAI,KAAK,EAAE,CAAC,MAAM,CAChB,qFAAqF,CACtF,CACF,CAAC,IAAI,CACJ,gHAAgH,CACjH,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAC3D,iFAAiF,CAClF,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACzC,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;QAC1B,KAAK,CAAC,OAAO,CACX,IAAI,IAAI,CAAC,YAAY,EAAE;YACrB,IAAI,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC;YAClC,IAAI,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC;SACnC,CAAC,CACH,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
||||
1
packages/discourse-legacy/dist/lib/markdown/page.d.ts
vendored
Normal file
1
packages/discourse-legacy/dist/lib/markdown/page.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export {};
|
||||
26
packages/discourse-legacy/dist/lib/markdown/page.js
vendored
Normal file
26
packages/discourse-legacy/dist/lib/markdown/page.js
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
import { RMark } from '.';
|
||||
const sampleText = `# Header 1
|
||||
## Header 2
|
||||
### Header 3
|
||||
#### Header 4
|
||||
##### Header 5
|
||||
###### Header 6
|
||||
|
||||
**Bold**
|
||||
*Italic*
|
||||
|
||||
[Link](https://github.com/tlylt/rmark)
|
||||

|
||||
|
||||
This is **Bold** and this is *Italic*.
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ornare erat facilisis odio viverra gravida. Phasellus in finibus libero. Duis eget pellentesque arcu, ut lobortis mi. Praesent vitae nulla sed leo dignissim finibus eget hendrerit arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vestibulum enim nibh, eu pellentesque tellus fermentum venenatis. Nam consectetur sem a magna mattis, sed luctus purus tincidunt. Nam faucibus tellus sed ligula molestie pulvinar. Mauris facilisis felis ex, eu tempor justo commodo et. Aenean lobortis dignissim diam eget tempor.
|
||||
|
||||
Sed pellentesque nulla sit amet tincidunt sagittis. Phasellus eget justo nulla. Cras nisi odio, lobortis nec ante eget, commodo euismod
|
||||
turpis. Cras id orci dolor. Etiam auctor, nisl luctus volutpat lacinia, turpis orci euismod magna, pharetra eleifend massa metus aliquet
|
||||
`;
|
||||
const page = document.getElementById('page');
|
||||
if (page) {
|
||||
page.innerHTML = new RMark().render(sampleText);
|
||||
}
|
||||
//# sourceMappingURL=page.js.map
|
||||
1
packages/discourse-legacy/dist/lib/markdown/page.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/markdown/page.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../../src/lib/markdown/page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC;AAE1B,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;CAmBlB,CAAC;AAEF,MAAM,IAAI,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;AAE7C,IAAI,IAAI,EAAE;IACR,IAAI,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;CACjD"}
|
||||
5
packages/discourse-legacy/dist/lib/markdown/types.d.ts
vendored
Normal file
5
packages/discourse-legacy/dist/lib/markdown/types.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
export type RegExCallback = (match: any, capture: any, arg1: any, arg2: any) => string;
|
||||
export interface RMarkOptions {
|
||||
images: RegExCallback;
|
||||
links?: RegExCallback;
|
||||
}
|
||||
2
packages/discourse-legacy/dist/lib/markdown/types.js
vendored
Normal file
2
packages/discourse-legacy/dist/lib/markdown/types.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=types.js.map
|
||||
1
packages/discourse-legacy/dist/lib/markdown/types.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/markdown/types.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/markdown/types.ts"],"names":[],"mappings":""}
|
||||
27
packages/discourse-legacy/dist/lib/oa/commons.d.ts
vendored
Normal file
27
packages/discourse-legacy/dist/lib/oa/commons.d.ts
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
import { IUploadedFileMeta } from '@polymech/commons';
|
||||
import { IOACategory, IOATags, IOAHowtoImport } from '../../';
|
||||
export declare const DEFAULT_HT_CATEGORY: {
|
||||
_modified: string;
|
||||
label: string;
|
||||
_id: string;
|
||||
_created: string;
|
||||
_deleted: boolean;
|
||||
};
|
||||
export declare const LATEST_TRACK = "${OSR_ROOT}/oa-data/howtos/latest_track.json";
|
||||
export declare const LATEST_TEST = "./latest_test.json";
|
||||
export declare const DEFAULT_USER = "katharinaelleke";
|
||||
export declare const getDataPath: (_path?: string) => string;
|
||||
export declare const getHowtosPath: () => string;
|
||||
export declare const getHowtos: () => IOAHowtoImport[];
|
||||
export declare const read_howtos: (src: string) => IOAHowtoImport[];
|
||||
export declare const read_categories: (src: string) => IOACategory[];
|
||||
export declare const read_tags: (src: string) => IOATags[];
|
||||
export declare const filter_valid: (users: IOAHowtoImport[]) => IOAHowtoImport[];
|
||||
export declare const kb_howto_folder: (howto: any) => string;
|
||||
export declare const kb_howto_file: (howto: any, filename: any) => string;
|
||||
export declare const getHowtoUser: (howto: IOAHowto) => any;
|
||||
export declare const toMDImage: (image: IUploadedFileMeta) => string;
|
||||
export declare const md_edit_wrap: (content: any, f: any, prefix?: string, context?: string) => any;
|
||||
export declare const removeEmojis: (string: any) => any;
|
||||
export declare const toHTML: (path: any, markdown: any) => any;
|
||||
export declare const createTextLinks_: (text: any) => any;
|
||||
88
packages/discourse-legacy/dist/lib/oa/commons.js
vendored
Normal file
88
packages/discourse-legacy/dist/lib/oa/commons.js
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
import { sanitize } from './lib';
|
||||
import * as path from 'path';
|
||||
import { sync as read } from '@polymech/fs/read';
|
||||
import { resolve } from '@polymech/commons';
|
||||
import { getUsers } from './users';
|
||||
import { html_beautify } from 'js-beautify';
|
||||
import { Converter } from 'showdown';
|
||||
var escapeHtml = require('escape-html');
|
||||
const pretty = require('pretty');
|
||||
const TEST = false;
|
||||
export const DEFAULT_HT_CATEGORY = {
|
||||
"_modified": "2022-09-18T08:51:47.196Z",
|
||||
"label": "Guides",
|
||||
"_id": "CrZjHORWfxEl6iDrrPIO",
|
||||
"_created": "2022-09-18T08:51:47.196Z",
|
||||
"_deleted": false
|
||||
};
|
||||
export const LATEST_TRACK = '${OSR_ROOT}/oa-data/howtos/latest_track.json';
|
||||
export const LATEST_TEST = './latest_test.json';
|
||||
export const DEFAULT_USER = 'katharinaelleke';
|
||||
export const getDataPath = (_path = '') => path.resolve(path.join(resolve('${OSR_ROOT}/oa-data/howtos/'), _path));
|
||||
export const getHowtosPath = () => path.resolve(resolve(TEST ? LATEST_TEST : LATEST_TRACK));
|
||||
export const getHowtos = () => read(path.resolve(getHowtosPath()), 'json') || [];
|
||||
export const read_howtos = (src) => {
|
||||
const raw = read(src, 'json');
|
||||
return raw.v3_howtos;
|
||||
};
|
||||
export const read_categories = (src) => {
|
||||
const raw = read(src, 'json');
|
||||
return raw.v3_categories;
|
||||
};
|
||||
export const read_tags = (src) => {
|
||||
const raw = read(src, 'json');
|
||||
return raw.v3_tags;
|
||||
};
|
||||
export const filter_valid = (users) => {
|
||||
return users.filter((user) => {
|
||||
if (user.title === 'Build a Fishing Canoe') {
|
||||
//debugger
|
||||
}
|
||||
if (user.moderation.toLowerCase() !== 'accepted') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
export const kb_howto_folder = (howto) => path.resolve(path.join(resolve("${KB_ROOT}/src/howtos/"), howto.slug));
|
||||
export const kb_howto_file = (howto, filename) => path.resolve(path.join(resolve("${KB_ROOT}/src/howtos/"), howto.slug, sanitize(filename)));
|
||||
export const getHowtoUser = (howto) => {
|
||||
const users = getUsers();
|
||||
let user = users.find((u) => u._id == howto._createdBy);
|
||||
if (user && user.f_id) {
|
||||
return user;
|
||||
}
|
||||
else {
|
||||
user = users.find((u) => u._id == DEFAULT_USER);
|
||||
if (user && user.f_id) {
|
||||
console.error('using default user : ' + DEFAULT_USER + ' : for' + howto.slug);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
};
|
||||
export const toMDImage = (image) => ``;
|
||||
export const md_edit_wrap = (content, f, prefix = '', context = '') => html_beautify(`<div prefix="${prefix}" file="${path.parse(f).base}" context="${context}" class="fragment">${content}</div>`);
|
||||
export const removeEmojis = (string) => {
|
||||
return string.replace(/([#0-9]\u20E3)|[\xA9\xAE\u203C\u2047-\u2049\u2122\u2139\u3030\u303D\u3297\u3299][\uFE00-\uFEFF]?|[\u2190-\u21FF][\uFE00-\uFEFF]?|[\u2300-\u23FF][\uFE00-\uFEFF]?|[\u2460-\u24FF][\uFE00-\uFEFF]?|[\u25A0-\u25FF][\uFE00-\uFEFF]?|[\u2600-\u27BF][\uFE00-\uFEFF]?|[\u2900-\u297F][\uFE00-\uFEFF]?|[\u2B00-\u2BF0][\uFE00-\uFEFF]?|(?:\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDEFF])[\uFE00-\uFEFF]?/g, '');
|
||||
};
|
||||
export const toHTML = (path, markdown) => {
|
||||
const content = read(path, 'string');
|
||||
if (!markdown) {
|
||||
let converter = new Converter({ tables: true });
|
||||
converter.setOption('literalMidWordUnderscores', 'true');
|
||||
return converter.makeHtml(content);
|
||||
}
|
||||
else {
|
||||
return content;
|
||||
}
|
||||
};
|
||||
export const createTextLinks_ = (text) => {
|
||||
return (text || "").replace(/([^\S]|^)(((https?\:\/\/)|(www\.))(\S+))/gi, function (match, space, url) {
|
||||
var hyperlink = url;
|
||||
if (!hyperlink.match('^https?:\/\/')) {
|
||||
hyperlink = 'http://' + hyperlink;
|
||||
}
|
||||
return space + '<a href="' + hyperlink + '">' + url + '</a>';
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=commons.js.map
|
||||
1
packages/discourse-legacy/dist/lib/oa/commons.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/oa/commons.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"commons.js","sourceRoot":"","sources":["../../../src/lib/oa/commons.ts"],"names":[],"mappings":"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"}
|
||||
9
packages/discourse-legacy/dist/lib/oa/howtos.d.ts
vendored
Normal file
9
packages/discourse-legacy/dist/lib/oa/howtos.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
import { IOAHowtoImport } from '../../';
|
||||
export declare const mergeLatest: (discorse: any, options: IOptions, oa_howtos: IOAHowtoImport[]) => IOAHowtoImport[];
|
||||
export declare const read_fragments: (src: any, config: any, prefix?: string, context?: string) => any;
|
||||
export declare function howto_content(howto: IOAHowtoImport, folder: string, fragments: any, templates: any): Promise<any>;
|
||||
export declare const createHowtoTopic: (discourse: any, howto: IOAHowtoImport, create?: boolean) => Promise<boolean>;
|
||||
export declare const importHowto: (discorse: any, howto: IOAHowtoImport) => Promise<boolean>;
|
||||
export declare const importHowtos: (discorse: any, options: IOptions, howtos: IOAHowtoImport[]) => Promise<any>;
|
||||
export declare const updateHowto: (discourse: Discourser, howto: IOAHowtoImport, options: IOptions) => Promise<boolean>;
|
||||
export declare const updateHowtos: (discorse: any, options: IOptions, howtos: IOAHowtoImport[]) => Promise<any>;
|
||||
464
packages/discourse-legacy/dist/lib/oa/howtos.js
vendored
Normal file
464
packages/discourse-legacy/dist/lib/oa/howtos.js
vendored
Normal file
@ -0,0 +1,464 @@
|
||||
import { Promise as BPromise } from 'bluebird';
|
||||
import { forward_slash } from '@polymech/commons';
|
||||
import { resolveConfig } from '@polymech/core';
|
||||
import { substitute } from '@polymech/core/strings';
|
||||
import { logger } from '../../index';
|
||||
import { HT_CATS } from '../discourse/constants';
|
||||
import { sanitize } from './lib';
|
||||
import * as path from 'path';
|
||||
import { sync as read } from '@polymech/fs/read';
|
||||
import { sync as exists } from '@polymech/fs/exists';
|
||||
import { sync as write } from '@polymech/fs/write';
|
||||
import { resolve } from '@polymech/commons';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { get_user_name } from './users';
|
||||
var escapeHtml = require('escape-html');
|
||||
import { sync as mkdir } from '@polymech/fs/dir';
|
||||
import { files } from '@polymech/commons';
|
||||
const FUCKING_TOKEN = 'j7oYrkQe5nbnikCNHcfoP2DGtXKV4iHHzDFip8gGatS145g3B65UU6mI09KeFday9mY5HNQnU2jXUTe7LLkP-w';
|
||||
import { kb_howto_file, kb_howto_folder, getHowtos, getHowtosPath, getHowtoUser, md_edit_wrap, toHTML, toMDImage, createTextLinks_, removeEmojis, DEFAULT_HT_CATEGORY, read_tags } from './commons';
|
||||
export const mergeLatest = (discorse, options, oa_howtos) => {
|
||||
const howtos = getHowtos();
|
||||
oa_howtos.forEach((h) => {
|
||||
const howto = howtos.find((tu) => {
|
||||
return tu._id === h._id;
|
||||
});
|
||||
if (!howto) {
|
||||
howtos.push(h);
|
||||
}
|
||||
});
|
||||
write(getHowtosPath(), howtos);
|
||||
return howtos;
|
||||
};
|
||||
const updateHowtoFile = (howto) => {
|
||||
const howtos = getHowtos();
|
||||
const index = howtos.findIndex((u) => u._id == howto._id);
|
||||
howtos[index] = howto;
|
||||
write(getHowtosPath(), howtos);
|
||||
};
|
||||
const uploadImage = async (discourse, user, image, localPath) => {
|
||||
if (image.data) {
|
||||
return image;
|
||||
}
|
||||
logger.debug('uploading image:', image.name);
|
||||
const upped = await discourse.uploadFile(user.f_id, localPath);
|
||||
const data = upped.data;
|
||||
if (data && data.id) {
|
||||
image.data = data;
|
||||
}
|
||||
else {
|
||||
logger.error('error uploading image');
|
||||
}
|
||||
return image;
|
||||
};
|
||||
export const read_fragments = (src, config, prefix = '', context = '') => {
|
||||
if (!exists(src)) {
|
||||
mkdir(src);
|
||||
}
|
||||
let fragments = files(src, '*.html');
|
||||
fragments.map((f) => {
|
||||
config[path.parse(f).name] = md_edit_wrap(toHTML(f, true), f, prefix, context);
|
||||
});
|
||||
fragments = files(src, '*.md');
|
||||
fragments.map((f) => {
|
||||
config[path.parse(f).name] = md_edit_wrap(toHTML(f, false), f, prefix, context);
|
||||
});
|
||||
return config;
|
||||
};
|
||||
export async function howto_content(howto, folder, fragments, templates) {
|
||||
//const tags = data.v3_tags;
|
||||
const howtoTags = [];
|
||||
/*
|
||||
for (const ht in howto.tags) {
|
||||
const gt = tags.find((t) => t._id === ht);
|
||||
if (gt) {
|
||||
howtoTags.push(gt.label);
|
||||
// logger.debug('resolved ' + ht + ' to ' + gt.label);
|
||||
} else {
|
||||
// logger.error('Cant resolve tag : ' + ht);
|
||||
}
|
||||
}
|
||||
*/
|
||||
howto.slug = howto.slug.trim();
|
||||
let s = '';
|
||||
let step_template = "" + templates.step;
|
||||
let invalid_step_images = false;
|
||||
const step_image = (i) => {
|
||||
if (!i.data || !i.data.short_url) {
|
||||
logger.error('invalid image : ' + i.downloadUrl + ' : ' + howto.slug);
|
||||
invalid_step_images = true;
|
||||
return '\n';
|
||||
}
|
||||
return `\n${toMDImage(i)}`;
|
||||
};
|
||||
const step_file = (i) => {
|
||||
const image = `/howtos/${howto.slug}/${encodeURIComponent(sanitize(i.name))}`;
|
||||
return `<div class="col-sm">
|
||||
<a href="${image}">
|
||||
<p>${i.name}"<p/>
|
||||
</a>
|
||||
</div>`;
|
||||
};
|
||||
const step_files = (s) => {
|
||||
const files = s.files.map(step_file).join('\n');
|
||||
return `<div class="row">
|
||||
${files}
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
const step_images = (s) => {
|
||||
const images = s.images.map(step_image).join('\n');
|
||||
return `${images}`;
|
||||
};
|
||||
const step_images_gallery = (s) => {
|
||||
const images = s.images.map(step_image).join('');
|
||||
return `<div data-theme-tiles="1">\n${images}</div>`;
|
||||
};
|
||||
const step = (s, i) => {
|
||||
const t = substitute(step_template, {
|
||||
title: s.title,
|
||||
text: createTextLinks_(escapeHtml(s.text.trim()).replace(/(?:\r\n|\r|\n)/g, '\n\n')),
|
||||
step_number: i + 1,
|
||||
images: s.images.length > 1 ? step_images_gallery(s) : step_images(s)
|
||||
});
|
||||
return t;
|
||||
};
|
||||
const steps = howto.steps.map((s, i) => step(s, i)).join('\n\n');
|
||||
const attachments = howto.files.map((f) => {
|
||||
return `[${sanitize(f.name)}](${f.downloadUrl})`;
|
||||
});
|
||||
howto.description = removeEmojis(howto.description);
|
||||
howto.description = createTextLinks_(howto.description);
|
||||
let authorName = (howto.user && howto.user.data && howto.user.data && howto.user.data.title) ? howto.user.data.title : (howto.user ? howto.user._id : 'OSR-Plastic');
|
||||
if (authorName === 'Precious Plastic Headquarters') {
|
||||
authorName = 'Precious Plastic Nantes';
|
||||
}
|
||||
let _3dFiles = [...files(path.resolve(`${folder}`), '**/**/*.step'), ...files(path.resolve(`${folder}`), '**/**/*.STEP'), ...files(path.resolve(`${folder}`), '**/**/*.stp')];
|
||||
_3dFiles = _3dFiles.map((f) => {
|
||||
return forward_slash(`${howto.slug}/${path.relative(path.resolve(folder), f)}`);
|
||||
});
|
||||
let previews = '';
|
||||
if (_3dFiles.length) {
|
||||
previews += '<div class="container">';
|
||||
previews += '<div class="row"><div class="col-12"><ul class="list-group">';
|
||||
_3dFiles = _3dFiles.map((f) => {
|
||||
return `
|
||||
<li class="list-group-item">
|
||||
<span>3D Step File: ${f.replace(howto.slug, '')} -
|
||||
<a href="" class="iframe-lightbox-link" data-src="/howtos/${encodeURIComponent(f).replace('.STEP', '.html').
|
||||
replace('.step', '.html').replace('.stp', '.html')}">
|
||||
Preview</a>
|
||||
</span>
|
||||
</li>`;
|
||||
});
|
||||
previews += _3dFiles.join('');
|
||||
previews += '</ul></div></div></div>';
|
||||
}
|
||||
if (invalid_step_images) {
|
||||
return false;
|
||||
}
|
||||
let index = substitute(templates.howto, {
|
||||
...fragments,
|
||||
image: `/howtos/${howto.slug}/${encodeURIComponent(sanitize(howto.cover_image.name))}`,
|
||||
title: howto.title.trim(),
|
||||
description: escapeHtml(howto.description.trim()) || "",
|
||||
enabled: howto.moderation == "accepted" ? true : false,
|
||||
steps: steps,
|
||||
keywords: ['Precious plastic', 'Preciousplastic', 'plastichub', 'osr', ...howtoTags].join(','),
|
||||
user: howto._createdBy,
|
||||
files: `${attachments.join('\n')}`,
|
||||
authorName: authorName,
|
||||
authorUrl: `https://osr-plastic.org/users/${howto.user ? howto.user._id : 'https://osr-plastic.org/users/plastichub'}.html`,
|
||||
// short: escapeHtml(howto.description.trim()).substring(0, 100) + '....',
|
||||
slug: howto.slug,
|
||||
previews3D: previews
|
||||
});
|
||||
const $ = cheerio.load(index, {
|
||||
xmlMode: true
|
||||
});
|
||||
/*
|
||||
$('a').each(function () {
|
||||
const url = $(this).attr("href");
|
||||
logger.debug('url : ' + url);
|
||||
if(url.indexOf('dropbox')){
|
||||
|
||||
}
|
||||
});*/
|
||||
//write(index_md, pretty(index, { ocd: true }));
|
||||
return removeEmojis(index);
|
||||
}
|
||||
export const createHowtoTopic = async (discourse, howto, create = true) => {
|
||||
if (!howto.category || !howto.category.label) {
|
||||
howto.category = DEFAULT_HT_CATEGORY;
|
||||
logger.error(`create howto : invalid category: ${howto.category} : ${howto.slug}`);
|
||||
}
|
||||
const user = getHowtoUser(howto);
|
||||
if (!user) {
|
||||
logger.error(`create howto : invalid user : ${howto._createdBy} :: ${howto.title}`);
|
||||
}
|
||||
const howto_folder = kb_howto_folder(howto);
|
||||
const howto_cover_image = kb_howto_file(howto, howto.cover_image.name);
|
||||
if (!exists(howto_folder)) {
|
||||
logger.error('howto folder doesnt exists', howto.title);
|
||||
}
|
||||
if (!exists(howto_cover_image)) {
|
||||
logger.error('howto cover image doesnt exists', howto.title);
|
||||
}
|
||||
if (!user || !user.f_id) {
|
||||
logger.error(`create howto : invalid user : ${howto._createdBy} :: ${howto.title}`);
|
||||
return false;
|
||||
}
|
||||
howto.cover_image = await uploadImage(discourse, user, howto.cover_image, howto_cover_image);
|
||||
updateHowtoFile(howto);
|
||||
let invalid_images = false;
|
||||
for (const step of howto.steps) {
|
||||
let i = 0;
|
||||
for await (const image of step.images) {
|
||||
const image_name = sanitize(image.name);
|
||||
const imagePath = path.resolve(path.join(howto_folder, sanitize(image_name)));
|
||||
if (!exists(imagePath)) {
|
||||
logger.error('step image doesnt exists : ' + image.name + ' in ' + howto.slug);
|
||||
invalid_images = true;
|
||||
continue;
|
||||
}
|
||||
step.images[i] = await uploadImage(discourse, user, step.images[i], imagePath);
|
||||
updateHowtoFile(howto);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (invalid_images) {
|
||||
logger.error('invalid images : ' + howto.slug);
|
||||
return false;
|
||||
}
|
||||
const cat = HT_CATS[howto.category.label];
|
||||
if (!cat) {
|
||||
logger.error('invalid kat');
|
||||
return false;
|
||||
}
|
||||
const templatesRoot = path.resolve(resolve("${OSR_ROOT}/osr-templates/discourse"));
|
||||
const cPath = path.resolve(`${templatesRoot}/base.json`);
|
||||
logger.debug(`read config at ${cPath}`);
|
||||
const config = read(cPath, 'json');
|
||||
const templates = path.resolve(`${templatesRoot}/howto`);
|
||||
if (!exists(templates)) {
|
||||
logger.error(`\t Cant find templates at ${templates}, path doesn't exists`);
|
||||
return;
|
||||
}
|
||||
let fragments = { ...config.variables };
|
||||
read_fragments(templates, fragments, "product_rel_path_name", "machine");
|
||||
let template = read(path.resolve(`${templates}/howto.md`), 'string');
|
||||
let step = read(path.resolve(`${templates}/step.md`), 'string');
|
||||
resolveConfig(fragments);
|
||||
const content = await howto_content(howto, howto_folder, fragments, {
|
||||
howto: template,
|
||||
step: '' + step
|
||||
});
|
||||
if (!content) {
|
||||
logger.error('invalid content : ' + howto.slug);
|
||||
return;
|
||||
}
|
||||
let data;
|
||||
if (create) {
|
||||
data = await discourse.createPost(sanitize(howto.title), content, cat);
|
||||
if (data) {
|
||||
logger.debug('created topic : ' + howto.title + ' : ' + data.id);
|
||||
if (data && data.id) {
|
||||
howto.post_id = data.id;
|
||||
howto.topic_id = data.topic_id;
|
||||
updateHowtoFile(howto);
|
||||
try {
|
||||
logger.debug('change user to ', user._id);
|
||||
await discourse.changeOwner(howto.post_id, howto.topic_id, get_user_name(user));
|
||||
}
|
||||
catch (e) {
|
||||
logger.debug('changing owner ' + howto.title + ' failed!');
|
||||
howto.oF = true;
|
||||
updateHowtoFile(howto);
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.debug('creating ' + howto.title + ' failed!', data.errors);
|
||||
howto.post_id = 'failed';
|
||||
if (data.errors) {
|
||||
if (data.errors[0] && data.errors[0] === 'Title has already been used') {
|
||||
logger.error('title already used : ' + howto.slug);
|
||||
howto.post_id = 'already';
|
||||
}
|
||||
}
|
||||
updateHowtoFile(howto);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
data = await discourse.updatePost(howto.post_id, content);
|
||||
howto._updatedContent1 = true;
|
||||
updateHowtoFile(howto);
|
||||
}
|
||||
};
|
||||
export const importHowto = async (discorse, howto) => {
|
||||
//const howtos = getHowtos()
|
||||
//const index = howtos.findIndex((u) => u._id == howto._id)
|
||||
const ret = await createHowtoTopic(discorse, howto);
|
||||
return ret;
|
||||
};
|
||||
export const importHowtos = async (discorse, options, howtos) => {
|
||||
logger.debug('read howtos from ', path.resolve(getHowtosPath()));
|
||||
howtos = mergeLatest(discorse, options, howtos);
|
||||
howtos = howtos.filter((h) => {
|
||||
if (h.title === 'Build a Fishing Canoe') {
|
||||
//debugger
|
||||
}
|
||||
if (h.post_id || h.post_id < 0) {
|
||||
return false;
|
||||
}
|
||||
if (h.post_id === 'failed') {
|
||||
logger.debug('skip failed : ' + h.slug);
|
||||
return false;
|
||||
}
|
||||
//if (u.alreadyExists || u.invalidData) {
|
||||
// return false;
|
||||
//}
|
||||
return true;
|
||||
});
|
||||
return await BPromise.resolve(howtos).map((h) => {
|
||||
try {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
const d = importHowto(discorse, h);
|
||||
if (d) {
|
||||
d.then(resolve);
|
||||
}
|
||||
else {
|
||||
reject();
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
debugger;
|
||||
logger.error('error creating howto ' + h._id, e);
|
||||
}
|
||||
}, { concurrency: 1 });
|
||||
};
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Update Howtos
|
||||
//
|
||||
let _discorseTags;
|
||||
const getDiscourseTags = async (discourse) => {
|
||||
if (!_discorseTags) {
|
||||
_discorseTags = await discourse.getTags();
|
||||
}
|
||||
return _discorseTags;
|
||||
};
|
||||
export const updateHowto = async (discourse, howto, options) => {
|
||||
const tags = read_tags(options.src);
|
||||
let howtoTags = [];
|
||||
for (const ht in howto.tags) {
|
||||
const t = ht;
|
||||
const gt = tags.find((t) => {
|
||||
return t._id === ht;
|
||||
});
|
||||
if (gt) {
|
||||
howtoTags.push(gt.label);
|
||||
}
|
||||
else {
|
||||
// logger.error('Cant resolve tag : ' + ht);
|
||||
}
|
||||
}
|
||||
howtoTags.push('oa-import');
|
||||
let discorseTags = await getDiscourseTags(discourse);
|
||||
const cat = HT_CATS[howto.category.label];
|
||||
if (howtoTags && howtoTags.length) {
|
||||
try {
|
||||
const ret = await discourse.updateTopic(howto.topic_id, cat, sanitize(howto.title), howtoTags);
|
||||
logger.debug('Updating howto tags : ' + howto.title);
|
||||
}
|
||||
catch (error) {
|
||||
logger.error('Error updating post' + howto.title, howto.topic_id, cat, howtoTags, error);
|
||||
howto['updateFailed1'] = 1;
|
||||
updateHowtoFile(howto);
|
||||
//debugger
|
||||
}
|
||||
}
|
||||
howto.updatedTags = true;
|
||||
updateHowtoFile(howto);
|
||||
const _date = howto._modified || howto._created;
|
||||
if (_date) {
|
||||
let date = new Date(_date);
|
||||
logger.debug('update ts ' + howto.slug + ' : ' + new Date(date).toLocaleDateString());
|
||||
let offset = 0;
|
||||
const valueOf = date.valueOf() - (offset) * 60000;
|
||||
let ts = Math.floor(valueOf / 1000);
|
||||
const tUpdate = await discourse.updateTopicTimestamp(howto.topic_id, ts, FUCKING_TOKEN);
|
||||
if (tUpdate) {
|
||||
howto.updatedTime8 = true;
|
||||
updateHowtoFile(howto);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.error('Have no ts : ' + howto.slug);
|
||||
}
|
||||
};
|
||||
export const updateHowtos = async (discorse, options, howtos) => {
|
||||
logger.debug('update howtos from ', path.resolve(getHowtosPath()));
|
||||
howtos = mergeLatest(discorse, options, howtos);
|
||||
const forceUpdateContent = true;
|
||||
const forceUpdateMeta = true;
|
||||
const updateContent = true;
|
||||
const updateMeta = true;
|
||||
howtos = howtos.filter((h) => {
|
||||
if (!h.post_id || !h.topic_id) {
|
||||
return false;
|
||||
}
|
||||
if (h.post_id === 'failed') {
|
||||
logger.debug('skip failed : ' + h.slug);
|
||||
return false;
|
||||
}
|
||||
if (forceUpdateContent || forceUpdateMeta) {
|
||||
return true;
|
||||
}
|
||||
if (!h._updatedContent1) {
|
||||
return true;
|
||||
}
|
||||
if (h.updatedTags && h.updatedTime8) {
|
||||
return false;
|
||||
}
|
||||
if (!h.updatedTags || !h.updatedTime8) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return await BPromise.resolve(howtos).map((h) => {
|
||||
try {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
if (updateContent) {
|
||||
logger.debug('\t recook howto content', h.title);
|
||||
let d = createHowtoTopic(discorse, h, false);
|
||||
d.then(() => {
|
||||
if (updateMeta) {
|
||||
d = updateHowto(discorse, h, options);
|
||||
if (d) {
|
||||
d.then(resolve);
|
||||
}
|
||||
else {
|
||||
reject();
|
||||
}
|
||||
}
|
||||
else {
|
||||
resolve(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
debugger;
|
||||
logger.error('error creating howto ' + h._id, e);
|
||||
}
|
||||
}, { concurrency: 1 });
|
||||
};
|
||||
//# sourceMappingURL=howtos.js.map
|
||||
1
packages/discourse-legacy/dist/lib/oa/howtos.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/oa/howtos.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
3
packages/discourse-legacy/dist/lib/oa/index.d.ts
vendored
Normal file
3
packages/discourse-legacy/dist/lib/oa/index.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './lib';
|
||||
export * from './users';
|
||||
export * from './types';
|
||||
4
packages/discourse-legacy/dist/lib/oa/index.js
vendored
Normal file
4
packages/discourse-legacy/dist/lib/oa/index.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './lib';
|
||||
export * from './users';
|
||||
export * from './types';
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
packages/discourse-legacy/dist/lib/oa/index.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/oa/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/oa/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
|
||||
3
packages/discourse-legacy/dist/lib/oa/lib.d.ts
vendored
Normal file
3
packages/discourse-legacy/dist/lib/oa/lib.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
export declare const sanitize: (f: any) => string;
|
||||
export declare const getImageName: (url: any) => string;
|
||||
export declare const convert: (input: string) => any;
|
||||
191
packages/discourse-legacy/dist/lib/oa/lib.js
vendored
Normal file
191
packages/discourse-legacy/dist/lib/oa/lib.js
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
const _sanitize = require("sanitize-filename");
|
||||
const URI = require("uri-js");
|
||||
import * as path from 'path';
|
||||
const filenamify = require('filenamify');
|
||||
var TurndownService = require('turndown');
|
||||
export const sanitize = (f) => {
|
||||
let str = filenamify(_sanitize(f)).replace(/[^\x00-\x7F]/g, "");
|
||||
if (str.startsWith('_')) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
return str;
|
||||
};
|
||||
export const getImageName = (url) => {
|
||||
const parsed = URI.parse(decodeURIComponent(url));
|
||||
const pParsed = path.parse(parsed.path);
|
||||
const fileName = sanitize(decodeURIComponent(pParsed.base));
|
||||
return fileName;
|
||||
};
|
||||
export const convert = (input) => {
|
||||
var turndownService = new TurndownService();
|
||||
return turndownService.turndown(input);
|
||||
};
|
||||
/*
|
||||
|
||||
|
||||
const getFUser = (users, user_name) => {
|
||||
return users.find((u) => {
|
||||
return u.name == user_name
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const indexUsers = async (d, forum: string, detail) => {
|
||||
|
||||
const forumUsers = await getForumUsers(d, detail)
|
||||
const raw = (read(path.resolve(forum + '/index.json'), 'json') as any)
|
||||
const users_raw = raw.users
|
||||
let users = []
|
||||
for (let u in users_raw) {
|
||||
const user = users_raw[u];
|
||||
const avatar = getOAvatar(raw, u);
|
||||
let aFileName = '';
|
||||
let fUser = getFUser(forumUsers, u);
|
||||
if (avatar) {
|
||||
const parsed = URI.parse(avatar);
|
||||
const pParsed = path.parse(parsed.path);
|
||||
aFileName = pParsed.base;
|
||||
}
|
||||
users.push({
|
||||
name: u,
|
||||
avatar: avatar,
|
||||
avatarFileName: aFileName,
|
||||
user_id: fUser ? fUser.id : -1
|
||||
});
|
||||
}
|
||||
write(path.resolve(forum + '/user.json'), users);
|
||||
}
|
||||
|
||||
const _createUser = async (discorse, forum, name, email) => {
|
||||
|
||||
const users = getUsers()
|
||||
const index = users.findIndex((u) => u.detail.name == name)
|
||||
let user = await createUser(discorse, null)
|
||||
|
||||
|
||||
if (user && users[index].upload_id) {
|
||||
await discorse.setUserAvatar(name, users[index].upload_id);
|
||||
//return users;
|
||||
}
|
||||
|
||||
if (user > 0 && index) {
|
||||
users[index].f_id = user;
|
||||
console.log('created ' + name + ' ' + user);
|
||||
write(getUsersPath(), users);
|
||||
} else {
|
||||
console.error('cant create user - error', name, user)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const _updateGroup = async (discorse, forum, name, id, forumUsers) => {
|
||||
const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
|
||||
const index = users.findIndex((u) => u.name == name);
|
||||
try {
|
||||
const d = await discorse.updateGroup(name, pUserGroup);
|
||||
console.log('updated user group for ' + name);
|
||||
users[index].g_id = pUserGroup;
|
||||
write(path.resolve(forum + '/user.json'), users);
|
||||
if (users[index].upload_id) {
|
||||
//await discorse.setUserAvatar(name, users[index].upload_id);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.data && e.data.status == 422) {
|
||||
users[index].g_id = pUserGroup;
|
||||
write(path.resolve(forum + '/user.json'), users);
|
||||
console.log('updated user group for ' + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const _updateAvatar = async (discorse, forum, name) => {
|
||||
const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
|
||||
const index = users.findIndex((u) => u.name == name);
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
setTimeout(() => {
|
||||
discorse.setUserAvatar(name, users[index].upload_id).then(() => {
|
||||
console.log('updated avatar for ' + name);
|
||||
users[index].avatarSet = true;
|
||||
write(path.resolve(forum + '/user.json'), users);
|
||||
resolve(1);
|
||||
});
|
||||
}, 200);
|
||||
} catch (e) {
|
||||
console.error('-error setting avatar', e);
|
||||
debugger;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const createUsers = async (d, forum) => {
|
||||
|
||||
const forumUsers = await getForumUsers(d, true)
|
||||
const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
|
||||
const toBeCreated = users.filter((u) => {
|
||||
if (u.f_id || u.f_id < 0) {
|
||||
return false;
|
||||
}
|
||||
if (u.name === 'plastichub' || u.name === 'lu' || u.name === 'timberstar' || u.name === 'nickname') {
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
console.log('Create Users ' + users.length + ' Total | Left: ' + toBeCreated.length);
|
||||
|
||||
return await BPromise.resolve(toBeCreated).map((u: any) => {
|
||||
const t = _createUser(d, forum, u.name, u.email);
|
||||
return t;
|
||||
}, { concurrency: 1 })
|
||||
|
||||
}
|
||||
|
||||
const updateUserGroups = async (forum) => {
|
||||
const forumUsers = (read(path.resolve(forum + '/fusers.json'), 'json') as any);
|
||||
const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
|
||||
const toBeUpdated = users.filter((u) => {
|
||||
if (u.g_id) {
|
||||
return false;
|
||||
}
|
||||
if (u.name === 'plastichub' || u.name === 'lu' || u.name === 'timberstar' || u.name === 'nickname') {
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
});
|
||||
const d = getDiscourse();
|
||||
console.log('Update Users ' + users.length + ' Total | Left: ' + toBeUpdated.length);
|
||||
return await BPromise.resolve(toBeUpdated).map((u: any) => {
|
||||
const t = _updateGroup(d, forum, u.name, u.f_id, forumUsers);
|
||||
return t;
|
||||
}, { concurrency: 1 })
|
||||
|
||||
}
|
||||
|
||||
const updateUserAvatars = async (forum) => {
|
||||
const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
|
||||
const toBeUpdated = users.filter((u) => {
|
||||
if (!u.upload_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (u.avatarSet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (u.name === 'plastichub' || u.name === 'lu' || u.name === 'timberstar' || u.name === 'nickname') {
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
});
|
||||
const d = getDiscourse();
|
||||
console.log('Update User Avatar ' + users.length + ' Total | Left: ' + toBeUpdated.length);
|
||||
return await BPromise.resolve(toBeUpdated).map((u: any) => {
|
||||
const t = _updateAvatar(d, forum, u.name);
|
||||
return t;
|
||||
}, { concurrency: 1 })
|
||||
|
||||
}
|
||||
*/
|
||||
//# sourceMappingURL=lib.js.map
|
||||
1
packages/discourse-legacy/dist/lib/oa/lib.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/oa/lib.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../../../src/lib/oa/lib.ts"],"names":[],"mappings":"AAAA,MAAM,SAAS,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;AAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;AAC7B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;AACxC,IAAI,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,EAAE;IAC1B,IAAI,GAAG,GAAW,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IACxE,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QACrB,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;KACzB;IACD,OAAO,GAAG,CAAA;AACd,CAAC,CAAA;AAGD,MAAM,CAAC,MAAM,YAAY,GAAI,CAAC,GAAG,EAAE,EAAE;IACjC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;IAC3D,OAAO,QAAQ,CAAA;AACnB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,EAAE;IACxC,IAAI,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA;IAC3C,OAAO,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuKE"}
|
||||
91
packages/discourse-legacy/dist/lib/oa/types.d.ts
vendored
Normal file
91
packages/discourse-legacy/dist/lib/oa/types.d.ts
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
import { IUploadedFileMeta, I_OSR_USER } from '@polymech/commons';
|
||||
export interface IOACategory {
|
||||
_created: string;
|
||||
_id: string;
|
||||
_deleted: boolean;
|
||||
label: string;
|
||||
_modified: string;
|
||||
}
|
||||
export interface IOATag {
|
||||
categories: string[];
|
||||
image: string;
|
||||
_created: string;
|
||||
_deleted: boolean;
|
||||
label: string;
|
||||
_createdBy: string;
|
||||
_modified: string;
|
||||
_id: string;
|
||||
}
|
||||
export type IOADifficultyLevel = 'Easy' | 'Medium' | 'Hard' | 'Very Hard';
|
||||
export interface IDImage {
|
||||
id: number;
|
||||
url: string;
|
||||
original_filename: string;
|
||||
filesize: number;
|
||||
width: number;
|
||||
height: number;
|
||||
thumbnail_width: number;
|
||||
thumbnail_height: number;
|
||||
extension: string;
|
||||
short_url: string;
|
||||
short_path: string;
|
||||
retain_hours: any;
|
||||
human_filesize: string;
|
||||
}
|
||||
export interface IOAHowto {
|
||||
moderation: string;
|
||||
category: IOACategory;
|
||||
previousSlugs: string[];
|
||||
total_downloads: number;
|
||||
_createdBy: string;
|
||||
slug: string;
|
||||
cover_image: IUploadedFileMeta;
|
||||
_modified: string;
|
||||
files: any[];
|
||||
description: string;
|
||||
mentions: any[];
|
||||
time: string;
|
||||
_created: string;
|
||||
fileLink: string;
|
||||
steps: IOAStep[];
|
||||
creatorCountry: string;
|
||||
title: string;
|
||||
tags: IOATags;
|
||||
_id: string;
|
||||
_deleted: boolean;
|
||||
total_views: number;
|
||||
difficulty_level: IOADifficultyLevel;
|
||||
comments: any[];
|
||||
user: IImportUser;
|
||||
pics?: string[];
|
||||
}
|
||||
export interface IOAStep {
|
||||
_animationKey: string;
|
||||
images: IUploadedFileMeta[];
|
||||
text: string;
|
||||
title: string;
|
||||
}
|
||||
export interface IOATags {
|
||||
[key: string]: boolean;
|
||||
}
|
||||
export type IOAHowtoImport = IOAHowto & {
|
||||
post_id?: number | string;
|
||||
topic_id?: number;
|
||||
oF?: boolean;
|
||||
updatedTags?: boolean;
|
||||
updatedTime8?: boolean;
|
||||
_updatedContent1?: boolean;
|
||||
};
|
||||
export interface IImportUser extends I_OSR_USER {
|
||||
f_id: number;
|
||||
upload_id: number;
|
||||
avatar: string;
|
||||
_didSetAvatar: boolean;
|
||||
_didSetGroup: boolean;
|
||||
alreadyExists: boolean;
|
||||
invalidData: boolean;
|
||||
didUpdateName: boolean;
|
||||
profileHeader?: IDImage;
|
||||
cardBackground?: IDImage;
|
||||
avatarImage?: IDImage;
|
||||
}
|
||||
2
packages/discourse-legacy/dist/lib/oa/types.js
vendored
Normal file
2
packages/discourse-legacy/dist/lib/oa/types.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=types.js.map
|
||||
1
packages/discourse-legacy/dist/lib/oa/types.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/oa/types.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/oa/types.ts"],"names":[],"mappings":""}
|
||||
29
packages/discourse-legacy/dist/lib/oa/users.d.ts
vendored
Normal file
29
packages/discourse-legacy/dist/lib/oa/users.d.ts
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
import { I_OSR_USER } from '@polymech/commons';
|
||||
import { IImportUser, IDiscourseUser } from '../../';
|
||||
export declare const read_users: (src: string) => I_OSR_USER[];
|
||||
export declare const filter_valid: (users: IImportUser[]) => IImportUser[];
|
||||
export declare const filter_email_only: (users: any[]) => any[];
|
||||
export declare const filter_invalid: (users: any[]) => any[];
|
||||
export declare const filter_email_missing: (users: any[]) => any[];
|
||||
export declare const filter_accepted: (users: IImportUser[]) => IImportUser[];
|
||||
export declare const oa_user_email: (user: I_OSR_USER) => string | false;
|
||||
export declare const get_user_name: (user: IImportUser) => any;
|
||||
export declare const get_user_display_name: (user: IImportUser) => any;
|
||||
export declare const getDataPath: (_path?: string) => string;
|
||||
export declare const getUsersPath: () => string;
|
||||
export declare const getUsers: () => IImportUser[];
|
||||
export declare const _getForumUsers: (d: Discourser, page: any, detail: any) => any;
|
||||
export declare const getForumUsers: (d: any, detail: any) => Promise<IDiscourseUser[]>;
|
||||
export declare const createUser: (discourse: Discourser, oa_user: IImportUser) => Promise<any>;
|
||||
export declare const uploadAvatar: (discourse: any, name: any, filePath: any) => Promise<IImportUser[]>;
|
||||
export declare const updateUser: (discorse: Discourser, oa_user: IImportUser) => Promise<void>;
|
||||
export declare const importUser: (discorse: Discourser, oa_user: IImportUser) => Promise<any>;
|
||||
export declare const mergeLatestUsers: (discorse: any, options: IOptions, oa_users: I_OSR_USER[]) => IImportUser[];
|
||||
export declare const mergeLatestUsersTest: (discorse: any, options: IOptions, oa_users: I_OSR_USER[]) => IImportUser[];
|
||||
export declare const importUsers: (discorse: any, options: IOptions, oa_users: I_OSR_USER[]) => Promise<any>;
|
||||
export declare const updateUsers: (discorse: any, options: IOptions, oa_users: I_OSR_USER[]) => Promise<any>;
|
||||
export declare const md_edit_wrap: (content: any, f: any, prefix?: string, context?: string) => any;
|
||||
export declare const toHTML: (path: any, markdown: any) => any;
|
||||
export declare const imageName: (url: any) => any;
|
||||
export declare const read_fragments: (src: any, config: any, prefix?: string, context?: string) => any;
|
||||
export declare const indexUsers: (discorse: any, options: IOptions, oa_users: I_OSR_USER[]) => Promise<void>;
|
||||
906
packages/discourse-legacy/dist/lib/oa/users.js
vendored
Normal file
906
packages/discourse-legacy/dist/lib/oa/users.js
vendored
Normal file
@ -0,0 +1,906 @@
|
||||
import { Promise as BPromise } from 'bluebird';
|
||||
import { getImageName, sanitize } from './lib';
|
||||
import { capitalize, replaceAll } from '@polymech/core/utils';
|
||||
import * as path from 'path';
|
||||
import { sync as read } from '@polymech/fs/read';
|
||||
import { sync as exists } from '@polymech/fs/exists';
|
||||
import { sync as write } from '@polymech/fs/write';
|
||||
import { resolve } from '@polymech/commons';
|
||||
import { logger } from '../../index';
|
||||
const slugify = require('slugify');
|
||||
import { substitute } from '@polymech/core';
|
||||
import { html_beautify } from 'js-beautify';
|
||||
import { sync as mkdir } from '@polymech/fs/dir';
|
||||
import { files } from '@polymech/commons';
|
||||
import { Converter } from 'showdown';
|
||||
const URI = require("uri-js");
|
||||
import { OA_USER_IMPORT_GROUP, LATEST_TEST, LATEST_TRACK, FETCH_DUSERS, F_USERS_ALL, F_USERS_NOW, DEFAULT_PASSWORD, DATA_PATH, OA_DIRECTORY_OVERVIEW_TOPIC } from '../discourse/constants';
|
||||
const filenamify = require('filenamify');
|
||||
const fg = require('fast-glob');
|
||||
const TEST = false;
|
||||
export const read_users = (src) => {
|
||||
const raw = read(src, 'json');
|
||||
return raw.v3_mappins.filter((f) => f.data != null);
|
||||
};
|
||||
export const filter_valid = (users) => {
|
||||
return users.filter((user) => {
|
||||
if (!user.data) {
|
||||
return false;
|
||||
}
|
||||
if (!user.geo) {
|
||||
return false;
|
||||
}
|
||||
if (!user.data.urls) {
|
||||
return false;
|
||||
}
|
||||
if (!user.data.title) {
|
||||
return false;
|
||||
}
|
||||
if (!user.detail) {
|
||||
return false;
|
||||
}
|
||||
if (!user.detail.heroImageUrl) {
|
||||
return false;
|
||||
}
|
||||
if (user.data && user.data.jsError) {
|
||||
return false;
|
||||
}
|
||||
if (user.moderation !== 'accepted') {
|
||||
//return false
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
export const filter_email_only = (users) => {
|
||||
return users.filter((user) => {
|
||||
if (!user.data) {
|
||||
return false;
|
||||
}
|
||||
if (!user.geo) {
|
||||
return false;
|
||||
}
|
||||
if (!user.data.urls) {
|
||||
return false;
|
||||
}
|
||||
if (user.data && user.data.jsError) {
|
||||
return false;
|
||||
}
|
||||
if (!user.detail) {
|
||||
return false;
|
||||
}
|
||||
if (!user.detail.name) {
|
||||
return false;
|
||||
}
|
||||
if (user.data.urls.find((l) => l.name == 'Email') == undefined) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
export const filter_invalid = (users) => {
|
||||
return users.filter((user) => {
|
||||
if (!user.data) {
|
||||
return false;
|
||||
}
|
||||
if (!user.geo) {
|
||||
return false;
|
||||
}
|
||||
if (!user.data.urls) {
|
||||
return false;
|
||||
}
|
||||
if (user.data && user.data.jsError) {
|
||||
return false;
|
||||
}
|
||||
if (!user.detail.name) {
|
||||
return true;
|
||||
}
|
||||
if (user.data.urls.find((l) => l.name == 'Email') == undefined) {
|
||||
return true;
|
||||
}
|
||||
if (user.moderation !== 'accepted') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
export const filter_email_missing = (users) => {
|
||||
return users.filter((user) => {
|
||||
if (!user.data) {
|
||||
return false;
|
||||
}
|
||||
if (!user.geo) {
|
||||
return false;
|
||||
}
|
||||
if (!user.data.urls) {
|
||||
return false;
|
||||
}
|
||||
if (user.data && user.data.jsError) {
|
||||
return false;
|
||||
}
|
||||
if (!user.detail) {
|
||||
return false;
|
||||
}
|
||||
if (!user.detail.name) {
|
||||
return false;
|
||||
}
|
||||
if (user.moderation !== 'accepted') {
|
||||
return false;
|
||||
}
|
||||
if (!user.data.urls.find((l) => l.name == 'Email')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
export const filter_accepted = (users) => {
|
||||
return users.filter((user) => {
|
||||
if (!user.data) {
|
||||
return false;
|
||||
}
|
||||
if (!user.geo) {
|
||||
return false;
|
||||
}
|
||||
if (!user.data.urls) {
|
||||
return false;
|
||||
}
|
||||
if (!user.detail.heroImageUrl) {
|
||||
return false;
|
||||
}
|
||||
if (user.data && user.data.jsError) {
|
||||
return false;
|
||||
}
|
||||
if (user.moderation !== 'accepted') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
export const oa_user_email = (user) => {
|
||||
if (!user.data) {
|
||||
return false;
|
||||
}
|
||||
if (!user.geo) {
|
||||
return false;
|
||||
}
|
||||
if (!user.data.urls) {
|
||||
return false;
|
||||
}
|
||||
if (user.data && user.data.jsError) {
|
||||
return false;
|
||||
}
|
||||
let u = user.data.urls.find((l) => l.name == 'Email');
|
||||
if (u) {
|
||||
return u.url.replace('mailto:', '');
|
||||
}
|
||||
};
|
||||
export const get_user_name = (user) => {
|
||||
let ret = replaceAll('--', '-', sanitize(filenamify(user._id)).replace(/^\-+/g, '').replace(/\-$/, ''));
|
||||
ret = ret.replace(/\-$/, '');
|
||||
ret = ret.replace(/\_$/, '');
|
||||
if (!oa_user_email(user)) {
|
||||
ret += '-uc';
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
export const get_user_display_name = (user) => replaceAll('--', '-', sanitize(filenamify(user.data.title)).replace(/^\-+/g, '').replace(/\-$/, ''));
|
||||
export const getDataPath = (_path = '') => path.resolve(path.join(resolve(DATA_PATH), _path));
|
||||
export const getUsersPath = () => path.resolve(resolve(TEST ? LATEST_TEST : LATEST_TRACK));
|
||||
export const getUsers = () => read(path.resolve(getUsersPath()), 'json') || [];
|
||||
let uPage = 1;
|
||||
let usersAll = [];
|
||||
export const _getForumUsers = async (d, page, detail) => {
|
||||
if (uPage == 1) {
|
||||
usersAll = [];
|
||||
}
|
||||
let users = await d.getUsers(page);
|
||||
if (users.length) {
|
||||
usersAll = usersAll.concat(users);
|
||||
uPage++;
|
||||
return _getForumUsers(d, uPage, detail);
|
||||
}
|
||||
else {
|
||||
uPage = 1;
|
||||
write(path.resolve(F_USERS_NOW), usersAll);
|
||||
let fUsers = read(path.resolve(F_USERS_ALL), 'json') || [];
|
||||
const add = async (u) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let fUser = fUsers.find((fu) => u.id == fu.id);
|
||||
if (!fUser) {
|
||||
fUsers.push(u);
|
||||
fUser = u;
|
||||
}
|
||||
if (!fUser.detail) {
|
||||
logger.debug('Retrieve User Detail ' + u.name);
|
||||
setTimeout(() => {
|
||||
d.getUser(fUser.id).then((detail) => {
|
||||
if (detail) {
|
||||
fUser.detail = detail;
|
||||
}
|
||||
write(path.resolve('./fusers-all.json'), fUsers);
|
||||
resolve(fUser);
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
else {
|
||||
resolve(fUser);
|
||||
}
|
||||
});
|
||||
};
|
||||
return await BPromise.resolve(usersAll).map((u) => {
|
||||
return add(u);
|
||||
}, { concurrency: 1 });
|
||||
}
|
||||
};
|
||||
export const getForumUsers = async (d, detail) => {
|
||||
if (!FETCH_DUSERS) {
|
||||
return read(getDataPath(F_USERS_ALL), 'json') || [];
|
||||
}
|
||||
return _getForumUsers(d, uPage, detail);
|
||||
};
|
||||
export const createUser = async (discourse, oa_user) => {
|
||||
/*
|
||||
Bazar
|
||||
https://shop.osr-plastic.org
|
||||
Website
|
||||
website2
|
||||
Instagram
|
||||
https://www.instagram.com/osr_plastic/
|
||||
Directory / Map Url
|
||||
https://www.google.com/maps/contrib/117674167598277014013
|
||||
OSR - Marketplace Url
|
||||
https://shop.osr-plastic.org/plastichub/
|
||||
*/
|
||||
if (!oa_user.data.title) {
|
||||
return -120;
|
||||
}
|
||||
let name = replaceAll('--', '-', get_user_display_name(oa_user).replace(/^\-+/g, '').replace(/\-$/, ''));
|
||||
let user_name = get_user_name(oa_user);
|
||||
name = user_name.replace(/\-$/, '');
|
||||
name = user_name.replace(/\_$/, '');
|
||||
let opts = {
|
||||
"name": name,
|
||||
"email": oa_user_email(oa_user) || `${user_name}_uc@osr-plastic.org`,
|
||||
"password": DEFAULT_PASSWORD(),
|
||||
"username": user_name,
|
||||
"active": true,
|
||||
"approved": true,
|
||||
"user_fields[1]": true
|
||||
};
|
||||
let user = await discourse.createUser(opts);
|
||||
if (name.length < 4) {
|
||||
return -120;
|
||||
}
|
||||
if (user_name.length > 50) {
|
||||
return -120;
|
||||
}
|
||||
if (user && user.errors) {
|
||||
if (user.message === "Username must be no more than 50 characters" ||
|
||||
user.message === 'Username must not contain a sequence of 2 or more special chars (.-_)') {
|
||||
return -120;
|
||||
}
|
||||
if (user.message === "Username must be unique" || user.message === "Primary email has already been taken") {
|
||||
return -100;
|
||||
}
|
||||
if (user.errors.email && user.errors.username) {
|
||||
user = await discourse.getUserByUsername(user_name);
|
||||
if (user && user.id && !oa_user._didSetGroup) {
|
||||
try {
|
||||
let gret = await discourse.updateGroup(user_name, OA_USER_IMPORT_GROUP);
|
||||
}
|
||||
catch (e) {
|
||||
logger.error('error adding to group', user_name);
|
||||
}
|
||||
return user.id;
|
||||
}
|
||||
;
|
||||
}
|
||||
logger.error('Error creating user ' + user_name, user.errors);
|
||||
}
|
||||
if (user && user.user_id) {
|
||||
try {
|
||||
await discourse.updateGroup(user_name, OA_USER_IMPORT_GROUP);
|
||||
return user.user_id;
|
||||
}
|
||||
catch (e) {
|
||||
logger.error('error adding to group', user_name);
|
||||
return user.user_id;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (user && user.message && user.message == 'Username must be unique\nPrimary email has already been taken') {
|
||||
logger.error('already created', oa_user.detail.name);
|
||||
return -10;
|
||||
}
|
||||
else if (user && user.message && user.message == 'Your account is activated and ready to use.') {
|
||||
if (user.user_id) {
|
||||
return user.user_id;
|
||||
}
|
||||
return -10;
|
||||
}
|
||||
else {
|
||||
logger.debug('cant create user ' + oa_user.detail.name, user);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
export const uploadAvatar = async (discourse, name, filePath) => {
|
||||
const users = getUsers();
|
||||
const index = users.findIndex((u) => u.detail.name == name);
|
||||
try {
|
||||
const upped = await discourse.upload(1, filePath);
|
||||
const data = upped.data;
|
||||
if (data && data.id) {
|
||||
users[index].upload_id = data.id;
|
||||
logger.debug('uploaded avatar ' + name + ' ' + data.id);
|
||||
write(getUsersPath(), users);
|
||||
}
|
||||
else {
|
||||
logger.error('upload - error', name);
|
||||
}
|
||||
return users;
|
||||
}
|
||||
catch (error) {
|
||||
users[index].upload_id = -1;
|
||||
logger.error('error uploading avatar', name);
|
||||
write(getUsersPath(), users);
|
||||
}
|
||||
};
|
||||
const uploadAvatars = async (discourse, users) => {
|
||||
const toBeUploaded = users.filter((u) => {
|
||||
if (u.upload_id) {
|
||||
return false;
|
||||
}
|
||||
const hero = getImageName(u.detail.heroImageUrl);
|
||||
const avatar = findAvatar(u, hero);
|
||||
if (!avatar) {
|
||||
logger.error('cant find avatar : ', u._id, hero);
|
||||
return false;
|
||||
}
|
||||
u.avatar = avatar;
|
||||
return true;
|
||||
});
|
||||
return await BPromise.resolve(toBeUploaded).map((u) => {
|
||||
if (!u.detail.name) {
|
||||
return;
|
||||
}
|
||||
logger.debug('upload avatar : ' + u._id);
|
||||
const t = uploadAvatar(discourse, u.detail.name, u.avatar);
|
||||
return t;
|
||||
}, { concurrency: 1 });
|
||||
};
|
||||
const findAvatar = (user, filename) => {
|
||||
const root = path.resolve(resolve(DATA_PATH));
|
||||
const _path = path.resolve(`${root}/${user._id}/${filename}`);
|
||||
if (exists(_path)) {
|
||||
return _path;
|
||||
}
|
||||
const files = fg.sync('**/**/*' + filename + '*', { dot: true, cwd: root, absolute: true });
|
||||
if (files.length == 0) {
|
||||
return false;
|
||||
}
|
||||
return files[0];
|
||||
};
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
// users
|
||||
//
|
||||
export const updateUser = async (discorse, oa_user) => {
|
||||
const users = getUsers();
|
||||
const index = users.findIndex((u) => u.detail.name == oa_user.detail.name);
|
||||
const user_name = replaceAll('--', '-', get_user_name(oa_user).replace(/^\-+/g, '').replace(/\-$/, ''));
|
||||
let ret = null;
|
||||
try {
|
||||
ret = await discorse.updateUser(user_name, {
|
||||
name: oa_user.data.title
|
||||
});
|
||||
try {
|
||||
let location;
|
||||
if (oa_user.geo) {
|
||||
location = `${oa_user.geo.continent} / ${oa_user.geo.countryName} / ${oa_user.geo.city} `;
|
||||
}
|
||||
let website;
|
||||
if (oa_user.data) {
|
||||
website = oa_user.data.urls.find((l) => l.name == 'Website');
|
||||
if (website) {
|
||||
website = website.url;
|
||||
}
|
||||
}
|
||||
let description;
|
||||
if (oa_user.data) {
|
||||
if (oa_user.data.description) {
|
||||
description += oa_user.data.description;
|
||||
}
|
||||
description += '\n';
|
||||
if (oa_user.data.services) {
|
||||
let services = `### Services \n`;
|
||||
let hasServices = false;
|
||||
for (let s in oa_user.data.services[0]) {
|
||||
if (oa_user.data.services[0][s]) {
|
||||
services += `- [x] ${capitalize(s)}\n`;
|
||||
hasServices = true;
|
||||
}
|
||||
}
|
||||
if (hasServices) {
|
||||
description += services;
|
||||
}
|
||||
}
|
||||
}
|
||||
let links = '';
|
||||
if (oa_user.data.urls) {
|
||||
links = oa_user.data.urls.filter((r) => r.name !== 'Bazar' && r.name !== 'sponsor the work').map((l) => {
|
||||
let label = '' + l.name;
|
||||
if (label === 'Social media') {
|
||||
if (l.url.indexOf('facebook') !== -1) {
|
||||
label = 'Facebook';
|
||||
}
|
||||
if (l.url.indexOf('instagram') !== -1) {
|
||||
label = 'Instagram';
|
||||
}
|
||||
}
|
||||
label += " - " + l.url;
|
||||
label = label.replace("https://", "");
|
||||
label = label.replace("http://", "");
|
||||
label = label.replace("mailto:", "");
|
||||
return `<a href="${l.url}">${label}</a>`;
|
||||
}).join("<br/>\n");
|
||||
description += '\n### Links\n';
|
||||
description += links;
|
||||
}
|
||||
if (oa_user.location) {
|
||||
description += `\n\n <a href="https://www.google.com/maps/search/${oa_user.location.lat},${oa_user.location.lng}">Get Directions</a>\n`;
|
||||
}
|
||||
let updatePrefs = await discorse.updateUserProfile(user_name, {
|
||||
bio_raw: replaceAll('undefined', '', description),
|
||||
location,
|
||||
website
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
logger.error(`Error updating user prefs : ${user_name}`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
logger.error('error updating user', oa_user._id, error.message);
|
||||
return;
|
||||
}
|
||||
if (ret.status === 200) {
|
||||
users[index].didUpdateName = true;
|
||||
logger.debug('did update user', oa_user._id, ' # ', oa_user.data.title);
|
||||
write(getUsersPath(), users);
|
||||
}
|
||||
else {
|
||||
logger.error('did update user failed ', oa_user._id);
|
||||
}
|
||||
};
|
||||
export const importUser = async (discorse, oa_user) => {
|
||||
const users = getUsers();
|
||||
const index = users.findIndex((u) => u._id == oa_user._id);
|
||||
let user = null;
|
||||
try {
|
||||
user = await createUser(discorse, oa_user);
|
||||
}
|
||||
catch (error) {
|
||||
debugger;
|
||||
logger.error('error creating user', error);
|
||||
return false;
|
||||
}
|
||||
if (user === -100) {
|
||||
users[index].alreadyExists = true;
|
||||
write(getUsersPath(), users);
|
||||
return;
|
||||
}
|
||||
if (user === -120) {
|
||||
users[index].invalidData = true;
|
||||
write(getUsersPath(), users);
|
||||
return;
|
||||
}
|
||||
if (user && users[index].upload_id && !users[index]._didSetAvatar) {
|
||||
try {
|
||||
await discorse.setUserAvatar(get_user_name(oa_user), users[index].upload_id);
|
||||
}
|
||||
catch (e) {
|
||||
logger.error('error setting avatar', get_user_name(oa_user));
|
||||
}
|
||||
}
|
||||
const _t = users[index];
|
||||
if (user > 0) {
|
||||
users[index].f_id = user;
|
||||
users[index]._didSetAvatar = true;
|
||||
users[index]._didSetGroup = true;
|
||||
logger.debug('\t created ' + oa_user.data.title);
|
||||
write(getUsersPath(), users);
|
||||
}
|
||||
else {
|
||||
logger.error('cant create user - error', oa_user.detail.name, user);
|
||||
}
|
||||
return users[index];
|
||||
};
|
||||
export const mergeLatestUsers = (discorse, options, oa_users) => {
|
||||
const users = getUsers();
|
||||
oa_users.forEach((u) => {
|
||||
const tUser = users.find((tu) => {
|
||||
return tu._id === u._id;
|
||||
});
|
||||
if (!tUser) {
|
||||
users.push(u);
|
||||
}
|
||||
});
|
||||
logger.debug(`Merged users to ${getUsersPath()}`);
|
||||
write(getUsersPath(), users);
|
||||
return users;
|
||||
};
|
||||
export const mergeLatestUsersTest = (discorse, options, oa_users) => {
|
||||
const users = (read(LATEST_TEST, 'json') || []);
|
||||
oa_users.forEach((u) => {
|
||||
const tUser = users.find((u) => {
|
||||
return u._id === u._id;
|
||||
});
|
||||
if (!tUser) {
|
||||
users.push(u);
|
||||
}
|
||||
});
|
||||
write(options.track, users);
|
||||
return users;
|
||||
};
|
||||
export const importUsers = async (discorse, options, oa_users) => {
|
||||
logger.debug('read users from ', path.resolve(getUsersPath()));
|
||||
let users = mergeLatestUsers(discorse, options, oa_users);
|
||||
//const users = mergeLatestUsersTest(discorse, options, oa_users)
|
||||
users = users.filter((u) => {
|
||||
if (u.f_id || u.f_id < 0) {
|
||||
return false;
|
||||
}
|
||||
if (u.detail.name === 'plastichub' || u.detail.name === 'lu' || u.detail.name === 'timberstar' || u.detail.name === 'nickname') {
|
||||
return false;
|
||||
}
|
||||
if (u.alreadyExists || u.invalidData) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
logger.debug('Create Users ' + users.length + ' Total | Left: ' + users.length);
|
||||
await uploadAvatars(discorse, users);
|
||||
return await BPromise.resolve(users).map((u) => {
|
||||
logger.debug('import user ' + get_user_name(u));
|
||||
try {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
const d = importUser(discorse, u);
|
||||
if (d) {
|
||||
d.then(resolve);
|
||||
}
|
||||
else {
|
||||
reject();
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
debugger;
|
||||
logger.error('error creating user ' + u._id, e);
|
||||
}
|
||||
}, { concurrency: 1 });
|
||||
};
|
||||
export const updateUsers = async (discorse, options, oa_users) => {
|
||||
// https://forum.osr-plastic.org/u/easymoulds/preferences/profile
|
||||
const users = mergeLatestUsers(discorse, options, oa_users);
|
||||
//const users = mergeLatestUsersTest(discorse, options, oa_users)
|
||||
let toBeCreated = users.filter((u) => {
|
||||
if (u.f_id || u.f_id < 0) {
|
||||
return true;
|
||||
}
|
||||
if (u.didUpdateName) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
const testUser = 'easymoulds';
|
||||
const test = toBeCreated.find((u) => {
|
||||
return u._id === testUser;
|
||||
});
|
||||
// toBeCreated = [test]
|
||||
return await BPromise.resolve(toBeCreated).map((u) => {
|
||||
/*
|
||||
if (u.didUpdateName) {
|
||||
return false
|
||||
}
|
||||
*/
|
||||
try {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
const d = updateUser(discorse, u);
|
||||
if (d) {
|
||||
d.then(resolve);
|
||||
}
|
||||
else {
|
||||
reject();
|
||||
}
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
debugger;
|
||||
logger.error('error creating user ' + u._id, e);
|
||||
}
|
||||
}, { concurrency: 1 });
|
||||
};
|
||||
export const md_edit_wrap = (content, f, prefix = '', context = '') => {
|
||||
return html_beautify(`<div prefix="${prefix}" file="${path.parse(f).base}" context="${context}" class="fragment">${content}</div>`);
|
||||
};
|
||||
export const toHTML = (path, markdown) => {
|
||||
const content = read(path, 'string');
|
||||
if (!markdown) {
|
||||
let converter = new Converter({ tables: true });
|
||||
converter.setOption('literalMidWordUnderscores', 'true');
|
||||
return converter.makeHtml(content);
|
||||
}
|
||||
else {
|
||||
return content;
|
||||
}
|
||||
};
|
||||
export const imageName = (url) => {
|
||||
if (!url) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
const parsed = URI.parse(decodeURIComponent(url));
|
||||
const pParsed = path.parse(parsed.path);
|
||||
return sanitize(decodeURIComponent(pParsed.base));
|
||||
}
|
||||
catch (error) {
|
||||
logger.error('error image name : ', url);
|
||||
return "";
|
||||
}
|
||||
};
|
||||
export const read_fragments = (src, config, prefix = '', context = '') => {
|
||||
if (!exists(src)) {
|
||||
//debug.warn(`Create template folder ${src}`);
|
||||
mkdir(src);
|
||||
}
|
||||
let fragments = files(src, '*.html');
|
||||
fragments.map((f) => {
|
||||
config[path.parse(f).name] = md_edit_wrap(toHTML(f, true), f, prefix, context);
|
||||
});
|
||||
fragments = files(src, '*.md');
|
||||
fragments.map((f) => {
|
||||
config[path.parse(f).name] = md_edit_wrap(toHTML(f, false), f, prefix, context);
|
||||
});
|
||||
return config;
|
||||
};
|
||||
export const indexUsers = async (discorse, options, oa_users) => {
|
||||
let users = mergeLatestUsers(discorse, options, oa_users);
|
||||
users = users.filter((u) => {
|
||||
if (u.f_id && u.data && u.geo) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
const continents = [];
|
||||
const countries = [];
|
||||
const navIndex = [];
|
||||
users.forEach((u) => {
|
||||
if (!u.geo || !u.data || u.data.jsError || !u.detail || !u.detail.heroImageUrl) {
|
||||
return;
|
||||
}
|
||||
if (!u.detail.heroImageUrl) {
|
||||
return;
|
||||
}
|
||||
let code = null;
|
||||
if (u.geo.continent && continents.indexOf(u.geo.continent) == -1) {
|
||||
continents.push(u.geo.continent);
|
||||
navIndex.push({
|
||||
title: u.geo.continent,
|
||||
url: `/users/${slugify(u.geo.continent)}.html`,
|
||||
children: [],
|
||||
code: u.geo.continentCode
|
||||
// code:u.geo.continentCode
|
||||
});
|
||||
}
|
||||
if (countries.indexOf(u.geo.countryName) == -1) {
|
||||
countries.push(u.geo.countryName);
|
||||
}
|
||||
const c = navIndex.find((c) => c.title === u.geo.continent);
|
||||
if (c) {
|
||||
const cc = c.children.find((i) => i.title == u.geo.countryName);
|
||||
if (!cc) {
|
||||
c.children.push({
|
||||
title: u.geo.countryName,
|
||||
url: `/users/${slugify(c.title)}.html#${slugify(u.geo.countryName.toLocaleLowerCase())}`,
|
||||
postTitle: `Directory - ${u.geo.countryName}`
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
navIndex.sort((a, b) => {
|
||||
if (a.title < b.title) {
|
||||
return -1;
|
||||
}
|
||||
if (a.title > b.title) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
navIndex.forEach((c) => {
|
||||
c.children.sort((a, b) => {
|
||||
if (a.title < b.title) {
|
||||
return -1;
|
||||
}
|
||||
if (a.title > b.title) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
});
|
||||
const directoryRoot = path.resolve(resolve('${OSR_ROOT}/osr-directory/pp'));
|
||||
const createContinentPage = (continent) => {
|
||||
const templates_path = path.resolve(`${directoryRoot}/templates`);
|
||||
if (!exists(templates_path)) {
|
||||
logger.error(`\t Cant find templates at ${templates_path}, path doesn't exists`);
|
||||
return;
|
||||
}
|
||||
const cPath = path.resolve(`${directoryRoot}/templates/config.json`);
|
||||
const config = read(cPath, 'json');
|
||||
let fragments = { ...config };
|
||||
read_fragments(templates_path, fragments, "product_rel_path_name", "machine");
|
||||
let templateCountry = read(path.resolve(`${templates_path}/country_users.md`), 'string');
|
||||
const ccountries = {};
|
||||
let code = null;
|
||||
users.forEach((u) => {
|
||||
if (!u.geo || !u.data || u.data.jsError || !u.detail || !u.detail.heroImageUrl) {
|
||||
return;
|
||||
}
|
||||
if (!u.detail.heroImageUrl) {
|
||||
return;
|
||||
}
|
||||
if (u.geo.continent && u.geo.continent === continent) {
|
||||
if (!code) {
|
||||
code = u.geo.continentCode;
|
||||
}
|
||||
if (!ccountries[u.geo.countryName]) {
|
||||
ccountries[u.geo.countryName] = [];
|
||||
}
|
||||
ccountries[u.geo.countryName].push(u);
|
||||
}
|
||||
});
|
||||
if (continent === 'Africa') {
|
||||
//debugger;
|
||||
}
|
||||
let weight = 100;
|
||||
for (var country in ccountries) {
|
||||
let cPage = "";
|
||||
if (country === 'Kenya') {
|
||||
//debugger;
|
||||
}
|
||||
cPage += `\n#### ${slugify(country)}\n\n`;
|
||||
if (country === 'undefined' || country === 'unknown' || !country) {
|
||||
return;
|
||||
}
|
||||
cPage += '<div class="container">';
|
||||
cPage += '<div class=""><div class="col-12"><div class="list-group">';
|
||||
let cusers = ccountries[country];
|
||||
cusers = cusers.sort((a, b) => a.type === b.type ? 1 : -1);
|
||||
const cUsersC = cusers.map((u) => {
|
||||
const prefix = u.moderation === 'rejected' ? "<span style='color:red'>Censored</span>" : "";
|
||||
const image = `/users/${u._id}/${encodeURIComponent(sanitize(imageName(u.detail.heroImageUrl)))}`;
|
||||
const title = u.data && u.data.title ? u.data.title : u._id;
|
||||
const uUrl = `/directory/users/${u._id}`;
|
||||
let censored = u.moderation === 'rejected' ? '<span class="text-danger">Yes</span>' : 'No';
|
||||
return `<div class="list-group-item d-flex align-items-center">
|
||||
<a href="${uUrl}">
|
||||
<img loading=lazy src="${image}" class="text-info mx-2 personLogo"/></a>
|
||||
<div class="">
|
||||
<a href="${uUrl}">${title}</a><br/>
|
||||
<span>Type: ${u.type}</span><br/>
|
||||
<span>Censored: ${censored}</span>
|
||||
<br/>
|
||||
<span class="personLocationInfo"> ${u.geo.principalSubdivision} / ${u.geo.locality} - ${u.geo.principalSubdivisionCode} - ${u.geo.postcode}</span>
|
||||
</div>
|
||||
</div>`;
|
||||
});
|
||||
cPage += cUsersC.join('');
|
||||
cPage += '</div></div></div></div>';
|
||||
country = country.replace(' (the)', '');
|
||||
/*
|
||||
const cPagePath = path.resolve(`${kb}/src/directory/users_${sanitize(slugify(country))}-${code}.md`)
|
||||
|
||||
const title = 'Users - ' + country;
|
||||
|
||||
cPage = substitute(templateCountry, {
|
||||
...fragments,
|
||||
title: title,
|
||||
keywords: 'Precious Plastic, Precious Plastic Users - ' + country,
|
||||
content: html_beautify(cPage),
|
||||
continent: slugify(continent),
|
||||
country: slugify(country),
|
||||
identifier: country + "-" + continent,
|
||||
weight: weight
|
||||
});
|
||||
|
||||
weight++;
|
||||
write(cPagePath, cPage);
|
||||
console.log('write ' + cPagePath);
|
||||
*/
|
||||
}
|
||||
/*
|
||||
content = substitute(template, {
|
||||
...fragments,
|
||||
title: 'Precious Plastic - Users ' + continent,
|
||||
keywords: 'Precious Plastic, Precious Plastic Users - ' + continent,
|
||||
content: content,
|
||||
continent: slugify(continent)
|
||||
});
|
||||
*/
|
||||
//const index_md = path.resolve(`${root}/_pages/users_${code}.md`);
|
||||
//write(index_md, content);
|
||||
};
|
||||
const templates_path = path.resolve(`${directoryRoot}/templates`);
|
||||
const createCountryPages = async (index, indexPath) => {
|
||||
let i = 0;
|
||||
for await (const continent of index) {
|
||||
const countries = continent.children;
|
||||
for await (const country of countries) {
|
||||
const d = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
await createCountryPages(navIndex, './');
|
||||
const createIntroPage = async (users, index, dst) => {
|
||||
let template = read(path.resolve(`${templates_path}/intro_users.md`));
|
||||
let content = "";
|
||||
const usersPerCountry = (country) => {
|
||||
return users.filter((u) => u.geo.countryName === country);
|
||||
};
|
||||
index.forEach((i) => {
|
||||
const heading = `## ${i.title}`;
|
||||
let countries = '';
|
||||
i.children.forEach((c) => {
|
||||
let title = c.title.replace(/ *\([^)]*\) */g, "");
|
||||
const nb = usersPerCountry(c.title).length;
|
||||
title = `${title} \(${nb}\)`;
|
||||
const cPagePath = `/directory/users_${sanitize(slugify(c.title))}-${i.code}`;
|
||||
countries += `- [${(title)}](${cPagePath.toLowerCase()})\n`;
|
||||
});
|
||||
content += `${heading}\n ${countries}`;
|
||||
});
|
||||
write(dst, substitute(template, {
|
||||
content: content,
|
||||
/*hidden: data.v3_mappins.filter((u) => u.moderation !== "accepted").length,
|
||||
total: data.v3_mappins.length*/
|
||||
}));
|
||||
let data;
|
||||
try {
|
||||
data = await discorse.updatePost(OA_DIRECTORY_OVERVIEW_TOPIC, content);
|
||||
debugger;
|
||||
//logger.debug('update post : ' + options.title + ' : ' + data.id + ' | topic id ' + data.topic_id)
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// await createIntroPage(users, navIndex, './index.md')
|
||||
/*
|
||||
|
||||
return await BPromise.resolve(users).map((u: IImportUser) => {
|
||||
try {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
const d = updateUser(discorse, u)
|
||||
if (d) {
|
||||
d.then(resolve)
|
||||
} else {
|
||||
reject()
|
||||
}
|
||||
}, 200)
|
||||
|
||||
})
|
||||
|
||||
} catch (e) {
|
||||
debugger;
|
||||
logger.error('error creating user ' + u._id, e)
|
||||
}
|
||||
}, { concurrency: 1 })
|
||||
|
||||
*/
|
||||
};
|
||||
//# sourceMappingURL=users.js.map
|
||||
1
packages/discourse-legacy/dist/lib/oa/users.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/oa/users.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
25
packages/discourse-legacy/dist/lib/oa/utils.d.ts
vendored
Normal file
25
packages/discourse-legacy/dist/lib/oa/utils.d.ts
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
export declare const uploadFile: (discourse: any, forum: any, name: any, filePath: any) => Promise<any>;
|
||||
export declare const findReplyPage: (b: any, pages: any) => any;
|
||||
export declare const findReplyUpload: (u: any, page: any) => any;
|
||||
export declare const getPages: (topics: any, topic: any) => any;
|
||||
export declare const getReplies: (topics: any, topic: any) => any[];
|
||||
export declare const findFile: (folder: any, filename: any) => any;
|
||||
export declare const topicFolder: (forum: any, folder: any, title: any) => string;
|
||||
export declare const getFUser: (users: any, user_name: any) => any;
|
||||
export declare const dOptions: {
|
||||
host: string;
|
||||
key: string;
|
||||
username: string;
|
||||
rateLimitConcurrency: number;
|
||||
};
|
||||
export declare const getOAvatar: (index: any, user: any) => any;
|
||||
export declare const getTopics: (index: any) => any[];
|
||||
export declare const convert: (input: string) => any;
|
||||
export declare const getDiscourse: () => any;
|
||||
export declare function inspect(arg: any): string;
|
||||
export declare function log(...args: any[]): void;
|
||||
export declare function mkdirp(path: string): Promise<void>;
|
||||
export declare function readJSON<T extends object>(path: string): Promise<T>;
|
||||
export declare function writeJSON(path: string, data: object): Promise<void>;
|
||||
export declare function exists(path: string): Promise<boolean>;
|
||||
export declare function escape(path: string): string;
|
||||
150
packages/discourse-legacy/dist/lib/oa/utils.js
vendored
Normal file
150
packages/discourse-legacy/dist/lib/oa/utils.js
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
import fs from 'fs';
|
||||
import { inspect as utilInspect } from 'util';
|
||||
const cwd = process.cwd();
|
||||
var TurndownService = require('turndown');
|
||||
import { Discourser } from '../index';
|
||||
import * as path from 'path';
|
||||
const fg = require('fast-glob');
|
||||
import slugify from "slugify";
|
||||
var sanitize = require("sanitize-filename");
|
||||
//import { replaceAll } from '../../lib';
|
||||
var mom = require('moment');
|
||||
export const uploadFile = async (discourse, forum, name, filePath) => {
|
||||
return await discourse.upload(1, filePath);
|
||||
};
|
||||
export const findReplyPage = (b, pages) => {
|
||||
return pages.find((p) => {
|
||||
return p.replies.find((r) => {
|
||||
return r.replyBody == b;
|
||||
});
|
||||
});
|
||||
};
|
||||
export const findReplyUpload = (u, page) => {
|
||||
const f_pics = page.f_pics || [];
|
||||
return f_pics.find((p) => {
|
||||
return p.url === u;
|
||||
});
|
||||
};
|
||||
export const getPages = (topics, topic) => {
|
||||
return topics.filter((t) => {
|
||||
return t.title == topic.title;
|
||||
});
|
||||
};
|
||||
export const getReplies = (topics, topic) => {
|
||||
if (topic.nextPages) {
|
||||
const all = topics.filter((t) => {
|
||||
return t.title == topic.title;
|
||||
});
|
||||
let replies = all.map((t) => t.replies);
|
||||
replies = [].concat.apply([], replies);
|
||||
replies = replies.sort((a, b) => {
|
||||
const d1 = mom(a.replyDate, 'DD/MM/YYYY AT HH:mm').toDate();
|
||||
const d2 = mom(b.replyDate, 'DD/MM/YYYY AT HH:mm').toDate();
|
||||
return new Date(d1).getTime() > new Date(d2).getTime() ? 1 : -1;
|
||||
});
|
||||
return replies;
|
||||
/*
|
||||
const findReply = (b, pages) => {
|
||||
return pages.find((p) => {
|
||||
return p.replies.find((r) => {
|
||||
return r.replyBody == b;
|
||||
})
|
||||
})
|
||||
}
|
||||
const p = findReply('\n\n\n<p>sounds great, let me get Old Tony´s Schaeubling 13 and a surface grinder first, after that I can do the parts for the espresso machine in the best <a href=\"https://www.youtube.com/watch?v=hpenv1ZqGx4\" rel=\"nofollow\" target=\"_blank\">maker porn fashion possible,</a> no seriously, every time I thought I know something, there’s just another video around the next corner making me cry like a baby, incl. the coffee machine <img draggable=\"false\" class=\"emoji\" alt=\"🙁\" src=\"https://s.w.org/images/core/emoji/11/svg/1f641.svg\"></p>\n', all);
|
||||
debugger;
|
||||
*/
|
||||
}
|
||||
return [];
|
||||
};
|
||||
export const findFile = (folder, filename) => {
|
||||
const files = fg.sync('**/**/*' + filename + '*', { dot: true, cwd: folder, absolute: true });
|
||||
if (files.length == 0) {
|
||||
return false;
|
||||
}
|
||||
return files[0];
|
||||
};
|
||||
export const topicFolder = (forum, folder, title) => {
|
||||
const _title = sanitize(slugify(title));
|
||||
const tf = path.resolve(forum + '/' + folder + '/' + _title);
|
||||
return tf;
|
||||
};
|
||||
export const getFUser = (users, user_name) => {
|
||||
return users.find((u) => {
|
||||
return u.name == user_name;
|
||||
});
|
||||
};
|
||||
export const dOptions = {
|
||||
host: 'https://forum.osr-plastic.org',
|
||||
key: 'f624b8385fb2219cb49de63d1e22883afdf7b7367a0bebf822523f49f2678031',
|
||||
username: 'admin',
|
||||
rateLimitConcurrency: 1
|
||||
};
|
||||
export const getOAvatar = (index, user) => {
|
||||
const topics = getTopics(index);
|
||||
let topic = topics.find((t) => {
|
||||
return t.authorName == user;
|
||||
});
|
||||
if (topic) {
|
||||
return topic.authorImage;
|
||||
}
|
||||
for (let i = 0; i < topics.length; i++) {
|
||||
const t = topics[i];
|
||||
if (t.replies) {
|
||||
const r = t.replies.find((r) => {
|
||||
return r.user == user;
|
||||
});
|
||||
if (r) {
|
||||
return r.avatar;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
export const getTopics = (index) => {
|
||||
let topics = [];
|
||||
for (let t in index) {
|
||||
topics.push(index[t]);
|
||||
}
|
||||
return topics;
|
||||
};
|
||||
export const convert = (input) => {
|
||||
var turndownService = new TurndownService();
|
||||
return turndownService.turndown(input);
|
||||
};
|
||||
export const getDiscourse = () => {
|
||||
return new Discourser(dOptions);
|
||||
};
|
||||
export function inspect(arg) {
|
||||
return utilInspect(arg, {
|
||||
depth: 5,
|
||||
colors: true,
|
||||
});
|
||||
}
|
||||
export function log(...args) {
|
||||
console.log(...args.map((arg) => inspect(arg)));
|
||||
}
|
||||
export async function mkdirp(path) {
|
||||
try {
|
||||
await fs.promises.mkdir(path);
|
||||
}
|
||||
catch (err) {
|
||||
// don't care if it already exists
|
||||
}
|
||||
}
|
||||
export async function readJSON(path) {
|
||||
const text = await fs.promises.readFile(path, 'utf8');
|
||||
return JSON.parse(text);
|
||||
}
|
||||
export function writeJSON(path, data) {
|
||||
return fs.promises.writeFile(path, JSON.stringify(data));
|
||||
}
|
||||
export function exists(path) {
|
||||
return new Promise(function (resolve) {
|
||||
fs.exists(path, resolve);
|
||||
});
|
||||
}
|
||||
export function escape(path) {
|
||||
return path.replace(/[^\w]/g, '-').replace(/-+/, '-');
|
||||
}
|
||||
//# sourceMappingURL=utils.js.map
|
||||
1
packages/discourse-legacy/dist/lib/oa/utils.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/oa/utils.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
packages/discourse-legacy/dist/lib/osr/index.d.ts
vendored
Normal file
1
packages/discourse-legacy/dist/lib/osr/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export * from './urls';
|
||||
2
packages/discourse-legacy/dist/lib/osr/index.js
vendored
Normal file
2
packages/discourse-legacy/dist/lib/osr/index.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './urls';
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
packages/discourse-legacy/dist/lib/osr/index.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/osr/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/osr/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA"}
|
||||
1
packages/discourse-legacy/dist/lib/osr/urls.d.ts
vendored
Normal file
1
packages/discourse-legacy/dist/lib/osr/urls.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare const marketplaceUrl: (store: any, product_id: any) => string;
|
||||
2
packages/discourse-legacy/dist/lib/osr/urls.js
vendored
Normal file
2
packages/discourse-legacy/dist/lib/osr/urls.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export const marketplaceUrl = (store, product_id) => `${store}/dispatch=products.view&product_id=${product_id}`;
|
||||
//# sourceMappingURL=urls.js.map
|
||||
1
packages/discourse-legacy/dist/lib/osr/urls.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/osr/urls.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../../../src/lib/osr/urls.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAChD,GAAG,KAAK,sCAAsC,UAAU,EAAE,CAAA"}
|
||||
11
packages/discourse-legacy/dist/lib/sync/commons.d.ts
vendored
Normal file
11
packages/discourse-legacy/dist/lib/sync/commons.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/// <reference types="node" resolution-mode="require"/>
|
||||
export declare const fileAsBuffer: (path: string) => Buffer;
|
||||
export declare const images_urls: (content: string) => any[];
|
||||
export declare const adjustUrls: (content: string, options: IOptionsSync) => any;
|
||||
export declare const fromJSON: (content: string, file: string, options: IOptionsSyncComponent) => void;
|
||||
export declare const fromYAML: (content: string, options: IOptionsSync) => {
|
||||
attributes: any;
|
||||
body: any;
|
||||
};
|
||||
export declare const option: (option: string, taskOptions: any, col: any, _default?: any) => any;
|
||||
export declare const createContent: (file: any, _options: any) => Promise<any>;
|
||||
164
packages/discourse-legacy/dist/lib/sync/commons.js
vendored
Normal file
164
packages/discourse-legacy/dist/lib/sync/commons.js
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
import * as path from 'path';
|
||||
import { Engine as engine } from '@plastichub/osrl/Engine';
|
||||
import { parse } from '@plastichub/osrl/options';
|
||||
import { pathInfo } from '@polymech/commons/glob';
|
||||
import { resolve } from '@polymech/commons';
|
||||
import { logger } from '../../';
|
||||
import { sync as exists } from '@polymech/fs/exists';
|
||||
import { sync as read } from '@polymech/fs/read';
|
||||
import { sync as write } from '@polymech/fs/write';
|
||||
import { Promise as BPromise } from 'bluebird';
|
||||
import { MODULE_NAME } from '../../constants';
|
||||
const chokidar = require("chokidar");
|
||||
const cheerio = require('cheerio');
|
||||
const frontMatter = require('front-matter');
|
||||
export const fileAsBuffer = (path) => read(path, 'buffer') || Buffer.from("-");
|
||||
import { get_cached, set_cached } from '@plastichub/osr-cache/lib';
|
||||
import { OSR_CACHE } from '@polymech/commons';
|
||||
import * as md5 from 'md5';
|
||||
import { RMark, toHTML } from '../markdown';
|
||||
export const images_urls = (content) => {
|
||||
const html = toHTML(content);
|
||||
const $ = cheerio.load(html, {
|
||||
xmlMode: true
|
||||
});
|
||||
const images = [];
|
||||
const links = [];
|
||||
$('img').each(function () {
|
||||
images.push($(this).attr('src'));
|
||||
});
|
||||
return images;
|
||||
};
|
||||
export const adjustUrls = (content, options) => {
|
||||
let ret = new RMark({
|
||||
images: (match, capture, arg1, arg2) => ``,
|
||||
//links: (match, capture, arg1, arg2) => `[${capture}](${arg1})`
|
||||
}).render(content);
|
||||
return ret;
|
||||
};
|
||||
export const fromJSON = (content, file, options) => {
|
||||
};
|
||||
export const fromYAML = (content, options) => {
|
||||
if (frontMatter.test(content)) {
|
||||
const fm = frontMatter(content);
|
||||
return {
|
||||
attributes: fm.attributes,
|
||||
body: fm.body
|
||||
};
|
||||
}
|
||||
else {
|
||||
return {
|
||||
attributes: {},
|
||||
body: content
|
||||
};
|
||||
}
|
||||
};
|
||||
// to be changed to osr-defaults
|
||||
export const option = (option, taskOptions, col, _default) => {
|
||||
// support grunt or yargs
|
||||
const val = col.option ? col.option : (option) => col[option];
|
||||
let ret = taskOptions[option] !== undefined ? taskOptions[option] : _default;
|
||||
if (val(option) !== undefined) {
|
||||
ret = val(option);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
export const createContent = async (file, _options) => {
|
||||
const parts = path.parse(file);
|
||||
const rel = path.relative(_options.root, file);
|
||||
let output = _options.output;
|
||||
let outputInfo = pathInfo(_options.output);
|
||||
const variables = {
|
||||
root: '.',
|
||||
cwd: _options.cwd || path.resolve('.'),
|
||||
..._options.variables
|
||||
};
|
||||
if (!outputInfo.FILE_EXT) {
|
||||
output = path.resolve(`${_options.output}/${path.parse(rel).dir}/${parts.name}.md`);
|
||||
}
|
||||
else {
|
||||
output = path.resolve(resolve(output, false, variables));
|
||||
}
|
||||
const defaults = {
|
||||
language: _options.lang,
|
||||
debug: _options.debug,
|
||||
profile: _options.profile,
|
||||
output: output,
|
||||
plugins: _options.plugins,
|
||||
env: _options.env || 'library',
|
||||
cwd: _options.cwd || path.resolve('.'),
|
||||
source: file,
|
||||
variables
|
||||
};
|
||||
const options = parse(defaults, defaults);
|
||||
const eOptions = {
|
||||
...options,
|
||||
root: [
|
||||
...options.profile.includes,
|
||||
path.parse(file).dir
|
||||
],
|
||||
toHTML: false,
|
||||
cache: false,
|
||||
keepOutputType: true,
|
||||
trimTagRight: false,
|
||||
trimTagLeft: false,
|
||||
trimOutputRight: false,
|
||||
trimOutputLeft: false,
|
||||
greedy: false
|
||||
};
|
||||
const Engine = new engine(eOptions);
|
||||
options.source = path.resolve(options.source);
|
||||
const osr_cache = OSR_CACHE();
|
||||
const cached = await get_cached(options.source, eOptions, _options.module || MODULE_NAME);
|
||||
if (osr_cache && cached && _options.cache !== false) {
|
||||
options.debug && logger.info('Compile file serving from cache: ' + options.source);
|
||||
let md5Src = md5(Buffer.from(cached));
|
||||
let md5Dst = md5(fileAsBuffer(options.output));
|
||||
if (!exists(options.output) || md5Src !== md5Dst) {
|
||||
write(options.output, cached);
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
options.debug && logger.info('Compile file ' + file, eOptions);
|
||||
let content = await Engine.render(options.source, options.variables);
|
||||
if (_options.onCompiled) {
|
||||
content = await _options.onCompiled(options.source, output, content);
|
||||
}
|
||||
if (osr_cache && _options.cache !== false) {
|
||||
options.debug && logger.info('Write output to cache', output);
|
||||
await set_cached(options.source, eOptions, _options.module || MODULE_NAME, content);
|
||||
}
|
||||
let dst = path.resolve(resolve(output, false, options.variables));
|
||||
_options.debug && logger.info('Write output to: ', dst);
|
||||
write(dst, content);
|
||||
if (_options.onCompileDone) {
|
||||
await _options.onCompileDone(options.source, dst, options, content);
|
||||
}
|
||||
return content;
|
||||
};
|
||||
const watch = async (src, options) => {
|
||||
src = path.resolve(src);
|
||||
const watcher = chokidar.watch(`${src}`, {
|
||||
ignored: /(^|[\/\\])\../,
|
||||
persistent: true
|
||||
});
|
||||
watcher.on('change', async (path) => {
|
||||
await createContent(path, options);
|
||||
});
|
||||
return watcher;
|
||||
};
|
||||
const compileAll = async (files, options) => {
|
||||
return await BPromise.resolve(files).map((f) => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
createContent(f, options).then(() => resolve(true));
|
||||
}, 50);
|
||||
});
|
||||
}, { concurrency: 1 });
|
||||
};
|
||||
const compileAllEx = async (files, options) => {
|
||||
return await BPromise.resolve(files).map((f) => {
|
||||
return createContent(f, options);
|
||||
}, { concurrency: 1 });
|
||||
};
|
||||
//# sourceMappingURL=commons.js.map
|
||||
1
packages/discourse-legacy/dist/lib/sync/commons.js.map
vendored
Normal file
1
packages/discourse-legacy/dist/lib/sync/commons.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
4
packages/discourse-legacy/dist/lib/sync/component.d.ts
vendored
Normal file
4
packages/discourse-legacy/dist/lib/sync/component.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
export declare const createPost: (discourse: Discourser, options: IOptionsSync, content: any) => Promise<boolean>;
|
||||
export declare const updatePost: (discourse: Discourser, options: IOptionsSync, topic_id: any, content: any) => Promise<boolean>;
|
||||
export declare const syncComponent: (options: IOptionsSync) => Promise<void>;
|
||||
export declare const sync: (options: IOptionsSync) => Promise<void>;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user