Skip to content

Commit

Permalink
feat: added support for create_time and update_time metadata paramete…
Browse files Browse the repository at this point in the history
…rs per #94 (#114)

* feat: added support for create_time and update_time metadata parameters per #94

* fix: lint and fix missing parts

* build

---------

Co-authored-by: Pionxzh <[email protected]>
  • Loading branch information
alex-rosenberg35 and pionxzh authored Jun 7, 2023
1 parent 927ca37 commit 5df4ba6
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 20 deletions.
62 changes: 52 additions & 10 deletions dist/chatgpt.user.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,7 @@ var __publicField = (obj, key, value) => {
var _a, _b, _c, _d, _e, _f, _g;
const title2 = conversation.title || "ChatGPT Conversation";
const createTime = conversation.create_time;
const updateTime = conversation.update_time;
const modelSlug = ((_c = (_b = (_a = Object.values(conversation.mapping).find((node2) => {
var _a2, _b2;
return (_b2 = (_a2 = node2.message) == null ? void 0 : _a2.metadata) == null ? void 0 : _b2.model_slug;
Expand Down Expand Up @@ -1300,6 +1301,7 @@ var __publicField = (obj, key, value) => {
modelSlug,
model,
createTime,
updateTime,
conversationNodes: result
};
}
Expand Down Expand Up @@ -8115,6 +8117,11 @@ var __publicField = (obj, key, value) => {
function getColorScheme() {
return document.documentElement.style.getPropertyValue("color-scheme");
}
function unixTimestampToISOString(timestamp2) {
if (!timestamp2)
return "";
return new Date(timestamp2 * 1e3).toISOString();
}
function downloadFile(filename, type, content2) {
const blob = content2 instanceof Blob ? content2 : new Blob([content2], {
type
Expand All @@ -8138,10 +8145,14 @@ var __publicField = (obj, key, value) => {
function getFileNameWithFormat(format, ext, {
title: title2 = document.title,
// chatId will be empty when exporting all conversations
chatId = ""
chatId = "",
createTime = Date.now(),
updateTime = Date.now()
} = {}) {
const _title = sanitizeFilename(title2).replace(/\s+/g, "_");
return format.replace("{title}", _title).replace("{date}", dateStr()).replace("{timestamp}", timestamp()).replace("{chat_id}", chatId).concat(`.${ext}`);
const _createTime = unixTimestampToISOString(createTime);
const _updateTime = unixTimestampToISOString(updateTime);
return format.replace("{title}", _title).replace("{date}", dateStr()).replace("{timestamp}", timestamp()).replace("{chat_id}", chatId).replace("{create_time}", _createTime).replace("{update_time}", _updateTime).concat(`.${ext}`);
}
class Schema {
/**
Expand Down Expand Up @@ -19247,7 +19258,9 @@ var __publicField = (obj, key, value) => {
const html2 = conversationToHtml(conversation, userAvatar, metaList);
const fileName = getFileNameWithFormat(fileNameFormat, "html", {
title: conversation.title,
chatId
chatId,
createTime: conversation.createTime,
updateTime: conversation.updateTime
});
downloadFile(fileName, "text/html", standardizeLineBreaks(html2));
return true;
Expand All @@ -19260,7 +19273,9 @@ var __publicField = (obj, key, value) => {
conversations.forEach((conversation) => {
let fileName = getFileNameWithFormat(fileNameFormat, "html", {
title: conversation.title,
chatId: conversation.id
chatId: conversation.id,
createTime: conversation.createTime,
updateTime: conversation.updateTime
});
if (filenameMap.has(fileName)) {
const count = filenameMap.get(fileName) ?? 1;
Expand Down Expand Up @@ -19327,6 +19342,8 @@ var __publicField = (obj, key, value) => {
title: title2,
model,
modelSlug,
createTime,
updateTime,
conversationNodes
} = conversation;
const conversationHtml = conversationNodes.map(({
Expand Down Expand Up @@ -19389,7 +19406,7 @@ var __publicField = (obj, key, value) => {
name,
value
}) => {
const val = value.replace("{title}", title2).replace("{date}", date).replace("{timestamp}", timestamp()).replace("{source}", source).replace("{model}", model).replace("{mode_name}", modelSlug);
const val = value.replace("{title}", title2).replace("{date}", date).replace("{timestamp}", timestamp()).replace("{source}", source).replace("{model}", model).replace("{mode_name}", modelSlug).replace("{create_time}", unixTimestampToISOString(createTime)).replace("{update_time}", unixTimestampToISOString(updateTime));
return [name, val];
})) ?? [];
const detailsHtml = _metaList.length > 0 ? `<details>
Expand Down Expand Up @@ -19569,7 +19586,9 @@ var __publicField = (obj, key, value) => {
}) => {
let fileName = getFileNameWithFormat(fileNameFormat, "json", {
title: conversation.title,
chatId: conversation.id
chatId: conversation.id,
createTime: conversation.createTime,
updateTime: conversation.updateTime
});
if (filenameMap.has(fileName)) {
const count = filenameMap.get(fileName) ?? 1;
Expand Down Expand Up @@ -19606,7 +19625,9 @@ var __publicField = (obj, key, value) => {
const markdown = conversationToMarkdown(conversation, metaList);
const fileName = getFileNameWithFormat(fileNameFormat, "md", {
title: conversation.title,
chatId
chatId,
createTime: conversation.createTime,
updateTime: conversation.updateTime
});
downloadFile(fileName, "text/markdown", standardizeLineBreaks(markdown));
return true;
Expand All @@ -19618,7 +19639,9 @@ var __publicField = (obj, key, value) => {
conversations.forEach((conversation) => {
let fileName = getFileNameWithFormat(fileNameFormat, "md", {
title: conversation.title,
chatId: conversation.id
chatId: conversation.id,
createTime: conversation.createTime,
updateTime: conversation.updateTime
});
if (filenameMap.has(fileName)) {
const count = filenameMap.get(fileName) ?? 1;
Expand Down Expand Up @@ -19685,14 +19708,16 @@ var __publicField = (obj, key, value) => {
title: title2,
model,
modelSlug,
createTime,
updateTime,
conversationNodes
} = conversation;
const source = `${baseUrl}/c/${id}`;
const _metaList = (metaList == null ? void 0 : metaList.filter((x2) => !!x2.name).map(({
name,
value
}) => {
const val = value.replace("{title}", title2).replace("{date}", dateStr()).replace("{timestamp}", timestamp()).replace("{source}", source).replace("{model}", model).replace("{modelSlug}", modelSlug);
const val = value.replace("{title}", title2).replace("{date}", dateStr()).replace("{timestamp}", timestamp()).replace("{source}", source).replace("{model}", model).replace("{model_name}", modelSlug).replace("{create_time}", unixTimestampToISOString(createTime)).replace("{update_time}", unixTimestampToISOString(updateTime));
return `${name}: ${val}`;
})) ?? [];
const frontMatter = _metaList.length > 0 ? `---
Expand Down Expand Up @@ -22452,9 +22477,14 @@ ${content2}`;
const timestamp$1 = timestamp();
const title2 = sanitizeFilename(_title).replace(/\s+/g, "_");
const chatId = getChatIdFromUrl() || "this-is-a-mock-chat-id";
const now = Date.now() / 1e3;
const createTime = now;
const updateTime = now;
const preview = getFileNameWithFormat(format, "{ext}", {
title: title2,
chatId
chatId,
createTime,
updateTime
});
const source = `${baseUrl}/${chatId}`;
return o$5($5d3850c4d0b4e6c7$export$be92b6f5f03c0fe9, {
Expand Down Expand Up @@ -22515,6 +22545,12 @@ ${content2}`;
}), ",", " ", o$5(Variable, {
name: "{chat_id}",
title: chatId
}), ",", " ", o$5(Variable, {
name: "{create_time}",
title: unixTimestampToISOString(createTime)
}), ",", " ", o$5(Variable, {
name: "{update_time}",
title: unixTimestampToISOString(updateTime)
})]
}), o$5("input", {
className: "Input mt-4",
Expand Down Expand Up @@ -22588,6 +22624,12 @@ ${content2}`;
}), ",", " ", o$5(Variable, {
name: "{model_name}",
title: "text-davinci-002-render-sha"
}), ",", " ", o$5(Variable, {
name: "{create_time}",
title: "2023-04-10T21:45:35.027Z"
}), ",", " ", o$5(Variable, {
name: "{update_time}",
title: "2023-04-10T21:45:35.027Z"
})]
}), exportMetaList.map((meta, i2) => o$5("div", {
className: "flex items-center mt-2",
Expand Down
3 changes: 3 additions & 0 deletions packages/userscript/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ export interface ConversationResult {
modelSlug: string
model: string
createTime: number
updateTime: number
conversationNodes: ConversationNode[]
}

Expand All @@ -230,6 +231,7 @@ const modelMapping: { [key in ModelSlug]: string } & { [key: string]: string } =
export function processConversation(conversation: ApiConversationWithId, conversationChoices: Array<number | null> = []): ConversationResult {
const title = conversation.title || 'ChatGPT Conversation'
const createTime = conversation.create_time
const updateTime = conversation.update_time
const modelSlug = Object.values(conversation.mapping).find(node => node.message?.metadata?.model_slug)?.message?.metadata?.model_slug || ''
let model = ''
if (modelSlug) {
Expand Down Expand Up @@ -318,6 +320,7 @@ export function processConversation(conversation: ApiConversationWithId, convers
modelSlug,
model,
createTime,
updateTime,
conversationNodes: result,
}
}
10 changes: 7 additions & 3 deletions packages/userscript/src/exporter/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { downloadFile, getFileNameWithFormat } from '../utils/download'
import { fromMarkdown, toHtml } from '../utils/markdown'
import { ScriptStorage } from '../utils/storage'
import { standardizeLineBreaks } from '../utils/text'
import { dateStr, getColorScheme, timestamp } from '../utils/utils'
import { dateStr, getColorScheme, timestamp, unixTimestampToISOString } from '../utils/utils'
import type { ApiConversationWithId, ConversationNodeMessage, ConversationResult } from '../api'
import type { ExportMeta } from '../ui/SettingContext'

Expand All @@ -26,7 +26,7 @@ export async function exportToHtml(fileNameFormat: string, metaList: ExportMeta[
const conversation = processConversation(rawConversation, conversationChoices)
const html = conversationToHtml(conversation, userAvatar, metaList)

const fileName = getFileNameWithFormat(fileNameFormat, 'html', { title: conversation.title, chatId })
const fileName = getFileNameWithFormat(fileNameFormat, 'html', { title: conversation.title, chatId, createTime: conversation.createTime, updateTime: conversation.updateTime })
downloadFile(fileName, 'text/html', standardizeLineBreaks(html))

return true
Expand All @@ -42,6 +42,8 @@ export async function exportAllToHtml(fileNameFormat: string, apiConversations:
let fileName = getFileNameWithFormat(fileNameFormat, 'html', {
title: conversation.title,
chatId: conversation.id,
createTime: conversation.createTime,
updateTime: conversation.updateTime,
})
if (filenameMap.has(fileName)) {
const count = filenameMap.get(fileName) ?? 1
Expand Down Expand Up @@ -111,7 +113,7 @@ const transformContent = (
}

function conversationToHtml(conversation: ConversationResult, avatar: string, metaList?: ExportMeta[]) {
const { id, title, model, modelSlug, conversationNodes } = conversation
const { id, title, model, modelSlug, createTime, updateTime, conversationNodes } = conversation

const conversationHtml = conversationNodes.map(({ message }) => {
if (!message || !message.content) return null
Expand Down Expand Up @@ -182,6 +184,8 @@ function conversationToHtml(conversation: ConversationResult, avatar: string, me
.replace('{source}', source)
.replace('{model}', model)
.replace('{mode_name}', modelSlug)
.replace('{create_time}', unixTimestampToISOString(createTime))
.replace('{update_time}', unixTimestampToISOString(updateTime))

return [name, val] as const
})
Expand Down
2 changes: 2 additions & 0 deletions packages/userscript/src/exporter/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export async function exportAllToJson(fileNameFormat: string, apiConversations:
let fileName = getFileNameWithFormat(fileNameFormat, 'json', {
title: conversation.title,
chatId: conversation.id,
createTime: conversation.createTime,
updateTime: conversation.updateTime,
})
if (filenameMap.has(fileName)) {
const count = filenameMap.get(fileName) ?? 1
Expand Down
12 changes: 8 additions & 4 deletions packages/userscript/src/exporter/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { checkIfConversationStarted, getConversationChoice } from '../page'
import { downloadFile, getFileNameWithFormat } from '../utils/download'
import { fromMarkdown, toMarkdown } from '../utils/markdown'
import { standardizeLineBreaks } from '../utils/text'
import { dateStr, timestamp } from '../utils/utils'
import { dateStr, timestamp, unixTimestampToISOString } from '../utils/utils'
import type { ApiConversationWithId, ConversationNodeMessage, ConversationResult } from '../api'
import type { ExportMeta } from '../ui/SettingContext'

Expand All @@ -22,7 +22,7 @@ export async function exportToMarkdown(fileNameFormat: string, metaList: ExportM
const conversation = processConversation(rawConversation, conversationChoices)
const markdown = conversationToMarkdown(conversation, metaList)

const fileName = getFileNameWithFormat(fileNameFormat, 'md', { title: conversation.title, chatId })
const fileName = getFileNameWithFormat(fileNameFormat, 'md', { title: conversation.title, chatId, createTime: conversation.createTime, updateTime: conversation.updateTime })
downloadFile(fileName, 'text/markdown', standardizeLineBreaks(markdown))

return true
Expand All @@ -36,6 +36,8 @@ export async function exportAllToMarkdown(fileNameFormat: string, apiConversatio
let fileName = getFileNameWithFormat(fileNameFormat, 'md', {
title: conversation.title,
chatId: conversation.id,
createTime: conversation.createTime,
updateTime: conversation.updateTime,
})
if (filenameMap.has(fileName)) {
const count = filenameMap.get(fileName) ?? 1
Expand Down Expand Up @@ -105,7 +107,7 @@ const transformContent = (
}

function conversationToMarkdown(conversation: ConversationResult, metaList?: ExportMeta[]) {
const { id, title, model, modelSlug, conversationNodes } = conversation
const { id, title, model, modelSlug, createTime, updateTime, conversationNodes } = conversation
const source = `${baseUrl}/c/${id}`

const _metaList = metaList
Expand All @@ -117,7 +119,9 @@ function conversationToMarkdown(conversation: ConversationResult, metaList?: Exp
.replace('{timestamp}', timestamp())
.replace('{source}', source)
.replace('{model}', model)
.replace('{modelSlug}', modelSlug)
.replace('{model_name}', modelSlug)
.replace('{create_time}', unixTimestampToISOString(createTime))
.replace('{update_time}', unixTimestampToISOString(updateTime))

return `${name}: ${val}`
})
Expand Down
15 changes: 13 additions & 2 deletions packages/userscript/src/ui/SettingDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useTitle } from '../hooks/useTitle'
import { LOCALES } from '../i18n'
import { getChatIdFromUrl } from '../page'
import { getFileNameWithFormat } from '../utils/download'
import { timestamp as _timestamp, dateStr } from '../utils/utils'
import { timestamp as _timestamp, dateStr, unixTimestampToISOString } from '../utils/utils'
import { IconCross, IconTrash } from './Icons'
import { useSettingContext } from './SettingContext'
import { Toggle } from './Toggle'
Expand Down Expand Up @@ -39,7 +39,10 @@ export const SettingDialog: FC<SettingDialogProps> = ({
const timestamp = _timestamp()
const title = sanitize(_title).replace(/\s+/g, '_')
const chatId = getChatIdFromUrl() || 'this-is-a-mock-chat-id'
const preview = getFileNameWithFormat(format, '{ext}', { title, chatId })
const now = Date.now() / 1000
const createTime = now
const updateTime = now
const preview = getFileNameWithFormat(format, '{ext}', { title, chatId, createTime, updateTime })

const source = `${baseUrl}/${chatId}`

Expand Down Expand Up @@ -90,6 +93,10 @@ export const SettingDialog: FC<SettingDialogProps> = ({
<Variable name="{timestamp}" title={timestamp} />
,{' '}
<Variable name="{chat_id}" title={chatId} />
,{' '}
<Variable name="{create_time}" title={unixTimestampToISOString(createTime)} />
,{' '}
<Variable name="{update_time}" title={unixTimestampToISOString(updateTime)} />
</p>
<input className="Input mt-4" id="filename" value={format} onChange={e => setFormat(e.currentTarget.value)} />
<p className="mt-1 text-sm text-gray-700 dark:text-gray-300">
Expand Down Expand Up @@ -144,6 +151,10 @@ export const SettingDialog: FC<SettingDialogProps> = ({
<Variable name="{model}" title={'ChatGPT-3.5'} />
,{' '}
<Variable name="{model_name}" title={'text-davinci-002-render-sha'} />
,{' '}
<Variable name="{create_time}" title={'2023-04-10T21:45:35.027Z'} />
,{' '}
<Variable name="{update_time}" title={'2023-04-10T21:45:35.027Z'} />
</p>
{exportMetaList.map((meta, i) => (
<div className="flex items-center mt-2" key={i}>
Expand Down
8 changes: 7 additions & 1 deletion packages/userscript/src/utils/download.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import sanitize from 'sanitize-filename'
import { dateStr, timestamp } from './utils'
import { dateStr, timestamp, unixTimestampToISOString } from './utils'

export function downloadFile(filename: string, type: string, content: string | Blob) {
const blob = content instanceof Blob ? content : new Blob([content], { type })
Expand All @@ -25,13 +25,19 @@ export function getFileNameWithFormat(format: string, ext: string, {
title = document.title,
// chatId will be empty when exporting all conversations
chatId = '',
createTime = Date.now(),
updateTime = Date.now(),
} = {}) {
const _title = sanitize(title).replace(/\s+/g, '_')
const _createTime = unixTimestampToISOString(createTime)
const _updateTime = unixTimestampToISOString(updateTime)

return format
.replace('{title}', _title)
.replace('{date}', dateStr())
.replace('{timestamp}', timestamp())
.replace('{chat_id}', chatId)
.replace('{create_time}', _createTime)
.replace('{update_time}', _updateTime)
.concat(`.${ext}`)
}
5 changes: 5 additions & 0 deletions packages/userscript/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ export function timestamp() {
export function getColorScheme(): 'light' | 'dark' {
return document.documentElement.style.getPropertyValue('color-scheme') as 'light' | 'dark'
}

export function unixTimestampToISOString(timestamp: number) {
if (!timestamp) return ''
return (new Date(timestamp * 1000)).toISOString()
}

0 comments on commit 5df4ba6

Please sign in to comment.