我在我的部落格上有很多長青內容。本教程將解釋我如何自動化在Twitter上重複使用這些內容的過程。
我定期在我的部落格上發表長青內容。所謂長青指的是內容不會關於新聞或最近的事件,而是即使今天有效,一年後,甚至五年後,如果我繼續進行更新以防止信息過時,它仍然有效。
每次我撰寫新的部落格文章時,我都會在Twitter上分享它,如果我的少數幾位絕妙的追隨者(👋)沒有在那裡看到它,他們可能永遠不會再次看到它,我認為這對我來說是一種不公平(因為我在撰寫該部落格文章時花了很多時間) ,對可能通過該文章學到新知識的人也是一種不公平。
我有時會不時分享一篇舊文章,但這是一個手動過程。我必須記得這樣做,而且我還必須記錄我已經分享過的內容,以避免再次發佈相同的內容。
因此,我想在這個問題周圍創建一個小小的自動化,以在我睡覺的時候每天發佈2篇舊文章。
我知道有一些服務可以做到這一點,但是-嘿-我們是開發人員,開發人員會建立自己的工具 😄
棧
我想創建一個應用程序,從列表中查找我要重複使用的帖子,當我調用特定的URL時,它會分享一篇隨機的帖子,總是選擇一篇不久前分享的帖子。
應用程序將基於Node.js,托管在Glitch上。我經常在教程中使用Glitch來進行代碼示例,它非常好用!
你不僅僅可以創建小型演示,還可以創建一個完整的Node.js應用程序,這對我的需求來說非常合適。儘管應用程序在幾個小時的不活動後關閉,但是一個HTTP請求就可以喚醒它。
最後一個謎題是決定在哪裡托管數據。我想要一個容易訪問的服務,不需要繁瑣的權限和授權設置,所以我選擇了Airtable。
在Airtable上托管數據
Airtable是一個類似於電子表格和數據庫的混合體。您可以非常輕松地添加數據,也可以通過API很容易地導出數據。
我創建了一個簡單的底部來保存帖子表:
它有以下列:
- 標題:帖子標題
- 鏈接:帖子鏈接
- 已分享:如果該帖子最近已經分享過了
- 禁用:如果選中,則該帖子將不會被 分享。有用的"暫停"內容
- 描述:可選的文字,將在標題之後,在鏈接之前分享在Twitter上
我在表中填充了一些帖子。您可以
我將使用這個表作為數據源,並使用Node.js API進行訪問。Airtable.js是官方的JavaScript庫。
Airtable的一個很酷的功能是API文檔是動態的,並且根據您的表的鍵和ID進行個性化,因此您可以直接將代碼放在應用程序中。 它還更進一步,提供您使用的確切字段以及實時內容:
這本身就很神奇,我希望更多的服務在他們的API文檔中也做這樣的好事。
現在,進入Glitch!
在Glitch上創建Node.js應用程序
我在Glitch上構建的Node.js應用程序需要與Airtable和Twitter通信。
這是完整的應用程序:https://glitch.com/edit/#!/flavio-repurpose-old-posts-twitter
Glitch提供了一個很好的功能,允許您在共享項目時將密鑰和參數保密,方法是將它們放在.env文件中。
我設定了Airtable訪問的密鑰:
- AIRTABLE_API_KEY
- AIRTABLE_BASE_ID
- AIRTABLE_BASE_NAME
- AIRTABLE_VIEW_NAME
以及Twitter的鍵:
- TWITTER_CONSUMER_KEY
- TWITTER_CONSUMER_SECRET
- TWITTER_ACCESS_TOKEN
- TWITTER_ACCESS_TOKEN_SECRET
這些Twitter參數是由Twitter Apps面板提供的。創建一個應用程序以獲取消費者密鑰和秘密,並通過單擊生成一個個人訪問令牌。
應用程序以此構建。在Node.js代碼中,通過process.env
可以訪問.env
值。
依賴項
應用程序使用
我使用方便的添加套件功能將它們添加到Glitch中,該功能在打開package.json
文件後可用。
初始化Airtable
讓我們開始:
const base = require('airtable').base(process.env.AIRTABLE_BASE_ID)
通過在基底上調用select()
方法,Airtable返回一個查詢對象。
查詢對象可以用於提取記錄。它以每次100行的塊返回內容。
我們需要通過這些進行分頁並存儲所有帖子,以防列表超過100項。
分頁查詢該表的記錄
我們使用eachPage
方法進行分頁查詢,它接受兩個函數。一個在每次迭代時執行,另一個在完成內容提取時執行,我們擁有所有記錄:
const repurposeOldPost = () => {
posts = []
base(process.env.AIRTABLE_BASE_NAME)
.select({
view: process.env.AIRTABLE_VIEW_NAME,
})
.eachPage(processPage, processPosts)
}
processPage()
處理單個“頁面”的結果,最多 100條記錄。它首先過濾列表以排除標題值為空的項(以跳過空行)和禁用列設置為true
的項。
然後,它將值映射到一個新數組中,該數組僅包含我們需要的屬性(id,title,link,shared,description),並將結果分配給partialPosts
。
它將該數組與當前存儲所有項目的posts
變量合併,在獲取下100項以處理。
const processPage = (records, fetchNextPage) => {
const partialPosts = records
.filter((record) => {
if (record.get('Title') && record.get('Disabled') !== true) return true
})
.map((record) => {
return {
id: record.id,
title: record.get('Title'),
link: record.get('Link'),
shared: record.get('Shared') || false,
description: record.get('Description'),
}
})
posts = [...posts, ...partialPosts]
fetchNextPage()
}
當此過程完成時,eachPage()
調用processPosts()
。
處理所有帖子
這是分析所有帖子列表並處理推文的地方:
const processPosts = (err) => {
if (err) {
console.error(err)
return
}
let post
const notShared = posts.filter((post) => post.shared === false)
if (notShared.length === 0) {
//already shared all posts, clear them and just get the first
post = posts[0]
clearSharedStateForAllPosts(posts)
} else {
post = notShared[0]
}
if (canTweet(lastTweetTimestamp)) {
updateLastTweetTimestamp()
tweet(post)
setAsSharedOnAirtable(post)
} else {
console.error('Tweeting too much')
}
}
首先,我找到最近未共享的帖子列表。我想從這個列表中選擇一篇帖子,這樣在重新共享一篇帖子之前,必須共享其他所有帖子。這很重要,因為我想對材料進行恰當的輪換。
我選擇此列表中的第一個。如果所有帖子已被分享,我會清除共享列,並從所有帖子列表中選擇第一個帖子。
一旦我有了一篇帖子,我檢查是否可以發送推文-我在canTweet()
函數中設置了60分鐘的檢查時間間隔,以防止誤觸多次調用URL而不察覺地洪水般的推文。
let lastTweetTimestamp = 0
const canTweet = (lastTweetTimestamp) => {
if (lastTweetTimestamp === 0) {
return true
}
const currentTimestamp = Math.floor(Date.now() / 1000)
if (currentTimestamp - lastTweetTimestamp > 60 * 60) {
return true
}
return false
}
如果我可以推文,我將更新全局時間戳值,以便下一次檢查基於此上次推文時間。
我用tweet(post)
發推文,這在Twit庫的幫助下非常簡單:
const Twit = require('twit')
const twitter = new Twit({
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
access_token: process.env.TWITTER_ACCESS_TOKEN,
access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
})
const tweet = (post) => {
let status = `${post.title} ${post.link}`
if (post.description) {
status = `${post.title} ${post.description} ${post.link}`
}
twitter.post('statuses/update', { status: status }, (err, data, response) => {
//console.log(data) //inspect the Twitter response
})
}
推文內容是${post.title} ${post.link}
,除非描述字段中有其他內容,否則為${post.title} ${post.description} ${post.link}
。
該字段是多行字段,因此我可以在其中使用表情符號和格式。
進入Express
我們現在需要一種方式來公開所有這些功能!Express非常適合這個。我將其設置為侦聽GET請求在/repurpose-old-post
上。
GET對於測試而言更方便。為了防止任何人都能夠發送推文,例如通過訪問我的Glitch(在我的情况下是公開的,以示示範,但也可以是私有的),我設置了一個名為secret
的URL查詢參數,在.env
文件中設置,因此只對我可見:
SECRET_URL_PARAMETER=something
const express = require('express')
const app = express()
app.get('/repurpose-old-post', (request, response) => {
if (request.query.secret === process.env.SECRET_URL_PARAMETER) {
repurposeOldPost()
response.send('Tweet sent')
} else {
console.log('Wrong secret parameter')
}
})
app.listen(process.env.PORT)
一切都正在運行!
這太完美了!現在,您可以通過點擊Show按鈕打開您的glitch前端,並使用您設置的私密URL調用URL。
如果您正確配置了Twitter和Airtable的憑據,並在Airtable基礎上放置了內容,它應該會幫您發推文:
自動發佈使用IFTTT
IFTTT(即IF這就是那)是一個了不起的工具,可以幫助您自動執行任務。
我設置它在一天的特定時間調用我的URL:
創建一個自動化非常容易,點擊“New Applet”:
點擊this並出現服務列表:
點擊Date & Time服務:
選擇“Every day at”:
選擇一天的時間。現在第一部分已經完成。點擊that
選擇一個操作服務。選擇Webhook服務:
填寫發送到Glitch的請求的詳細信息(或者您想要的任何URL):
最後,點擊create action,然後點擊finish。
就是這樣!我們現在可以坐下來觀看我們的Twitter自動駕駛🤖,但別忘記Twitter不僅僅用於推出您的“內容”。它是用於交流的,所以如果您想要增加關注者,請確保不要陷入只推送內容的陷阱,而是與之互動並在推文中找到平衡。