Skip to content

Commit

Permalink
feat: add stars milestone notification
Browse files Browse the repository at this point in the history
  • Loading branch information
byodian committed Oct 22, 2024
1 parent 49063e4 commit 0a57ca6
Show file tree
Hide file tree
Showing 11 changed files with 1,799 additions and 79 deletions.
13 changes: 12 additions & 1 deletion README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@

![for_message_change_message](./docs/message_fork.jpg)

**Stars里程碑消息**

![stars_milestone](./docs/milestone.jpeg)

## 未来计划
- [ ] 配置 Stars 里程碑,达到里程碑后,发送祝贺消息
- [x] 配置 Stars 里程碑,达到里程碑后,发送祝贺图片
- [ ] 优化事件频繁发生,消息过多问题
- [ ] 增加数据统计功能,定期发送统计数据

Expand Down Expand Up @@ -95,6 +99,13 @@ npx wrangler secret put TELEGRAM_CHAT_ID
pnpm run deploy
```

`wrangler.toml` 中配置 GitHub 仓库的 Stars 里程碑节点

```
[vars]
MILESTONES = [10,50,100,500,1000,5000,100000]
```

打开 Cloudflare 网站获取 Worker URL 后续会用到。

## 4. 配置 Github Webhooks
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ The event notification styles are as follows

![for_message_change_message](./docs/message_fork.jpg)

**Stars milestone message**

![star_milestone](./docs/milestone.jpeg)

## Future Plans
- [ ] Configure Stars milestones, send congratulatory messages when milestones are reached
- [x] Configure Stars milestones, send congratulatory messages when milestones are reached
- [ ] Optimize the issue of too many messages when events occur frequently
- [ ] Add data statistics functionality, send statistical data periodically

Expand Down Expand Up @@ -94,6 +98,12 @@ npx wrangler secret put TELEGRAM_CHAT_ID
pnpm run deploy
```

Configure GitHub Stars milestones in wrangler.toml
```
[vars]
MILESTONES = [10,50,100,500,1000,5000,100000]
```

Open the Cloudflare website to get the Worker URL, which will be used later.

## 4. Configure Github Webhooks
Expand Down
Binary file added docs/milestone.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"wrangler": "^3.60.3"
},
"dependencies": {
"bumpp": "^9.7.1"
"bumpp": "^9.7.1",
"svg2png-wasm": "^1.4.1"
}
}
7 changes: 7 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 28 additions & 22 deletions src/github.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { stores } from "./stores"

// event types
const events = {
issues : 'issues',
Expand All @@ -18,7 +20,7 @@ const actions = {
* Function to get the event message
* @param {string} event github event - issues, pull_request, star
* @param {Object} body
* @returns
* @returns
*/
export default function getEventMessage(event, body) {
const strategy = getStrategy(event)
Expand All @@ -40,12 +42,12 @@ function getStrategy(event) {
function issuesEventHandler(body) {
const {
action,
repository: {
name: repo,
repository: {
name: repo,
html_url: repoUrl,
},
issue: {
html_url: issueUrl,
issue: {
html_url: issueUrl,
user: {
login: issueCreator,
html_url: issueCreatorUrl
Expand All @@ -56,15 +58,15 @@ function issuesEventHandler(body) {
if (action === actions.opened) {
return `
[Issue](${issueUrl}) opened in [${repo}](${repoUrl}) repo by [${issueCreator}](${issueCreatorUrl})!
Great chance to improve your project! 🚀
Great chance to improve your project! 🚀
Let's keep making *${repo}* better! 🌟
`
}

if (action === actions.closed) {
return `
[Issue](${issueUrl}) closed in [${repo}](${repoUrl}) repo!
Nice! You’ve made *${repo}* stronger.
Nice! You’ve made *${repo}* stronger.
Keep it up! 💪
`
}
Expand All @@ -75,12 +77,12 @@ Keep it up! 💪
function pullRequestEventHandler(body) {
const {
action,
repository: {
name: repo,
repository: {
name: repo,
html_url: repoUrl,
},
pull_request: {
html_url: prUrl,
pull_request: {
html_url: prUrl,
user: {
login: prCreator,
html_url: prCreatorUrl
Expand All @@ -97,7 +99,7 @@ Your hard work is getting recognized! 💡
if (action === actions.closed) {
return `
[Pull request](${prUrl}) closed in [${repo}](${repoUrl}) repo!
Contribution reviewed and done!
Contribution reviewed and done!
*${repo}* is growing stronger! 👏
`
}
Expand All @@ -108,17 +110,21 @@ Contribution reviewed and done!
function starEventHandler(body) {
const {
action,
repository: {
name: repo,
repository: {
name: repo,
html_url: repoUrl,
stargazers_count,
forks_count
},
sender: {
login: sender,
sender: {
login: sender,
html_url: senderUrl
},
} = body
stores.stars = stargazers_count
stores.forks = forks_count
stores.repo = repo
stores.action = action
if (action === actions.created) {
return `
Star created for [${repo}](${repoUrl}) repo!
Expand All @@ -140,19 +146,19 @@ Don’t worry, keep going! More stars will come. 🌱

function forkEventHandler(body) {
const {
repository: {
name: repo,
repository: {
name: repo,
html_url: repoUrl,
},
sender: {
login: sender,
sender: {
login: sender,
html_url: senderUrl
},
} = body

return `
The Repo [${repo}](${repoUrl}) has been forked by [${sender}](${senderUrl})!
The repo [${repo}](${repoUrl}) has been forked by [${sender}](${senderUrl})!
Your project is spreading!
*${repo}* is reaching more people! 🌍
`
}
}
117 changes: 65 additions & 52 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,76 @@
import getEventMessage from "./github"
import { stores } from "./stores"
import { getMilestonePng } from "./utils"

/**
* Telegram Bot API Docs - https://core.telegram.org/bots/api#sendmessage
*/
export default {
async fetch(request, env, ctx) {
if (request.method !== 'POST') {
return new Response('Invalid request method', { status: 405 })
}
async fetch(request, env, ctx) {
if (request.method !== 'POST') {
return new Response('Invalid request method', { status: 405 })
}

if (!request.headers.has('X-GitHub-Event')) {
return new Response('Invalid github event', { status: 404 })
}

if (!request.headers.has('X-GitHub-Event')) {
return new Response('Invalid github event', { status: 404 })
}
const githubEvent = request.headers.get('X-GitHub-Event')

const githubEvent = request.headers.get('X-GitHub-Event')
try {
const body = await request.json()
const message = getEventMessage(githubEvent, body)

// send message to Telegram
// api docs - https://core.telegram.org/bots/api#sendmessage
const telegramUrl = `https://api.telegram.org/bot${env.TELEGRAM_TOKEN}/sendMessage`

const telegramPayload = {
chat_id: env.TELEGRAM_CHAT_ID,
text: message,
parse_mode: "Markdown",
link_preview_options: { is_disabled: true }
}

const telegramResponse = await fetch(telegramUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(telegramPayload),
})

if (telegramResponse.ok) {
return new Response('Message sent to Telegram', { status: 200 })
} else {
return new Response(`Failed to send message to Telegram`, { status: 500 })
}
// send message
const body = await request.json()
const message = getEventMessage(githubEvent, body)
await sendTelegramMessage(env.TELEGRAM_TOKEN, env.TELEGRAM_CHAT_ID, message)

// send milestone photo
if (githubEvent === stores.eventType &&
stores.action === 'created' &&
env.MILESTONES.includes(stores.stars)) {
try {
const photoBuffer = await getMilestonePng(stores.stars)
await sendTelegramPhoto(env.TELEGRAM_TOKEN, env.TELEGRAM_CHAT_ID, photoBuffer)
} catch (error) {
console.log('Failed to send milestone photo:', error.message)
}
}

return new Response('Message sent to Telegram', { status: 200 })
} catch (error) {
return new Response("Failed to process webhook event.", {
status: 500,
});
console.error('Error send message:', error.message)
return new Response("Failed to handle github event.", { status: 500 })
}
}
}
}

async function sendTelegramMessage(token, chatId, message) {
const response = await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: chatId,
text: message,
parse_mode: "Markdown",
link_preview_options: { is_disabled: true }
}),
})
if (!response.ok) {
throw new Error('Failed to send message to Telegram')
}
return response
}

function makeMessage(body) {
const {
name: repo,
html_url: repoUrl,
stargazers_count,
forks_count
} = body.repository

const { login: follwer, html_url: follwerUrl } = body.sender

return `
New Github star for [${repo}](${repoUrl}) repo!
The *${repo}* repo now has *${stargazers_count}* stars and *${forks_count}* forks!🎉
Your new fan is [${follwer}](${follwerUrl})
`
async function sendTelegramPhoto(token, chatId, photoBuffer) {
const formData = new FormData()
formData.append('chat_id', chatId)
formData.append('photo', new Blob([photoBuffer], { type: 'image/png' }), 'image.png')

const response = await fetch(`https://api.telegram.org/bot${token}/sendPhoto`, {
method: 'POST',
body: formData
})
if (!response.ok) {
throw new Error('Failed to send photo to Telegram')
}
return response
}
Loading

0 comments on commit 0a57ca6

Please sign in to comment.