From 4664d9fe0550ea1a0faf1f2fd86c359dde99c1fc Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Mon, 24 Apr 2023 16:29:04 -0400 Subject: [PATCH] Removed XMLResponseGenerator class in favor of Mongoose Schema methods --- src/models/community.ts | 13 + src/models/post.ts | 66 ++++ src/services/api/routes/communities.ts | 63 +++- src/services/api/routes/people.ts | 49 ++- src/services/api/routes/posts.ts | 47 ++- src/services/api/routes/topics.ts | 63 +++- src/types/mongoose/community.ts | 9 +- .../post-to-json-options.ts} | 2 +- src/types/mongoose/post.ts | 3 + src/types/mongoose/settings.ts | 1 + src/util/xmlResponseGenerator.ts | 282 ------------------ 11 files changed, 272 insertions(+), 326 deletions(-) rename src/types/{common/xml-response-generator-options.ts => mongoose/post-to-json-options.ts} (67%) delete mode 100644 src/util/xmlResponseGenerator.ts diff --git a/src/models/community.ts b/src/models/community.ts index e794703..8d853f4 100644 --- a/src/models/community.ts +++ b/src/models/community.ts @@ -93,4 +93,17 @@ CommunitySchema.method('downFollower', async function downFollower(): Promise { + return { + community_id: this.community_id, + name: this.name, + description: this.description, + icon: '', + icon_3ds: '', + pid: '', + app_data: this.app_data, + is_user_community: '0' + }; +}); + export const Community: CommunityModel = model('Community', CommunitySchema); \ No newline at end of file diff --git a/src/models/post.ts b/src/models/post.ts index 5165b1f..d4c8728 100644 --- a/src/models/post.ts +++ b/src/models/post.ts @@ -1,6 +1,9 @@ import crypto from 'node:crypto'; +import moment from 'moment'; import { Schema, model } from 'mongoose'; import { HydratedPostDocument, IPost, IPostMethods, PostModel } from '@/types/mongoose/post'; +import { HydratedCommunityDocument } from '@/types/mongoose/community'; +import { PostToJSONOptions } from '@/types/mongoose/post-to-json-options'; const PostSchema = new Schema({ id: String, @@ -129,6 +132,69 @@ PostSchema.method('generatePostUID', async function generatePostUID(length: numb } }); +PostSchema.method('json', function json(options: PostToJSONOptions, community?: HydratedCommunityDocument): Record { + const json: Record = { + body: this.body ? this.body.replace(/[^A-Za-z\d\s-_!@#$%^&*(){}+=,.<>/?;:'"[\]]/g, '').replace(/[\n\r]+/gm, '') : '', + country_id: this.country_id ? this.country_id : 254, + created_at: moment(this.created_at).format('YYYY-MM-DD HH:MM:SS'), + feeling_id: this.feeling_id, + id: this.id, + is_autopost: this.is_autopost, + is_community_private_autopost: this.is_community_private_autopost, + is_spoiler: this.is_spoiler, + is_app_jumpable: this.is_app_jumpable, + empathy_count: this.empathy_count, + language_id: this.language_id, + number: '0', + pid: this.pid, + platform_id: this.platform_id, + region_id: this.region_id, + reply_count: this.reply_count, + screen_name: this.screen_name, + title_id: this.title_id + }; + + if (this.app_data && options.app_data) { + json.app_data = this.app_data.replace(/[^A-Za-z0-9+/=]/g, '').replace(/[\n\r]+/gm, '').trim(); + } + + if (options.topics && community) { + json.community_id = community.community_id; + } else { + json.community_id = this.community_id; + } + + if (options.with_mii) { + json.mii = this.mii.replace(/[^A-Za-z0-9+/=]/g, '').replace(/[\n\r]+/gm, '').trim(); + json.mii_face_url = this.mii_face_url; + } + + if (this.painting) { + json.painting = { + format: 'tga', + content: this.painting.replace(/[\n\r]+/gm, '').trim(), + size: this.painting.length, + url: `https://pretendo-cdn.b-cdn.net/paintings/${this.pid}/${this.id}.png` + }; + } + + if (this.screenshot && this.screenshot_length) { + json.screenshot = { + size: this.screenshot_length, + url: `https://pretendo-cdn.b-cdn.net/screenshots/${this.pid}/${this.id}.jpg` + }; + } + + if (this.topic_tag && options.topic_tag) { + json.topic_tag = { + name: this.topic_tag, + title_id: this.title_id + }; + } + + return json; +}); + PostSchema.pre('save', async function(next) { if (!this.id) { await this.generatePostUID(21); diff --git a/src/services/api/routes/communities.ts b/src/services/api/routes/communities.ts index 59648f7..4e82410 100644 --- a/src/services/api/routes/communities.ts +++ b/src/services/api/routes/communities.ts @@ -1,4 +1,5 @@ import express from 'express'; +import xmlbuilder from 'xmlbuilder'; import multer from 'multer'; import { z } from 'zod'; import { @@ -9,12 +10,10 @@ import { getUserContent, getCommunityByTitleIDs } from '@/database'; -import comPostGen from '@/util/xmlResponseGenerator'; import { getValueFromQueryString } from '@/util'; import { LOG_WARN } from '@/logger'; import { Community } from '@/models/community'; import { Post } from '@/models/post'; -import { XMLResponseGeneratorOptions } from '@/types/common/xml-response-generator-options'; import { CreateNewCommunityBody } from '@/types/common/create-new-community-body'; import { HydratedCommunityDocument } from '@/types/mongoose/community'; import { CommunityPostsQuery } from '@/types/mongoose/community-posts-query'; @@ -34,18 +33,31 @@ const router: express.Router = express.Router(); router.get('/', async function (request: express.Request, response: express.Response): Promise { response.type('application/xml'); - const community: HydratedCommunityDocument | null = await getCommunityByTitleID(request.paramPack.title_id); - if (!community) { + const parentCommunity: HydratedCommunityDocument | null = await getCommunityByTitleID(request.paramPack.title_id); + if (!parentCommunity) { response.sendStatus(404); return; } - const subCommunities: HydratedCommunityDocument[] = await getSubCommunities(community.olive_community_id); - subCommunities.unshift(community); + const communities: HydratedCommunityDocument[] = await getSubCommunities(parentCommunity.olive_community_id); + communities.unshift(parentCommunity); - const communities: string = await comPostGen.Communities(subCommunities); + const json: Record = { + result: { + has_error: '0', + version: '1', + request_name: 'communities', + communities: [] + } + }; - response.send(communities); + for (const community of communities) { + json.result.communities.push({ + community: community.json() + }); + } + + response.send(xmlbuilder.create(json).end({ pretty: true, allowEmpty: true })); }); router.get('/popular', async function (_request: express.Request, response: express.Response): Promise { @@ -142,15 +154,27 @@ router.get('/:appID/posts', async function (request: express.Request, response: posts = await Post.find(query).sort({ created_at: -1}).limit(limit); } - /* Build formatted response and send it off. */ - const options: XMLResponseGeneratorOptions = { - name: 'posts', - with_mii: withMii === '1', - app_data: true, - topic_tag: true + const json: Record = { + has_error: 0, + version: 1, + request_name: 'posts', + topic: { + community_id: community.community_id + }, + posts: [] }; - response.send(await comPostGen.PostsResponse(posts, community, options)); + for (const post of posts) { + json.result.posts.push({ + post: post.json({ + with_mii: withMii === '1', + app_data: true, + topic_tag: true + }) + }); + } + + response.send(xmlbuilder.create(json).end({ pretty: true, allowEmpty: true })); }); // Handler for POST on '/v1/communities' @@ -188,7 +212,14 @@ router.post('/', multer().none(), async function (request: express.Request, resp app_data: request.body.app_data.replace(/[^A-Za-z0-9+/=\s]/g, ''), }); - response.send(await comPostGen.Community(community)); + response.send(xmlbuilder.create({ + result: { + has_error: '0', + version: '1', + request_name: 'community', + community: community.json() + } + }).end({ pretty: true, allowEmpty: true })); }); export default router; diff --git a/src/services/api/routes/people.ts b/src/services/api/routes/people.ts index 6aac0f1..4b650fd 100644 --- a/src/services/api/routes/people.ts +++ b/src/services/api/routes/people.ts @@ -1,9 +1,9 @@ import express from 'express'; -import xmlGenerator from '@/util/xmlResponseGenerator'; +import xmlbuilder from 'xmlbuilder'; +import moment from 'moment'; import { getUserContent, getFollowedUsers } from '@/database'; import { getValueFromQueryString, getUserFriendPIDs } from '@/util'; import { Post } from '@/models/post'; -import { XMLResponseGeneratorOptions } from '@/types/common/xml-response-generator-options'; import { HydratedContentDocument } from '@/types/mongoose/content'; import { CommunityPostsQuery } from '@/types/mongoose/community-posts-query'; import { HydratedPostDocument } from '@/types/mongoose/post'; @@ -69,14 +69,30 @@ router.get('/', async function (request: express.Request, response: express.Resp posts = await Post.find(query).sort({ created_at: -1}).limit(limit); } - /* Build formatted response and send it off. */ - const options: XMLResponseGeneratorOptions = { - name: 'posts', - with_mii: withMii === '1', - topic_tag: true + const json: Record = { + has_error: 0, + version: 1, + expire: moment().add(1, 'days').format('YYYY-MM-DD HH:MM:SS'), + request_name: 'posts', + people: [] }; - response.send(await xmlGenerator.People(posts, options)); + for (const post of posts) { + json.result.people.push({ + person: { + posts: [ + { + post: post.json({ + with_mii: withMii === '1', + topic_tag: true + }) + } + ] + } + }); + } + + response.send(xmlbuilder.create(json).end({ pretty: true, allowEmpty: true })); }); router.get('/:pid/following', async function (request: express.Request, response: express.Response): Promise { @@ -98,7 +114,22 @@ router.get('/:pid/following', async function (request: express.Request, response const people: HydratedSettingsDocument[] = await getFollowedUsers(userContent); - response.send(await xmlGenerator.Following(people)); + const json: Record = { + result: { + has_error: '0', + version: '1', + request_name: 'user_infos', + people: [] + } + }; + + for (const person of people) { + json.result.people.push({ + person: person.json() + }); + } + + response.send(xmlbuilder.create(json).end({ pretty: true, allowEmpty: true })); }); export default router; \ No newline at end of file diff --git a/src/services/api/routes/posts.ts b/src/services/api/routes/posts.ts index c7674e6..c8e6c2c 100644 --- a/src/services/api/routes/posts.ts +++ b/src/services/api/routes/posts.ts @@ -1,7 +1,7 @@ import express from 'express'; import multer from 'multer'; import xml from 'object-to-xml'; -import communityPostGen from '@/util/xmlResponseGenerator'; +import xmlbuilder from 'xmlbuilder'; import { z } from 'zod'; import { processPainting, uploadCDNAsset, getValueFromQueryString } from '@/util'; import { @@ -17,7 +17,6 @@ import { import { LOG_WARN } from '@/logger'; import { Post } from '@/models/post'; import { Community } from '@/models/community'; -import { XMLResponseGeneratorOptions } from '@/types/common/xml-response-generator-options'; import { HydratedPostDocument, IPost } from '@/types/mongoose/post'; import { HydratedContentDocument } from '@/types/mongoose/content'; import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; @@ -138,13 +137,23 @@ router.get('/:post_id/replies', async function (request: express.Request, respon return; } - const options: XMLResponseGeneratorOptions = { - name: 'replies', - with_mii: request.query.with_mii as string === '1', - topic_tag: true + const json: Record = { + has_error: 0, + version: 1, + request_name: 'replies', + posts: [] }; - response.send(await communityPostGen.RepliesResponse(posts, options)); + for (const post of posts) { + json.result.posts.push({ + post: post.json({ + with_mii: request.query.with_mii as string === '1', + topic_tag: true + }) + }); + } + + response.send(xmlbuilder.create(json).end({ pretty: true, allowEmpty: true })); }); router.get('/', async function (request: express.Request, response: express.Response): Promise { @@ -178,9 +187,19 @@ router.get('/', async function (request: express.Request, response: express.Resp message: 'Not Found' } })); - } else { - response.send(await communityPostGen.QueryResponse(post)); + return; } + + response.send(xmlbuilder.create({ + result: { + has_error: '0', + version: '1', + request_name: 'posts.search', + posts: { + post: post.json({ with_mii: true }) + } + } + }).end({ pretty: true, allowEmpty: true })); }); async function newPost(request: express.Request, response: express.Response): Promise { @@ -364,7 +383,15 @@ async function newPost(request: express.Request, response: express.Response): Pr parentPost.save(); } - response.send(await communityPostGen.SinglePostResponse(post)); + response.send(xmlbuilder.create({ + result: { + has_error: '0', + version: '1', + post: { + post: post.json({ with_mii: true }) + } + } + }).end({ pretty: true, allowEmpty: true })); } export default router; \ No newline at end of file diff --git a/src/services/api/routes/topics.ts b/src/services/api/routes/topics.ts index 658a60d..e975961 100644 --- a/src/services/api/routes/topics.ts +++ b/src/services/api/routes/topics.ts @@ -1,9 +1,10 @@ import express from 'express'; import memoize from 'memoizee'; -import { getPNID, getEndpoint } from '@/database'; +import moment from 'moment'; +import xmlbuilder from 'xmlbuilder'; +import { getPNID, getEndpoint, getPostsBytitleID } from '@/database'; import { Post } from '@/models/post'; import { Community } from '@/models/community'; -import comPostGen from '@/util/xmlResponseGenerator'; import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; import { HydratedEndpointDocument } from '@/types/mongoose/endpoint'; import { HydratedCommunityDocument } from '@/types/mongoose/community'; @@ -12,7 +13,10 @@ import { HydratedPostDocument } from '@/types/mongoose/post'; const router: express.Router = express.Router(); // TODO - Need to add types to memoize in @/types/memoize.d.ts -const memoized = memoize(comPostGen.topics, { async: true, maxAge: 1000 * 60 * 60 }); +const memoizedGenerateTopicsXML = memoize(generateTopicsXML, { + async: true, + maxAge: 1000 * 60 * 60 // * cache for 1 hour +}); /* GET post titles. */ router.get('/', async function (request: express.Request, response: express.Response): Promise { @@ -39,9 +43,60 @@ router.get('/', async function (request: express.Request, response: express.Resp return; } - response.send(await memoized(communities)); + response.send(await memoizedGenerateTopicsXML(communities)); }); +async function generateTopicsXML(communities: HydratedCommunityDocument[]): Promise { + const json: Record = { + has_error: 0, + version: 1, + expire: moment().add(1, 'days').format('YYYY-MM-DD HH:MM:SS'), + request_name: 'topics', + topics: [] + }; + + for (const community of communities) { + const topic: Record = { + topic: { + empathy_count: community.empathy_count, + has_shop_page: community.has_shop_page, + icon: community.icon, + title_ids: [], + title_id: community.title_id[0], + community_id: community.community_id, + is_recommended: community.is_recommended, + name: community.name, + people: [] + } + }; + + community.title_id.forEach(function (title_id: string) { + if (title_id !== '') { + topic.topic.title_ids.push({ title_id }); + } + }); + + const posts: HydratedPostDocument[] = await getPostsBytitleID(community.title_id, 30); + + for (const post of posts) { + topic.topic.people.push({ + person: { + posts: [ + { + post: post.json({ + with_mii: true, + topics: true + }) + } + ] + } + }); + } + } + + return xmlbuilder.create(json).end({ pretty: true, allowEmpty: true }); +} + async function calculateMostPopularCommunities(hours: number, limit: number): Promise { const now: Date = new Date(); const last24Hours: Date = new Date(now.getTime() - hours * 60 * 60 * 1000); diff --git a/src/types/mongoose/community.ts b/src/types/mongoose/community.ts index c08560c..40f37cd 100644 --- a/src/types/mongoose/community.ts +++ b/src/types/mongoose/community.ts @@ -30,10 +30,11 @@ export interface ICommunity { } export interface ICommunityMethods { - upEmpathy(): Promise - downEmpathy(): Promise - upFollower(): Promise - downFollower(): Promise + upEmpathy(): Promise; + downEmpathy(): Promise; + upFollower(): Promise; + downFollower(): Promise; + json(): Record; } interface ICommunityQueryHelpers {} diff --git a/src/types/common/xml-response-generator-options.ts b/src/types/mongoose/post-to-json-options.ts similarity index 67% rename from src/types/common/xml-response-generator-options.ts rename to src/types/mongoose/post-to-json-options.ts index 7a368c9..209b03d 100644 --- a/src/types/common/xml-response-generator-options.ts +++ b/src/types/mongoose/post-to-json-options.ts @@ -1,4 +1,4 @@ -export interface XMLResponseGeneratorOptions { +export interface PostToJSONOptions { name?: string; with_mii: boolean; app_data?: boolean; diff --git a/src/types/mongoose/post.ts b/src/types/mongoose/post.ts index 42734c9..0b5c286 100644 --- a/src/types/mongoose/post.ts +++ b/src/types/mongoose/post.ts @@ -1,4 +1,6 @@ import { Model, Types, HydratedDocument } from 'mongoose'; +import { HydratedCommunityDocument } from '@/types/mongoose/community'; +import { PostToJSONOptions } from '@/types/mongoose/post-to-json-options'; export interface IPost { id: string; @@ -42,6 +44,7 @@ export interface IPostMethods { remove(reason: string): Promise; unRemove(reason: string): Promise; generatePostUID(length: number): Promise; + json(options: PostToJSONOptions, community?: HydratedCommunityDocument): Record; } interface IPostQueryHelpers {} diff --git a/src/types/mongoose/settings.ts b/src/types/mongoose/settings.ts index 052954f..14ffb12 100644 --- a/src/types/mongoose/settings.ts +++ b/src/types/mongoose/settings.ts @@ -26,6 +26,7 @@ export interface ISettingsMethods { relationshipVisible(active: boolean): Promise; countryVisible(active: boolean): Promise; favCommunityVisible(active: boolean): Promise; + json(): Record; } interface ISettingsQueryHelpers {} diff --git a/src/util/xmlResponseGenerator.ts b/src/util/xmlResponseGenerator.ts deleted file mode 100644 index 1ddb5ec..0000000 --- a/src/util/xmlResponseGenerator.ts +++ /dev/null @@ -1,282 +0,0 @@ -import xmlbuilder from 'xmlbuilder'; -import moment from 'moment'; -import { getPostsBytitleID } from '@/database'; -import { XMLResponseGeneratorOptions } from '@/types/common/xml-response-generator-options'; -import { HydratedPostDocument } from '@/types/mongoose/post'; -import { HydratedCommunityDocument } from '@/types/mongoose/community'; -import { HydratedSettingsDocument } from '@/types/mongoose/settings'; - -class XmlResponseGenerator { - static RepliesResponse(posts: HydratedPostDocument[], options: XMLResponseGeneratorOptions): string { - const xml: xmlbuilder.XMLElement = xmlbuilder.create('result', { encoding: 'UTF-8' }) - .e('has_error', '0').up() - .e('version', '1').up() - .e('request_name', 'replies').up() - .e('posts'); - - for (const post of posts) { - postObj(xml, post, options, null); - } - - return xml.up().end({ pretty: true, allowEmpty: true }); - } - - static PostsResponse(posts: HydratedPostDocument[], community: HydratedCommunityDocument, options: XMLResponseGeneratorOptions): string { - const xml: xmlbuilder.XMLElement = xmlbuilder.create('result', { encoding: 'UTF-8' }) - .e('has_error', '0').up() - .e('version', '1').up() - .e('request_name', options.name).up() - .e('topic') - .e('community_id', community.community_id).up() - .up() - .e('posts'); - - for (const post of posts) { - postObj(xml, post, options, null); - } - - return xml.up().end({ pretty: true, allowEmpty: true }); - } - - static EmptyResponse(): string { - const xml: xmlbuilder.XMLElement = xmlbuilder.create('result', { encoding: 'UTF-8' }) - .e('has_error', '0').up() - .e('version', '1').up(); - - return xml.end({ pretty: true, allowEmpty: true }); - } - - static Communities(communities: HydratedCommunityDocument[]): string { - let xml: xmlbuilder.XMLElement = xmlbuilder.create('result', { encoding: 'UTF-8' }) - .e('has_error', '0').up() - .e('version', '1').up() - .e('request_name', 'communities').up() - .e('communities'); - - for (const community of communities) { - xml = xml.e('community') - .e('community_id', community.community_id).up() - .e('name', community.name).up() - .e('description', community.description).up() - .e('icon').up() - .e('icon_3ds').up() - .e('pid').up() - .e('app_data', community.app_data).up() - .e('is_user_community', 0).up() - .up(); - } - - return xml.up().end({ pretty: true, allowEmpty: true }); - } - - static Community(community: HydratedCommunityDocument): string { - const xml: xmlbuilder.XMLElement = xmlbuilder.create('result', { encoding: 'UTF-8' }) - .e('has_error', '0').up() - .e('version', '1').up() - .e('request_name', 'community').up() - .e('community') - .e('community_id', community.community_id).up() - .e('name', community.name).up() - .e('description', community.description).up() - .e('icon').up() - .e('icon_3ds').up() - .e('pid').up() - .e('app_data', community.app_data).up() - .e('is_user_community', 0) - .up(); - - return xml.up().end({ pretty: true, allowEmpty: true }); - } - - static SinglePostResponse(post: HydratedPostDocument): string { - const xml: xmlbuilder.XMLElement = xmlbuilder.create('result', { encoding: 'UTF-8' }) - .e('has_error', '0').up() - .e('version', '1').up() - .e('post'); - - const options: XMLResponseGeneratorOptions = { - with_mii: true - }; - - postObj(xml, post, options, null); - - return xml.up().end({ pretty: true, allowEmpty: true }); - } - - static QueryResponse(post: HydratedPostDocument): string { - const xml: xmlbuilder.XMLElement = xmlbuilder.create('result', { encoding: 'UTF-8' }) - .e('has_error', '0').up() - .e('version', '1').up() - .e('request_name', 'posts.search').up() - .e('posts'); - - const options: XMLResponseGeneratorOptions = { - with_mii: true - }; - - postObj(xml, post, options, null); - - return xml.up().end({ pretty: true, allowEmpty: true }); - } - - /** - * Generate response to /v1/topics - * @param communities - * @returns xml - */ - static async topics(communities: HydratedCommunityDocument[]): Promise { - const expirationDate = moment().add(1, 'days'); - - let xml: xmlbuilder.XMLElement = xmlbuilder.create('result', { encoding: 'UTF-8' }) - .e('has_error', '0').up() - .e('version', '1').up() - .e('request_name', 'topics').up() - .e('expire', expirationDate.format('YYYY-MM-DD HH:MM:SS')).up() - .e('topics'); - - for (const community of communities) { - const posts = await getPostsBytitleID(community.title_id, 30); - - xml = xml.e('topic') - .e('empathy_count', community.empathy_count).up() - .e('has_shop_page', community.has_shop_page).up() - .e('icon', community.icon).up() - .e('title_ids'); - - community.title_id.forEach(function (title_id: string) { - if (title_id !== '') { - xml = xml.e('title_id', title_id).up(); - } - }); - - xml = xml.up() - .e('title_id', community.title_id[0]).up() - .e('community_id', community.community_id).up() - .e('is_recommended', community.is_recommended).up() - .e('name', community.name).up() - .e('people'); - - for (const post of posts) { - xml = xml.e('person').e('posts'); - - const options: XMLResponseGeneratorOptions = { with_mii: true, - app_data: false, - topic_tag: false, - topics: true - }; - - postObj(xml, post, options, community); - xml = xml.up().up(); - } - - xml = xml.up().up(); - } - - return xml.end({ pretty: false, allowEmpty: true }); - } - - static Following(people: HydratedSettingsDocument[]): string { - let xml: xmlbuilder.XMLElement = xmlbuilder.create('result', { encoding: 'UTF-8' }) - .e('has_error', '0').up() - .e('version', '1').up() - .e('request_name', 'user_infos').up() - .e('people'); - - for (const person of people) { - xml = xml.e('person') - .e('pid', person.pid).up() - .e('screen_name', person.screen_name).up() - .up(); - } - - return xml.up().end({ pretty: true, allowEmpty: true }); - } - - static People(posts: HydratedPostDocument[], options: XMLResponseGeneratorOptions): string { - const expirationDate = moment().add(1, 'days'); - - let xml: xmlbuilder.XMLElement = xmlbuilder.create('result', { encoding: 'UTF-8' }) - .e('has_error', '0').up() - .e('version', '1').up() - .e('expire', expirationDate.format('YYYY-MM-DD HH:MM:SS')).up() - .e('request_name', options.name).up() - .e('people'); - - for (const post of posts) { - xml = xml.e('person').e('posts'); - - postObj(xml, post, options, null); - - xml = xml.up().up(); - } - - return xml.up().end({ pretty: true, allowEmpty: true }); - } -} - -function postObj(xml: xmlbuilder.XMLElement, post: HydratedPostDocument, options: XMLResponseGeneratorOptions, community: HydratedCommunityDocument | null): void { - xml = xml.e('post'); - - if (post.app_data && options.app_data) { - xml.e('app_data', post.app_data.replace(/[^A-Za-z0-9+/=]/g, '').replace(/[\n\r]+/gm, '').trim()).up(); - } - - xml.e('body', post.body ? post.body.replace(/[^A-Za-z\d\s-_!@#$%^&*(){}+=,.<>/?;:'"[\]]/g, '').replace(/[\n\r]+/gm, '') : '').up(); - - if (options.topics && community) { - xml.e('community_id', community.community_id).up(); - } else { - xml.e('community_id', post.community_id).up(); - } - - xml.e('country_id', post.country_id ? post.country_id : 254).up() - .e('created_at', moment(post.created_at).format('YYYY-MM-DD HH:MM:SS')).up() - .e('feeling_id', post.feeling_id).up() - .e('id', post.id).up() - .e('is_autopost', post.is_autopost).up() - .e('is_community_private_autopost', post.is_community_private_autopost).up() - .e('is_spoiler', post.is_spoiler).up() - .e('is_app_jumpable', post.is_app_jumpable).up() - .e('empathy_count', post.empathy_count).up() - .e('language_id', post.language_id).up(); - - if (options.with_mii) { - xml.e('mii', post.mii.replace(/[^A-Za-z0-9+/=]/g, '').replace(/[\n\r]+/gm, '').trim()).up() - .e('mii_face_url', post.mii_face_url).up(); - } - - xml.e('number', '0').up(); - - if (post.painting) { - xml.e('painting') - .e('format', 'tga').up() - .e('content', post.painting.replace(/[\n\r]+/gm, '').trim()).up() - .e('size', post.painting.length).up() - .e('url', `https://pretendo-cdn.b-cdn.net/paintings/${post.pid}/${post.id}.png`).up() - .up(); - } - - xml.e('pid', post.pid).up() - .e('platform_id', post.platform_id).up() - .e('region_id', post.region_id).up() - .e('reply_count', post.reply_count).up() - .e('screen_name', post.screen_name).up(); - - if (post.screenshot && post.screenshot_length) { - xml.e('screenshot') - .e('size', post.screenshot_length).up() - .e('url', `https://pretendo-cdn.b-cdn.net/screenshots/${post.pid}/${post.id}.jpg`).up() - .up(); - } - - if (post.topic_tag && options.topic_tag) { - xml.e('topic_tag') - .e('name', post.topic_tag).up() - .e('title_id', post.title_id).up() - .up(); - } - - xml.e('title_id', post.title_id).up().up(); -} - -export default XmlResponseGenerator;