新月実装開発部

e9f6aa66 が〜りっく UymiUhS1SIl 2010-10-18 11:05
新月実装を作りたい人はまずここで。
ある程度完成したら専用スレ立ててね。
f39d5dd2 が〜りっく UymiUhS1SIl 2010-10-18 11:38
ネタ企画 shでShinGETsuクライアント

・始めた理由
シェルスクリプトを勉強するのに目標があった方がいいから
シェルスクリプトでもHTTPサーバが作れることが分かっているから
何より、コマンド名を思いついたから。(shaku shと既存のクライアントsakuを掛けている。 一番下らない理由)

参考:シェルスクリプトでHTTPサーバ書いてみた http://emasaka.blog65.fc2.com/blog-entry-663.html
e9aaa762 白帽子 pRqBriWgNGG 2010-10-18 13:38
>>f39d5dd2
ソフトウェア和名は「錫(shaku)返せ」ですね、分かります
34d49161 anonymous vdsv8i7lEuk 2010-10-18 22:28
Jane Xeno風の専用ブラウザとか、PGP普及促進の為に、インストーラー無しのお手軽PGPソフトとか作るよ

言ってみただけですw
597a34c1 が〜りっく UymiUhS1SIl 2010-10-18 23:22
>>e9aaa762
尺取り虫かもしれません
76a6fd2e 白帽子 pRqBriWgNGG 2010-10-18 23:26
>>597a34c1
よさそうだな
c5aa8e93 が〜りっく UymiUhS1SIl 2010-10-19 04:54
>>34d49161
最終的にはそういう感じのものを作れるだけの技術を身につけた否と思っております。
Windows向け以外で。
66dcfd0e anonymous 2010-10-19 13:25
>>e9aaa762
子鬼トリオ乙
6fecc5de anonymous vdsv8i7lEuk 2010-10-19 19:42
>>c5aa8e93
私はお零れには預かれないのですね(涙ww
4939429d が〜りっく UymiUhS1SIl 2010-10-20 07:12
既出プラグイン(.js)の機能を使用するにはやっぱり吐き出すHTMLは朔のHTMLと互換の方がいいかね。
あるいは完全別にして、より使いやすい形を考えるか。
(その前にプログラム本体作れよ、と自分でツッコミ入れてみる)
a87a7c27 anonymous 2010-10-20 10:38
>>4939429d
完全別でいいと思うよ。表示の問題だけならあとからでもどうとでもなるから。
93210046 が〜りっく UymiUhS1SIl 2010-10-20 13:34
>>6fecc5de
マルチプラットフォームという選択肢もあるから安心したまへ・・・
f392cc15 が〜りっく UymiUhS1SIl 2010-10-20 18:24
とりあえず、Shakuに実装する『予定』の事としては

・新月の最新バージョンに対応(おそらくできるであろうことを確認済)
・専ブラのようなGUIモード(これはできるかどうか確認中)
・カテゴリタグの設定とカテゴリタグ別表示(要望の高い機能)

てか、Bashだけじゃなくてブラウザ表示にJSも必要じゃね?
まぁ、ブックオフで買った本があるからたぶん大丈夫だけどさ。
611dabf2 anonymous vdsv8i7lEuk 2010-10-20 20:04
>>93210046
わーい\(^ω^)/
06ae67e6 が〜りっく UymiUhS1SIl 2010-10-21 02:57
>>a87a7c27
レスサンクス。

とりあえず、以下のテキストを教材にBashスクリプトを習得した上でBashで作られたHTTPサーバを解析。
それからShakuの製作に取り組むことにする。
時間かかるけどうちの所属してるサークルの第一作目(2009年一月から現在までずっと制作中)よりかは早く完成させるつもりで居るから。

・テキスト
http://www.fireproject.jp/feature/bash/index.html
http://www.k4.dion.ne.jp/~mms/unix/shellscript/index.html
75260737 anonymous vdsv8i7lEuk 2010-10-24 00:06
>>f392cc15
新着レスが分かりやすく表示するっていうのは無理?
ソートの優先順位を、新着かどうか>書き込み日時
みたいにすれば見のがすことも無くなる

リロードする度に、ソートをすれば、番号が飛び飛びになることもないだろうし
a72298be anonymous 2011-02-08 16:40
wktk
b52eeafb が~りっくすらいす UymiUhS1SIl 2011-02-09 01:33
朔のフォークの晦にちょっと期待を寄せてみる。
新月実装開発ブームが来ればいいよ!
自分もいい加減にシェルスクリプト覚えてshakuの製作に取り掛からなくては・・・
582e031a anonymous 2011-02-09 11:36
あげるときってsakuのbranchがいいのかな
たぶん別に作ったほうがいいよね
d679522a anonymous LmvnroqnGbm 2011-02-11 01:05
node.js版新月製作中。。。
取りあえず/ping・/nodeだけ出来た。
6e022a47 anonymous 2011-02-11 02:16
HDDの中にrubyで/ping,/node,/join,/bye,/have,/getのリクエスト処理するところまではつくってあるのを見つけた
自分からは接続に行かないみたいだけど
a7a30134 白帽子@publicgw pRqBriWgNGG 2011-02-11 10:27
>>582e031a
朔と同じ場所で管理したほうがわかりやすいけど、
別にそうでなくてもいいんじゃないかな。
c84e6556 anonymous LmvnroqnGbm 2011-02-11 15:07
取りあえずping・node・join・byeだけ実装した自作のクライアントを、bbs.shingetsu.infoに繋いでみた。一応動いてるけど大丈夫かな…。
d1013857 白帽子@publicgw pRqBriWgNGG 2011-02-11 15:35
>>c84e6556
早いねえ
650d9c11 anonymous LmvnroqnGbm 2011-02-11 15:46
>>d1013857
今のところ、単にノード情報を集めて接続していってるだけです…。
新月プロトコルを見てもよく分からない(´・ω・`)
4405bb46 anonymous LmvnroqnGbm 2011-02-13 02:24
ノード管理の仕方がよく分からない。
とりあえず通信層は後回しにしようかな?
Pythonが読めれば朔を参考にできるんだけどね…。

node.js版新月もどきのログ張り付けてみる。今のところ張りぼて状態。
nshinGETsu node-v0.4.0  linux
sg_mid : load thread application
sg_com : init bbs.shingetsu.info:8000/server.cgi
sg_com : pingTo http://bbs.shingetsu.info:8000/server.cgi/ping
sg_mid : initialized database ./nsg.db
sg_com : pong from http://bbs.shingetsu.info:8000/server.cgi/ping 200
sg_com : own node : xx.xx.xx.xx:7743/server
sg_com : joinTo bbs.shingetsu.info:8000/server.cgi
sg_com : ping from 59.106.27.44
sg_com : joined bbs.shingetsu.info:8000/server.cgi 200
sg_com : nodes (1/1)
sg_com : next node : 124.37.200.179:49152/server.cgi
c8f06132 anonymous 2011-02-13 03:11
>>4405bb46
Pythonとjsって結構違うん?
fcf7c052 anonymous 2011-02-13 11:31
かっくいー>ω<
552598d1 anonymous LmvnroqnGbm 2011-02-13 12:20
>>c8f06132
あまり知らないけど見た目は大分違うと思う。
あと、インデント=ブロックってのが好きじゃない。
いつか勉強しようとは思ってるんですけどね
c3adff62 anonymous 2011-02-13 12:33
>>552598d1
そなんだ
俺はむしろインデント好きだなw
まあ勉強始めたばっかだけど
cc16fc24 白帽子@公開GW pRqBriWgNGG 2011-02-13 12:39
>>c3adff62
インデントが下手だとすごく読みにくいもんねえ。
束縛される感じはあるけどそのうち慣れると思う。
71ef52ce anonymous 2015-04-07 12:11
age
>>d679522a とは違うけどこっちもちょっとnode.jsでノード作ってみた
haveに無条件でno返すだけのハリボテだけど
11746a4f anonymous 2015-12-07 00:45
ああそうか、Markdownでは絵文字に対応してなかったんだっけorz
コードを共有するのに差支えが出るからこのままにしておこうっと。
a78f9a94 anonymous 2015-12-07 05:49
新月の新実装をClojureで書くためにいろいろ調べはじめたけど、Luminusかいろいろ変わっててびっくり。デフォルトのデータベースはHyperSQLにしたいんだけど、使えるのかな…
368b98bd anonymous 2015-12-07 06:54
@markdown
とりあえずプロジェクトを作ってみた。HyperSQLは後で足すことにする。

    lein new luminus ju +postgres +mysql +auth +cljs +swagger +war
27349a85 anonymous 2015-12-07 08:26
@markdown
>>368b98bd
PostgreSQLの設定しかないorz
とりあえずメインのMySQLだけでやり直し。

    lein new luminus ju +mysql +auth +cljs +swagger +war
aeae7070 anonymous 2015-12-07 09:38
@markdown
HyperSQLの設定はうまくいったみたい。以下は`profiles.clj`の設定。
```clojure
 {:profiles/dev  {:env {:database-url "jdbc:hsqldb:file:ju.hsqldb;user=sa;password=;hsqldb.tx=mvcc"}}
 :profiles/test {:env {:database-url "jdbc:hsqldb:file:ju.hsqldb;user=sa;password=;hsqldb.tx=mvcc"}}}
```
Webサーバーが起動されて、クライアント側のClojureScriptもバッチリ動いてる:laughing:
ブラウザのREPLもサポートされているようだ。Luminusもえらく便利になったな~
0b097efb anonymous 2015-12-07 14:59
一応/joinするところまではできた。続きは明日やろうっと。
2ab9a6dd anonymous 2015-12-08 15:27
@markdown
`/node`を打ってアクティブなノードの一覧を得ることに成功。
本当にこの使い方でいいのかしらん。

```clojure
(def active-nodes (atom (hash-set)))
(def shingetsu-server-node-name (atom "http://24.130.242.114:8888/server"))

(defn collect-nodes
  [node-name]
  (try
    (client/get (str "http://" node-name "/join/" (clojure.string/replace @shingetsu-server-node-name #"/" "+")))
    (dotimes [n 16]
      (swap!
        active-nodes
        conj
        (clojure.string/replace
          (:body (client/get (str "http://" node-name "/node")))
          #"\n$"
          "")))
    (client/get (str "http://" node-name "/bye/" (clojure.string/replace @shingetsu-server-node-name #"/" "+")))
    (catch Exception e
      nil)))

(defroutes home-routes
           ; TODO: Check the remote address.
           (GET "/server/ping" request
             (->
               (ok
                 (str
                   "PONG\n"
                   (or (get-in request [:headers "x-forwarded-for"]) (:remote-addr request))
                   ))
               (content-type "text/plain; charset=UTF-8")
               ))
           (GET "/test/join" request
             (do
               (doall
                 (pmap
                   #(collect-nodes %1)
                   ["node.shingetsu.info:8000/server.cgi"
                    "node.fuktommy.com:8000/server.cgi"
                    "rep4649.ddo.jp:8002/server.cgi"
                    "saku.dpforest.info:8000/server.cgi"]))
               (doall
                 (pmap
                   #(collect-nodes %1)
                   @active-nodes))
               (->
                 (ok (str "#:" (count @active-nodes) "\n" @active-nodes))
                 (content-type "text/plain; charset=UTF-8"))))
```
6b49d8ec anonymous 2015-12-09 10:14
/ping /node /join /byeの実装がほぼ完了。明日はいよいよファイルの取得を試してみよう。
ce639e27 anonymous 2015-12-10 08:21
ファイルの取得の前に隣接ノードへの自動接続を実装。
とはいっても/pingで接続をチェックして、新しいノードが見つかり次第/joinしてるだけなんだけど…
fad0f036 anonymous 2015-12-10 21:35
@markdown
> When Should I Not Use Yesql?
>
> When you need your SQL to work with many different kinds of database at once. If you want one complex query to be transparently translated into different dialects for MySQL, Oracle, Postgres etc., then you genuinely do need an abstraction layer on top of SQL.

https://github.com/krisajenkins/yesql

Yesqlは複数のデータベースには対応してないのかorz
61bf3927 anonymous 2015-12-11 01:42
試しに他のノードの/recentを取得してみたら壊れまくっててワロタw
デコードしてスレタイの一覧を作ってみよう。
ac3e3260 anonymous 2015-12-11 05:37
ようやく文字化けがないスレタイの一覧の取得に成功。データが壊れすぎだろう…
815623ad anonymous 2015-12-11 06:19
ノードの情報をデータベースで管理するように変更。
明日こそスレの取得を試してみよう。
クローラーさえできればゲートウェイの実装に取り掛かれるので楽しみ:grin:
2ec29131 anonymous 2015-12-11 06:29
とりあえず次に/recentのスレをダウンロードしてデータベースに保存するクローラーを作ってみよう。
a02f95e6 anonymous 2015-12-11 07:52
結局データベースのアクセスにはkormaを使うことにする。
データベースの作成はうまくいったので、次はノード管理をデータベースでやってみようっと。
6edf8b07 anonymous 2015-12-11 22:10
スレッドの取得に一応成功。次は/headを使ってもっと効率良くしてみようっと。
eb88658c anonymous 2015-12-12 00:03
@markdown
ファイル用のテーブルを作成。またどうせ後で変更するんだろうけど…
```clojure
(defn create-files-table
  [db-spec]
  (let [{:keys [id blob varchar varchar-ignorecase-unique]} (db-types db-spec)]
    (sql/db-do-commands
      db-spec
      (sql/create-table-ddl
        :files
        [:id           id]
        [:file_name    varchar-ignorecase-unique "NOT NULL"]
        [:application    varchar-ignorecase-unique "NOT NULL"]
        [:time_created "TIMESTAMP NULL"]
        [:time_first_post "TIMESTAMP NULL"]
        [:time_updated "TIMESTAMP NULL"]
        [:num_records "INTEGER DEFAULT 0"]
        [:num_deleted_records "INTEGER DEFAULT 0"]))))
```
43404a01 anonymous 2015-12-12 02:31
@markdown
どうやらクローラーができたっぽい。それでは早速ポチッとな。

```clojure
(defn get-files-with-recent-command []
  (let [records (clojure.string/split (apply str (pmap #(recent %1 "0-") @active-nodes)) #"\n")
        records (remove #(not (re-find #"^[0-9]+<>[0-9a-f]{32}<>thread_[0-9A-F]+(<>.*)?$" %)) records)
        file-names (map #(second (re-find #"^[0-9]+<>[0-9a-f]{32}<>(thread_[0-9A-F]+)(<>.*)?$" %)) records)
        file-names (clojure.set/difference (into #{} file-names) known-corrupt-files)]
    file-names))

(defn download-thread-from-node
  ([node-name file-name]
   (download-thread-from-node node-name file-name "0-"))

  ([node-name file-name range]
   (timbre/debug "download-thread-from-node:" node-name file-name range)
   (if-not (valid-node-name? node-name)
     (throw (IllegalArgumentException. "Invalid node name.")))
   (if-not (valid-file-name? file-name)
     (throw (IllegalArgumentException. "Invalid file name.")))
   (if-not (valid-range? range)
     (throw (IllegalArgumentException. "Invalid range.")))

   (try
     (let [file-id (db/get-file-id file-name)
           existing-records (and file-id (db/get-all-records-in-file-without-bodies file-id))]
       (if (and (= range "0-")
                existing-records
                (pos? (count existing-records)))
         ; Use /head to find missing records.
         (let [file (:body (client/get (str "http://" node-name "/head/" file-name "/" range) http-params))
               file (clojure.string/replace file #"(?m)^(?![0-9]+<>[0-9a-f]{32}).*$" "")
               file (clojure.string/replace file #"\r" "")
               file (clojure.string/replace file #"\n+" "\n")
               records (remove #(zero? (count %)) (clojure.string/split-lines file))
               records (map #(let [match (re-find #"^([0-9]+)<>([0-9a-f]{32})" %)]
                              {:stamp (Integer/parseInt (nth match 1)) :record-id (nth match 2)})
                              records)
               existing-records (map #(identity {:stamp (:stamp %) :record-id (:record-id %)}) existing-records)
               records (clojure.set/difference (into #{} records) (into #{} existing-records))]
           (if (empty? records)
             0
             (let [stamps (map :stamp records)
                   oldest (apply min stamps)
                   newest (apply max stamps)]
               (download-thread-from-node node-name file-name (str oldest "-" newest)))))

         ; Use the supplied range.
         (let [file (:body (client/get (str "http://" node-name "/get/" file-name "/" range) http-params))
               file (clojure.string/replace file #"(?m)^(?![0-9]+<>[0-9a-f]{32}<>).*$" "")
               file (clojure.string/replace file #"\r" "")
               file (clojure.string/replace file #"\n+" "\n")
               records (remove #(zero? (count %)) (clojure.string/split-lines file))]
           (dorun
             (pmap
               #(try
                 (let [match (re-find #"^([0-9]+)<>([0-9a-f]{32})<>(.*)$" %)
                       stamp (nth match 1)
                       record-id (nth match 2)
                       body (nth match 3)]
                   (db/add-record file-id stamp record-id body))
                 (catch Throwable _ (timbre/debug (str "download-thread-from-node: Record skipped: " %))))
               records))
           ;(if-not (valid-file? file)
           ;  (throw (Exception. "Invalid file.")))
           (count records))))
         (catch Exception e
           (timbre/error e)
           nil))))

(defn download-thread-from-all-active-nodes
  ([file-name]
   (download-thread-from-all-active-nodes file-name "0-"))

  ([file-name range]
   (if-not (valid-file-name? file-name)
     (throw (IllegalArgumentException. "Invalid file name.")))
   (if-not (valid-range? range)
     (throw (IllegalArgumentException. "Invalid range.")))
   (dorun
     (map
       #(download-thread-from-node % file-name range)
       (shuffle @active-nodes)))
   true))

(defn crawl-nodes []
  (timbre/debug "crawl-nodes")
  (try
    (let [file-names (get-files-with-recent-command)]
      (dorun (pmap #(db/add-file %) file-names)))
    (dorun
      (pmap
        download-thread-from-all-active-nodes
        (map :file-name (db/get-all-files))))
    (catch Throwable t
      (timbre/error t)
      nil)))
```
afd30e3f anonymous 2015-12-12 15:29
@markdown
クローラがようやくちゃんと動くようになりました。
/getをうまく使わないとすぐタイムアウトになっちゃいまね、これ。
/headでレスの欠損を調べて、一括でダウンロードできなかったスレは
レコードを個別にダウンロードしています。
```clojure
(defn get-files-with-recent-command []
  (let [records (clojure.string/split (apply str (pmap #(recent %1 "0-") @active-nodes)) #"\n")
        records (remove #(not (re-find #"^[0-9]+<>[0-9a-f]{32}<>thread_[0-9A-F]+(<>.*)?$" %)) records)
        file-names (map #(second (re-find #"^[0-9]+<>[0-9a-f]{32}<>(thread_[0-9A-F]+)(<>.*)?$" %)) records)
        file-names (clojure.set/difference (into #{} file-names) known-corrupt-files)]
    file-names))

(defn download-thread-from-node
  ([node-name file-name]
   (download-thread-from-node node-name file-name "0-"))

  ([node-name file-name range]
   (timbre/debug "download-thread-from-node:" node-name file-name range)
   (if-not (valid-node-name? node-name)
     (throw (IllegalArgumentException. "Invalid node name.")))
   (if-not (valid-file-name? file-name)
     (throw (IllegalArgumentException. "Invalid file name.")))
   (if-not (valid-range? range)
     (throw (IllegalArgumentException. "Invalid range.")))

   (try
     (let [file-id (db/get-file-id file-name)
           existing-records (and file-id (db/get-all-records-in-file-without-bodies file-id))]
       (if (and (= range "0-")
                existing-records
                (pos? (count existing-records)))
         ; Use /head to find missing records.
         (let [file (:body (client/get (str "http://" node-name "/head/" file-name "/" range) http-params))
               file (clojure.string/replace file #"(?m)^(?![0-9]+<>[0-9a-f]{32}).*$" "")
               file (clojure.string/replace file #"\r" "")
               file (clojure.string/replace file #"\n+" "\n")
               records (remove #(zero? (count %)) (clojure.string/split-lines file))
               records (map #(let [match (re-find #"^([0-9]+)<>([0-9a-f]{32})" %)]
                              {:stamp (Integer/parseInt (nth match 1)) :record-id (nth match 2)})
                              records)
               existing-records (map #(identity {:stamp (:stamp %) :record-id (:record-id %)}) existing-records)
               records (clojure.set/difference (into #{} records) (into #{} existing-records))]
           (if (empty? records)
             0
             (let [stamps (map :stamp records)
                   oldest (apply min stamps)
                   newest (apply max stamps)]
               (download-thread-from-node node-name file-name (str oldest "-" newest))
               (let [existing-records (map #(identity {:stamp (:stamp %) :record-id (:record-id %)}) existing-records)
                     records (clojure.set/difference (into #{} records) (into #{} existing-records))
                     stamps (map :stamp records)]
                 (dorun (map #(download-thread-from-node node-name file-name (str %)) stamps))))))

         ; Use the supplied range.
         (let [file (:body (client/get (str "http://" node-name "/get/" file-name "/" range) http-params))
               file (clojure.string/replace file #"(?m)^(?![0-9]+<>[0-9a-f]{32}<>).*$" "")
               file (clojure.string/replace file #"\r" "")
               file (clojure.string/replace file #"\n+" "\n")
               records (remove #(zero? (count %)) (clojure.string/split-lines file))]
           (dorun
             (pmap
               #(try
                 (let [match (re-find #"^([0-9]+)<>([0-9a-f]{32})<>(.*)$" %)
                       stamp (nth match 1)
                       record-id (nth match 2)
                       body (nth match 3)]
                   (db/add-record file-id stamp record-id body))
                 (catch Throwable _ (timbre/debug (str "download-thread-from-node: Record skipped: " %))))
               records))
           ;(if-not (valid-file? file)
           ;  (throw (Exception. "Invalid file.")))
           (count records))))
         (catch Exception e
           (timbre/error e)
           nil))))

(defn download-thread-from-all-active-nodes
  ([file-name]
   (download-thread-from-all-active-nodes file-name "0-"))

  ([file-name range]
   (if-not (valid-file-name? file-name)
     (throw (IllegalArgumentException. "Invalid file name.")))
   (if-not (valid-range? range)
     (throw (IllegalArgumentException. "Invalid range.")))
   (dorun
     (map
       #(download-thread-from-node % file-name range)
       (shuffle @active-nodes)))
   true))

(defn crawl-node [node-name]
  (timbre/debug "crawl-node:" node-name)
  (try
    (dorun
      (map
        #(if (some #{ node-name } @active-nodes)
          (download-thread-from-node node-name %))
        (shuffle (map :file-name (db/get-all-files)))))
    (catch Throwable t
      (timbre/error t)
      nil)))

(defn crawl-nodes []
  (timbre/debug "crawl-nodes")
  (try
    (comment let [file-names (get-files-with-recent-command)]
      (dorun (pmap #(db/add-file %) file-names)))
    (dorun
      (pmap crawl-node (shuffle @active-nodes)))
    (catch Throwable t
      (timbre/error t)
      nil)))
```
0b2675c7 anonymous 2015-12-13 02:09
@markdown
レコードの本文をVARCHARで保存してたらメモリ不足になったのでBLOBに変更してやり直し。結構たくさんたまりました。
```
(count (ju.db.core/get-all-records))
=> 252439
```
003d5e73 anonymous 2015-12-13 07:41
>>e58230ac
/pingと/joinだけなら負荷も全然軽いし大丈夫でしょう。
8cefa68a anonymous 2015-12-13 10:21
>>003d5e73
joinはネットワークの形を変える機能だよ
539165e8 anonymous 2015-12-13 10:32
>>8cefa68a
というより、/joinする相手から/join済みノードを追い出す機能

Top of this page. | <<last <<new 0 1 2

limit: 15360KB

(新月実装開発部/255/0.8MB)


Powered by shinGETsu.