DEV Community

hikari.huang
hikari.huang

Posted on

[Distributed SNS] A story about the making Shinjiro Koizumi bot on Nostr.

This is the 14th article of Nostr (1) Advent Calendar 2023
Japanese ver is here

I made a GPT-4 Shinjiro Koizumi bot on Nostr and X(Twitter).
Links↓

Introduction

Who's Shinjiro?

Do you know Shinjiro Koizumi? He is a Japanese statesman, his father is ex-Prime Minister Junichiro Koizumi.

Image description
Image description

Mr.Shinjiro Koizumi is kinda Internet meme in Japan. Because his remarks are often so "Interesting".
Why? That is "Tautology". That means his sentence looks so meaningful but meaningless actually. We call it Shinjiro-Syntax.
These are examples. His actual remarks.

  • I don't think Japan should stay the way it is now. That's why I think Japan shouldn't stay the way it is now.
  • Thanks to working from home, I can carry out my official work remotely.
  • To the point that I don't seem to be remorseful, I remose it. it's my own problem.
  • I heard you were born on your birthday.(This's ogiri)

What's Nostr?

Nostr is a protol, that's used for next generation distributed SNS. I don't explain about Nostr this time, but I highly recommend it because it's "the Free1 and Secure"!
Please check out here↓

Coding

Pioneers have already lectured details how to write codes for Nostr Protocol on these pages or books, so I just intoduce the ingenuity and stuck points

1. Connection to multiple relays

Now, it seems to be easy to use SimplePool() of nostr-tools to post to multiple relays, but I somehow couldn't work at that time. so I use a simple for statement.

// Post
if (message != null){
  for (const relayURL of relayURLs) {
    try {
      await postToRelays(relayURL, metadata);
    } catch (e) {
      console.log(e);
      continue;
      }
    }
  }
Enter fullscreen mode Exit fullscreen mode

I added the "Like" function, but lots of Shinjiro
When I posted, "Shinjiro" is occasionally mentioned in the timeline. Each time, I used to manually like the post, but it's annoying, so I automated it. (Probably if Shinjiro liked their posts, Everyone would be happy)
This time, I've decided to like all posts if it contains the word "Koizumi" or "Shinjiro".
I retrieved the all posts from the relays, and filtered them with includes(), and send a Like event (kind7).
When I finally run it, somehow, a lots of of Shinjiro appeared in the Like filed, causing the timeline to buzz.

  • Proliferated Shinjiro

    That's why sending events to multiple relays, but it is a mystery because it only generates just one event so it is unique...(so the number of likes is normal).
    And then I send like event once an hour, so I tried to reduce duplicates as much as possible by retrieving only posts within an hour.

const likePosts = async (relayUrl, targetWords) => {
  const relay = relayInit(relayUrl);
  relay.on("error", () => {
    console.error("failed to connect");
  });

  await relay.connect();
  const sub = relay.sub([{ kinds: [1] }]);
  let num = 0;
  sub.on("event", (ev) => {
    try {
      const currentTime = currUnixtime(); // Now UNIX TIME
      const oneHourAgo = currentTime - 3600; // UNIX TIME 1 hour ago

      // Like only posts which includes target words and within an hour
      if ((ev.created_at > oneHourAgo) && (ev.content.includes(targetWords[0]) || ev.content.includes(targetWords[1]))) {
        const reaction = composeReaction(ev);
        publishToRelay(relay, reaction);
        num++;
      }
    } catch (err) {
      console.error(err);
    }
  });
  return num;
};

Enter fullscreen mode Exit fullscreen mode

2. Can't I use OpenAI's API?

When I tried to use the JavaScript OpenAI library, I got an error message and had trouble. It seems that the usage has changed with the newer version. I introduced it in another article.

3. Botting with GitHub Actions

As it is, I am running the script manually, so it is not a bot. I wanted to run it automatically, so at first I rented a free server (GoogleComputeEngine) and tried to run it all the time, but the SSH connection was very unstable.
I thought, "If I just wanna run it periodically (once an hour), Why not use GitHub Actions? I decided to do so.
I found out that Actions can also use cron-like code.
This time, I just need to make a node environment and run main.js, so I asked ChatGPT to write a workflow configuration file.
like this (uncomment out as needed)

name: automate
on:
  # schedule:
  #   - cron: '0 * * * *'
  # push:
  #   branches: [ '**' ]

permissions:
  contents: read
  issues: read
  checks: write
  pull-requests: write

jobs:
  post_and_like:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18.x]
    steps:
      - uses: actions/checkout@v3

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
          cache: npm
          cache-dependency-path: ./package-lock.json

      - name: Install Dependencies
        run: npm install

      - name: Post and Like
        run: node ./main.js
        timeout-minutes: 1
Enter fullscreen mode Exit fullscreen mode

Now, every hour around 0:00 (the schedule of Actions isn't precise), Shinjiro will post and like!
Also, the scheduled execution of Actions will be automatically stopped if there is no changes in the repository for 60 days, so I also made workflow for automatic commit once a day.

name: auto-commit

on:
  workflow_dispatch:

  # schedule:
  #   - cron:  "0 15 * * *" # Carry out every 24:00 in Japan

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Set current datetime as env variable
        env:
          TZ: 'Asia/Tokyo' 
        run: echo "CURRENT_DATETIME=$(date +'%Y-%m-%d %H:%M:%S')" >> $GITHUB_ENV

      - name: Commit
        run: |
          git config --global user.email ${{ secrets.USER_EMAIL }}
          git config --global user.name ${{ secrets.USER_NAME }}
          echo -e ${{ env.CURRENT_DATETIME }} >> commit_log.txt
          git add commit_log.txt
          git commit -m "[add] 自動コミット:${{ env.CURRENT_DATETIME }}"
          git push origin main     

Enter fullscreen mode Exit fullscreen mode

Result

I got a crazy buzz on X(Twitter).
I immediately started running it on Nostr, and it became a hot topic there.
I was ranked No. 1 several times in Nostr's Buzz Word ranking, which satisfied my need for approval.
Then one day, Mr.mattn introduced me on X, and I got a lot of buzz (1.2 million impressions ❗️).
I heard that it was also flowing to X of my friend...

I have no choice but to get on this big wave!

So, I rapidly got the API of X, and started on X as well. (The number of followers has not grown much since then...)

  • Shinjiro Bot on X

But... Shinjiro is definitey popular!2 Thanks, Shinjiro!!


  1. Don't become a slave of Freedom (by Attack on Titan) 

  2. Not including political intentions 

Top comments (0)