diff --git a/public/img/ghost_post.png b/public/img/ghost_post.png new file mode 100644 index 0000000..76bcb64 Binary files /dev/null and b/public/img/ghost_post.png differ diff --git a/public/scripts/upload.js b/public/scripts/upload.js index 9c77a39..cb766c6 100644 --- a/public/scripts/upload.js +++ b/public/scripts/upload.js @@ -8,20 +8,24 @@ async function updateMediaType(attachmentsCount, attachmentListElem) { const mediaTypeElem = document.getElementById('media-type'); const spoilerMediaControl = document.querySelector('.spoiler-media-control'); + const ghostPostMediaControl = document.querySelector('.ghost-post-media-control'); let mediaTypeDesc; if (attachmentsCount === 0) { mediaTypeDesc = 'Text 📝'; spoilerMediaControl.style.display = 'none'; + ghostPostMediaControl.style.display = 'block'; } else if (attachmentsCount === 1) { const singleAttachmentType = attachmentListElem.querySelector('select').value; if (singleAttachmentType === 'Image') mediaTypeDesc = 'Image 🖼️'; else mediaTypeDesc = 'Video 🎬'; spoilerMediaControl.style.display = 'block'; + ghostPostMediaControl.style.display = 'none'; } else { mediaTypeDesc = 'Carousel 🎠'; spoilerMediaControl.style.display = 'block'; + ghostPostMediaControl.style.display = 'none'; } mediaTypeElem.innerText = mediaTypeDesc; @@ -72,10 +76,56 @@ document.addEventListener('DOMContentLoaded', async () => { const pollAttachmentOptions = document.getElementById( 'poll-attachment-options' ); + const ghostPostMediaControl = document.querySelector('.ghost-post-media-control'); if (pollAttachmentOptions.style.display === 'none') { pollAttachmentOptions.style.display = 'block'; + ghostPostMediaControl.style.display = 'none'; } else { pollAttachmentOptions.style.display = 'none'; + ghostPostMediaControl.style.display = 'block'; } }); + + const ghostPostCheckbox = document.querySelector('input[name="ghostPostMedia"]'); + const topicTagMediaControl = document.querySelector('.topic-tag-media-control'); + const linkAttachmentMediaControl = document.querySelector('.link-attachment-media-control'); + const attachImageMediaControl = document.querySelector('.attach-image-media-control'); + const replyOptionsMediaControl = document.querySelector('.reply-options-media-control'); + + const topicTagInput = document.getElementById('topic-tag'); + const linkAttachmentInput = document.getElementById('link-attachment'); + const replyControlSelect = document.getElementById('reply-control'); + const attachmentsList = document.getElementById('attachments-list'); + const pollAttachmentOptions = document.getElementById('poll-attachment-options'); + + if (ghostPostCheckbox) { + ghostPostCheckbox.addEventListener('change', async () => { + // When ghost post is checked, disable fields that are not relevant to ghost posts + if (ghostPostCheckbox.checked) { + topicTagMediaControl.style.display = 'none'; + linkAttachmentMediaControl.style.display = 'none'; + attachPollButton.style.display = 'none'; + attachImageMediaControl.style.display = 'none'; + replyOptionsMediaControl.style.display = 'none'; + + if (topicTagInput) topicTagInput.value = ''; + if (linkAttachmentInput) linkAttachmentInput.value = ''; + if (replyControlSelect) replyControlSelect.value = ''; + if (attachmentsList) attachmentsList.innerHTML = ''; + if (pollAttachmentOptions) { + pollAttachmentOptions.style.display = 'none'; + const pollInputs = pollAttachmentOptions.querySelectorAll('input[type="text"]'); + pollInputs.forEach(input => input.value = ''); + } + + await updateMediaType(0, null); + } else { // When the checkbox is unchecked, enable all fields + topicTagMediaControl.style.display = 'block'; + linkAttachmentMediaControl.style.display = 'block'; + attachPollButton.style.display = 'block'; + attachImageMediaControl.style.display = 'block'; + replyOptionsMediaControl.style.display = 'block'; + } + }); + } }); diff --git a/src/index.js b/src/index.js index 99cfe40..29836bb 100644 --- a/src/index.js +++ b/src/index.js @@ -62,6 +62,7 @@ const FIELD__USERNAME = 'username'; const FIELD__VIEWS = 'views'; const FIELD_IS_SPOILER_MEDIA = 'is_spoiler_media'; const FIELD_TEXT_ENTITES = 'text_entities'; +const FIELD_GHOST_POST_STATUS = 'ghost_post_status'; const MEDIA_TYPE__CAROUSEL = 'CAROUSEL'; const MEDIA_TYPE__IMAGE = 'IMAGE'; @@ -100,6 +101,7 @@ const PARAMS__TOPIC_TAG = 'topic_tag'; const PARAMS__USERNAME = 'username'; const PARAMS_IS_SPOILER_MEDIA = 'is_spoiler_media'; const PARAMS_TEXT_ENTITES = 'text_entities'; +const PARAMS_IS_GHOST_POST = 'is_ghost_post'; // Read variables from environment require('dotenv').config(); @@ -449,6 +451,7 @@ app.post('/upload', upload.array(), async (req, res) => { pollOptionD, quotePostId, spoilerMedia, + ghostPostMedia, } = req.body; const params = { @@ -479,6 +482,10 @@ app.post('/upload', upload.array(), async (req, res) => { params[PARAMS_IS_SPOILER_MEDIA] = true; } + if (ghostPostMedia) { + params[PARAMS_IS_GHOST_POST] = true; + } + if (pollOptionA && pollOptionB) { const pollAttachment = JSON.stringify({ option_a: pollOptionA, @@ -679,6 +686,7 @@ app.get('/threads/:threadId', loggedInUserChecker, async (req, res) => { FIELD__REPOSTED_POST, FIELD_IS_SPOILER_MEDIA, FIELD_TEXT_ENTITES, + FIELD_GHOST_POST_STATUS, ].join(','), }, req.session.access_token @@ -688,7 +696,7 @@ app.get('/threads/:threadId', loggedInUserChecker, async (req, res) => { const queryResponse = await axios.get(queryThreadUrl, { httpsAgent: agent, }); - const { poll_attachment, ...rest } = queryResponse.data; + const { poll_attachment, ghost_post_status, ...rest } = queryResponse.data; data = rest; if (poll_attachment) { @@ -697,6 +705,12 @@ app.get('/threads/:threadId', loggedInUserChecker, async (req, res) => { ...poll_attachment, }; } + + const is_ghost_post = ghost_post_status === 'ACTIVE'; + data = { + ...data, + is_ghost_post, + }; } catch (e) { console.error(e?.response?.data?.error?.message ?? e.message); } diff --git a/views/thread.pug b/views/thread.pug index 173265d..63a68d7 100644 --- a/views/thread.pug +++ b/views/thread.pug @@ -39,6 +39,9 @@ block content tr td Is Spoiler Media Post td #{is_spoiler_media} + tr + td Is Ghost Post + td #{is_ghost_post} tr td GIF URL td diff --git a/views/upload.pug b/views/upload.pug index 8397645..b6a0be3 100644 --- a/views/upload.pug +++ b/views/upload.pug @@ -58,6 +58,16 @@ block content .spoiler-media-control { display: none; } + .ghost-post-media-control { + display: flex; + flex-direction: row; + align-items: center; + } + #ghost-post-img{ + width: 25px; + height: 25px; + margin-bottom: 0; + } if (replyToId !== undefined) p(style='color: gray') Replying to #{replyToId} @@ -67,37 +77,55 @@ block content | Text: textarea(placeholder='Start a thread...' id='text' name='text' autocomplete='off') br - | To attach an image or video, click the image below - div.attachments-area - img#attachments-button(src='/img/attachment.png') - div.attachment-controls - div#attachments-list.attachments - div.spoiler-media-control - label(for='spoilerMedia') - | Mark Media as Spoiler    - input(type='checkbox' name='spoilerMedia' value='true') - br - - label(for="reply-control") Who Can Reply - select#reply-control(name='replyControl' hint="Reply Control") - option(value="" selected) - option(value="everyone") Everyone - option(value="accounts_you_follow") Accounts You Follow - option(value="mentioned_only") Mentioned Only - option(value="parent_post_author_only") Parent Post Author Only - option(value="followers_only") Followers Only + div.attach-image-media-control + | To attach an image or video, click the image below + div.attachments-area + img#attachments-button(src='/img/attachment.png') + div.attachment-controls + div#attachments-list.attachments + div.spoiler-media-control + label(for='spoilerMedia') + | Mark Media as Spoiler    + input(type='checkbox' name='spoilerMedia' value='true') + br - label(for='topicTag') - | Topic Tag - input#topic-tag(type='text' name='topicTag' value='' maxlength='50') + div.reply-options-media-control + label(for="reply-control") Who Can Reply + br + select#reply-control(name='replyControl' hint="Reply Control") + option(value="" selected) + option(value="everyone") Everyone + option(value="accounts_you_follow") Accounts You Follow + option(value="mentioned_only") Mentioned Only + option(value="parent_post_author_only") Parent Post Author Only + option(value="followers_only") Followers Only + + div.topic-tag-media-control + label(for='topicTag') + | Topic Tag + br + input#topic-tag(type='text' name='topicTag' value='' maxlength='50') + br - label(for='linkAttachment') - | Link Attachment - input#link-attachment(type='text' name='linkAttachment' value='') + div.link-attachment-media-control + label(for='linkAttachment') + | Link Attachment + br + input#link-attachment(type='text' name='linkAttachment' value='') + br label(for="autoPublishText") input(type="checkbox" name="autoPublishText" id="autoPublishText") | Auto-Publish (only for text posts) + br + + br + div.ghost-post-media-control + input(type='checkbox' name='ghostPostMedia' value='true') + label(for='ghostPostMedia') + | Publish as Ghost Post   + img#ghost-post-img(src='/img/ghost_post.png') + br button#poll-attachment-button(type='button' name='pollAttachment') Attach Poll 🗳️ div#poll-attachment-options(style='display:none')