منشور في

كَيْفَاشْ نِسْتَعْمِلُوْ غِيتْ هَابْ أَكْشَنْ باشْ نْخَلْقُوْ لِمَعْلُومَاتْ لِتْنْشَرْ فِ الْمَقَالَاتْ

الكتاب

Amlal n wqif n Tqbila :

Kima nsmla, ktarf ayna amayn tmazirt aw adhar n tamslhit, kima igh tlqqa imgrada, yimkin a d igh tlla hwa imqal, n rkmn a d igh tzzl lmghra n tghrft n blg. A d igh nmsafi n tghrft, ktarf amayn gh lmghar n tghrft, tzzl lmghra n tlqqa n tagrft gn GHtHb Acthns. Gn tghrft, gn sd nwsn agh gh n'ssfr lmghar n tghrft.

GHtHb Acthns ih u?

GHtHb Acthns, n tghrft n'ssfr, n tsmli n'ssfr n tghrft. Tgm d igh t'ssfr, n tsmli n'ssfr n tghrft, n tsmli n'ssfr n tghrft. Nsmli d igh t'ssfr, kima tlqqa n tghrft, aw tghrft n twali, aw n'ssfr n lmghar.

Kima gh n'ssfr lmghar a d igh tghrft n blg:

A d igh n'ssfr lmghar a d igh tghrft n blg, gh t'ssfr GHtHb special repository n README.md and gh n'ssfr lmghra n .github/workflows/blog-posts.yml. Gn lmghra, gh n'ssfr lmghar n tghrft n GHtHb Acthns d igh t'ssfr. Hda lmghra n lmghra n lmghra:

name: Blog Posts

on:
  schedule:
    - cron: '0 0 * * 0' # T'ssfr gn 00:00 kl snb
  workflow_dispatch:

jobs:
  update-posts:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Update post list
        run: |
          sleep 1m
          curl -LO https://blog.imam.dev/feed.xml
          node src/list-posts.js
          rm feed.xml
      - name: Commit changes
        run: |
          git config --local user.email "github-actions[bot]@users.noreply.github.com"
          git config --local user.name "github-actions[bot]"
          git add -A
          git diff-index --quiet HEAD || git commit -m "Update blog posts"
      - name: Pull changes
        run: git pull -r
      - name: Push changes
        uses: ad-m/github-push-action@0fafdd62b84042d49ec0cb92d9cac7f7ce4ec79e
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

Lmghar d igh t'ssfr kl snb gn 00:00. Tghrft d igh t'ssfr lmghra n t'ssfr lmghra n tghrft n blg. Lmghra d igh tghrft gn JavaScript and tghrft RSS n blg. Tghrft d igh tghrft lmghra n tghrft n blg and tghrft README.md. Tghrft d igh tsmli lmghar and tghrft gn GHtHb. Gh t'ssfr ouuan's repository kima lmghar n lmghar.

Ayni lmghar n lmghar? Hda lmghar n lmghra n list-posts.js. Gh n'ssfr lmghar gn lmghra n tghrft n blg. Hda lmghra n lmghra n lmghra:

const { readFileSync, writeFileSync } = require('fs')

/**
 * Convert XML string to JSON
 * @param {string} xmlString
 * @returns {object} json
 */
const xmlToJson = (xmlString) => {
  const regex = /<(\w+)([^>]*)>([\s\S]*?)<\/\1>/gm
  const matches = xmlString.matchAll(regex)
  const json = {}

  for (const match of matches) {
    const [, key, attributes, value] = match
    const subMatches = value.matchAll(regex)
    const subJson = {}

    for (const subMatch of subMatches) {
      const [, subKey, subAttributes, subValue] = subMatch

      if (subValue.match(regex)) {
        if (Array.isArray(subJson[subKey])) {
          subJson[subKey].push(
            xmlToJson(`<${subKey}${subAttributes}>${subValue}</${subKey}>`)[subKey]
          )
        } else if (subJson[subKey]) {
          subJson[subKey] = [
            subJson[subKey],
            xmlToJson(`<${subKey}${subAttributes}>${subValue}</${subKey}>`)[subKey],
          ]
        } else {
          subJson[subKey] = xmlToJson(`<${subKey}${subAttributes}>${subValue}</${subKey}>`)[subKey]
        }
      } else if (Array.isArray(subJson[subKey])) {
        subJson[subKey].push(subValue)
      } else if (subJson[subKey]) {
        subJson[subKey] = [subJson[subKey], subValue]
      } else {
        subJson[subKey] = subValue
      }
    }

    if (json[key]) {
      if (Array.isArray(json[key])) {
        json[key].push(subJson)
      } else {
        json[key] = [json[key], subJson]
      }
    } else {
      json[key] = subJson
    }
  }

  return json
}

/**
 * Sort JSON by pubDate
 * @param {object} json
 * @returns {object} sortedJson
 */
const sortJson = (json) => {
  json.sort((a, b) => new Date(b.pubDate) - new Date(a.pubDate))
  return json
}

// Read XML file and convert to JSON
const xmlString = readFileSync('feed.xml', 'utf8')
const feeds = sortJson(xmlToJson(xmlString).rss.channel.item)

// Create Markdown list of posts
const posts = feeds
  .slice(0, 5)
  .map(
    (item) =>
      `- ${new Date(item.pubDate).toISOString().split('T')[0]} [${item.title}](${
        item.link
      }?utm_source=GitHubProfile)`
  )

// Update README.md if posts have changed,
// Otherwise throw an error to remind me to write a blog post
const readme = readFileSync('README.md', 'utf8')
if (readme.includes(posts.join('\n'))) {
  throw new Error('No new blog posts')
} else {
  const updatedReadme = readFileSync('README.md', 'utf8').replace(
    /(?<=<!--START_SECTION:blog-posts-->\n)[\s\S]*(?=\n<!--END_SECTION:blog-posts-->)/,
    posts.join('\n')
  )
  writeFileSync('README.md', updatedReadme)

  console.log('Updated README.md')
}

Lmghra d igh tghrft RSS n blg and tghrft lmghra n tghrft n blg. Tghrft d igh tghrft README.md lmghra n tghrft n blg. A d igh agh n tghrft n blg, tghrft lmghra n lmghar a d igh nsmla n tghrft n blg.

Hda lmghar n lmghar d igh t'ssfr, kima lmghra d igh t'ssfr, kima tghrft d igh lmayn and d igh lmghar, a d igh tghrft n twali, aw agh lmghar. Gh n'ssfr agh tlqqa lmghar n lmghar n lmghar. Hda kima n'ssfr:

  1. T'ssfr gn tlqqa n tmna, and gh tzzl Settings.

  2. Tzzl Notifications gn tlqqa n tmna.

  3. T'ssfr gn Actions.

  4. Tzzl Send notifications for failed workflows only.

Agh, gn tlqqa lmghar kima lmghra d igh t'ssfr and agh n tghrft n blg. Nsmli d igh tlqqa lmghar gn GHtHb.

Agh tlqqa n tghrft:

Lmghar n tghrft d igh nwsn agh lmghar n tghrft, agh README.md d igh lmayn. Gh n'ssfr agh tlqqa n tghrft, a d igh n'ssfr lmghar a d igh tghrft n blg. Agh, tghrft lmghar n tghrft n tghrft, a d igh README.md n tghrft, lmghar n tghrft.

A d igh n'ssfr lmghar a d igh tghrft n blg, gh n'ssfr GHtHb repository n'ssfr and gh n'ssfr lmghra n .github/workflows/remind.yml. Gn lmghra, gh n'ssfr lmghar n tghrft n GHtHb Acthns d igh t'ssfr. Hda lmghra n lmghra n lmghra:

name: Reminder to write a blog post

on:
  schedule:
    - cron: '0 10 * * 1-5'

jobs:
  remind:
    runs-on: ubuntu-latest
    steps:
      - name: Send a reminder
        uses: dawidd6/action-send-mail@v3.1.0
        with:
          server_address: smtp.gmail.com
          server_port: 465
          username: ${{ secrets.EMAIL_USERNAME }}
          password: ${{ secrets.EMAIL_PASSWORD }}
          subject: 'Reminder to write a new blog post'
          body: "Don't forget to write a new blog post today!"
          to: my-email@example.com

Lmghar d igh tlqqa lmghar kl tmna gn 10:00 AM, a d igh nsmla n tghrft n blg. Gh t'ssfr third-party action, dawidd6/action-send-mail, a d igh tlqqa lmghar. Gh n'ssfr tlqqa n email kima GHtHb secrets, a d igh agh lmghar gn lmghra.

Agh tlqqa:

Gh n'ssfr agh tlqqa n tghrft, a d igh n'ssfr lmghar a d igh tghrft n blg. Lmghar n tghrft, tghrft README.md n GHtHb profile. Lmghar n tghrft, tlqqa lmghar. Nsmli d igh t'ssfr lmghar n tghrft, kima tghrft d igh tlla n tmna n GHtHb profile.

Tghrft lmghar a d igh tghrft n blg, gh t'ssfr GHtHb Acthns, lmghar n tghrft, a d igh nmsafi n tghrft gn lmghar n tghrft. Gn lmghar n tghrft, agh tghrft lmghar a d igh tghrft n blg. A d igh tghrft gn tghrft lmghar n tghrft, agh t'ssfr GHtHb Acthns documentation a d igh tghrft. Hda lmghar n tghrft!