import _ from 'lodash'; import moment from 'moment'; // import Pageres from 'pageres'; // import nconf from 'nconf'; // import got from 'got'; import md from 'habitica-markdown'; import csvStringify from '../../libs/csvStringify'; import { marshallUserData } from '../../libs/xmlMarshaller'; import * as Tasks from '../../models/task'; import * as inboxLib from '../../libs/inbox'; // import { model as User } from '../../models/user'; import { authWithSession } from '../../middlewares/auth'; const api = {}; /** * @apiDefine DataExport Data Export * These routes allow you to download backups of your data. * * **Note:** They are intended to be used on the website only and as such are part * of the private API and may change at any time. */ /** * @api {get} /export/history.csv Export user tasks history in CSV format * @apiDescription History is only available for habits and dailies so todos and rewards won't be included. Can only be used on [https://habitica.com](https://habitica.com). * @apiName ExportUserHistory * @apiGroup DataExport * * @apiSuccess {CSV} File A csv file of your task history. * * @apiSuccessExample {csv} history.csv * Task Name,Task ID,Task Type,Date,Value * Be Awesome,e826ddfa-dc2e-445f-a06c-64d3881982ea,habit,2016-06-02 13:26:05,1 * Be Awesome,e826ddfa-dc2e-445f-a06c-64d3881982ea,habit,2016-06-03 05:06:55,1.026657310999762 * ... */ api.exportUserHistory = { method: 'GET', url: '/export/history.csv', middlewares: [authWithSession], async handler (req, res) { const { user } = res.locals; const tasks = await Tasks.Task.find({ userId: user._id, type: { $in: ['habit', 'daily'] }, }).exec(); const output = [ ['Task Name', 'Task ID', 'Task Type', 'Date', 'Value'], ]; tasks.forEach(task => { task.history.forEach(history => { output.push([ task.text, task._id, task.type, moment(history.date).format('YYYY-MM-DD HH:mm:ss'), history.value, ]); }); }); res.set({ 'Content-Type': 'text/csv', 'Content-disposition': 'attachment; filename=habitica-tasks-history.csv', }); const csvRes = await csvStringify(output); res.status(200).send(csvRes); }, }; // Convert user to json and attach tasks divided by type and inbox messages // at user.tasks[`${taskType}s`] (user.tasks.{dailys/habits/...}) async function _getUserDataForExport (user) { const userData = user.toJSON(); userData.tasks = {}; userData.inbox.messages = {}; const [tasks, messages] = await Promise.all([ Tasks.Task.find({ userId: user._id, }).exec(), inboxLib.getUserInbox(user, { asArray: false }), ]); userData.inbox.messages = messages; _(tasks) .map(task => task.toJSON()) .groupBy(task => task.type) .forEach((tasksPerType, taskType) => { userData.tasks[`${taskType}s`] = tasksPerType; }); return userData; } /** * @api {get} /export/userdata.json Export user data in JSON format * @apiName ExportUserDataJson * @apiGroup DataExport * * @apiSuccess {JSON} File A JSON file of the user object and tasks. */ api.exportUserDataJson = { method: 'GET', url: '/export/userdata.json', middlewares: [authWithSession], async handler (req, res) { const userData = await _getUserDataForExport(res.locals.user); res.set({ 'Content-Type': 'application/json', 'Content-disposition': 'attachment; filename=habitica-user-data.json', }); const jsonRes = JSON.stringify(userData); res.status(200).send(jsonRes); }, }; /** * @api {get} /export/userdata.xml Export user data in XML format * @apiName ExportUserDataXml * @apiDescription This XML export feature is not currently working (https://github.com/HabitRPG/habitica/issues/10100). * @apiGroup DataExport * * @apiSuccess {XML} File An xml file of the user object. */ api.exportUserDataXml = { method: 'GET', url: '/export/userdata.xml', middlewares: [authWithSession], async handler (req, res) { const userData = await _getUserDataForExport(res.locals.user); const xmlData = marshallUserData(userData); res.set({ 'Content-Type': 'text/xml', 'Content-disposition': 'attachment; filename=habitica-user-data.xml', }); res.status(200).send(xmlData); }, }; /** * @api {get} /export/inbox.html Export user private messages as HTML document * @apiName ExportUserPrivateMessages * * @apiGroup DataExport * * @apiSuccess {HTML} File An html page of the user's private messages. */ api.exportUserPrivateMessages = { method: 'GET', url: '/export/inbox.html', middlewares: [authWithSession], async handler (req, res) { const { user } = res.locals; const timezoneUtcOffset = user.getUtcOffset(); const dateFormat = user.preferences.dateFormat.toUpperCase(); const TO = res.t('to'); const FROM = res.t('from'); const inbox = await inboxLib.getUserInbox(user); let messages = '
'; inbox.forEach((message, index) => { const recipientLabel = message.sent ? TO : FROM; const messageUser = message.user; const timestamp = moment.utc(message.timestamp).utcOffset(timezoneUtcOffset).format(`${dateFormat} HH:mm:ss`); const text = md.render(message.text); const pageIndex = `(${index + 1}/${inbox.length})`; messages += `
${recipientLabel} ${messageUser} ${timestamp}
${pageIndex}
${text}