Mastodonでオススメユーザーを紹介してくれるWebサービスを作った

はじめに

この記事は、Mastodon Advent Calendar 2018 の5日目です

qiita.com

 

この記事では、Mastodonのオススメユーザーを紹介してくれるWebサービスMastodon Follow Suggestion」について紹介します。

 

Mastodon Follow Suggestion とは?

Mastodonにv2.4.3から実装された /api/v1/suggestions を使用し、オススメユーザーを紹介してくれるWebサービスです。

https://mastodon-follow-suggestion.herokuapp.com/

 

Mastodonアカウントでログインし、「おすすめユーザーを見てみる」をクリックするとオススメのユーザーを一覧で見ることができます。

 

リモートフォロー用のリンクもあるので、そこからフォローすることも可能となっています。

 

フロントエンドにVue.js、バックエンドにRuby on Railsを使用し制作しました

サービス自体はHerokuを使い、運用しています。

 

実装など

 

Mastodonアカウントでのログイン部分などはRailsで処理しています。

具体的には、下記の記事のように実装しています。

 

qiita.com

 

あとは、Vue.js側でaxiosを使ってAPIへリクエストを投げてオススメのユーザーをを取得しています

 

実装としてはこれぐらいです

そのため比較的シンプルな構造になっています

 

作ろうと思ったきっかけ

今年のRuby World Conference に参加していたところ、唐突に「何かRailsでアプリを作りたい!」とったのが事のはじまり

 

で、ちょうどその時にタイムライン上でMastodonのフォローレコメンデーションについての話が流れてきたので「よし、じゃあ作ってみようか!」となり作った次第

 

おわりに

まだいろいろと手が回っていないところもありますので、まだ追加で実装する余地があるのでPRとかしてもいいのよ?

 

明日は、Foods Checker for Mastodonの紹介です

Ruby/Tkで作ったMastodonクライアント:Legion

はじめに

この記事は、Mastodon Advent Calendar 2018 の4日目の記事になります

qiita.com

 

RubyTkで制作したMastodonクライアント「Legion」について紹介します。

 

Legionって?

プログラミング言語RubyとTkというGUI開発のツールキットを使って作られたMastodonクライアントです。

 

github.com

 

Toot(公開範囲も設定可能)、ホームタイムライン、ローカルタイムライン、連合タイムラインなどに対応しています。

 

画像の投稿なども対応しており、NSFWやCWも可能です。

 

画像の表示関連は実装できておらず、そのあたりに課題が残っています。

それとSSL証明書を導入する必要もあったり……

 

.envにインスタンスのURLとアクセストークンをカンマ区切りで渡すことでマルチポスト/マルチアカウントにも対応しています。

 

あと、地味にMacでの対応もできていたり……(その辺は、のえるさんが確認してくださいました!誠にありがとうございます!)

 

この間、るびま(Rubyist Magazine)にLegionが載りました!

RegionalRubyKaigi レポート (68) 松江 Ruby 会議 09

 

インストール方法

gemとして公開してあるので、以下のコマンドで導入できます。

 

gem install legion_mastodon_client

 

あとは、legion.rbとGemfile、.envを作成し以下のように記述します。

# legion.rb
require
'bundler/setup' Bundler.require(:default) require 'legion' Legion.exec

 

# Gemfile
source "https://rubygems.org" gem 'legion_mastodon_client', '~> 0.1.1' gem 'mastodon-api', git: 'https://github.com/tootsuite/mastodon-api.git', ref: '189deb8' gem 'dotenv' gem "highline" gem 'nokogiri' gem 'rmagick' gem 'parallel'

 

# .env

MASTODON_URL=<インスタンスのURL>
MASTODON_TOKEN=<インスタンスで発行したアクセストークン>

 

あとは、bundle install して以下のコマンドを実行すればLegionを使用できます。

ruby legion.rb

 

 

おわりに

今後はGTKなどへ移行し、UIをもうちょい良いものにしたいと思いますねー

 

明日は、Mastodon User Follow Suggestion の紹介です

Mastodonを簡単に構築できるMastodonScript

はじめに

この記事は、Mastodon Advent Calendar 2018 の一日目の記事です。

qiita.com

 

Mastodonの構築やアップデートなどをよしなにしてくれるMastodon Script を紹介します。

 

Mastodon Scriptって?

ざっくりいえば、シェルスクリプトMastodonの構築やアップデート処理などを楽にしてくれるものです。

 

ソースはGitHubにて、CC0にて公開しています。

 

github.com

 

 

使い方

 

プラットフォームとしてはGoogle Cloud Platformを使用し、 non-docker環境かつUbuntu 16.04を使用している状況を想定しています。

なお、DNSなどの設定はすでに完了しているものとします。

 

まず、git clone でシェルスクリプトを落としてきます。

 

git clone https://github.com/S-H-GAMELINKS/MastodonScript.git script && cd script

 

あとは、mastodon.sh に取得したドメインを引数に渡して以下のように実行するだけ

sh mastodon.sh hogehoge.masto.com

mastodonアカウントの作成やRubyのインストールなどを自動で行います。

 

しばらくすると、mastodon アカウントへのログインを実行します。 パスワードを入力後、以下のコマンドを実行してください

echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc && echo 'eval "$(rbenv init -)"' >> ~/.bashrc
source ~/.bashrc
exit 

 

その後、再び mastodonアカウントへのログインを行い、下記のコマンドを実行します

rbenv install 2.5.1 && rbenv global 2.5.1
exit

 

最後にもう一度、mastodonアカウントへのログインを行い、以下のコマンドを実行

cd ~/live && gem install bundler && bundle install -j$(getconf _NPROCESSORS_ONLN) --deployment --without development test && yarn install --pure-lockfile

 

そのあと、postgresが起動しますので、以下のコマンドでDBを作成

CREATE USER mastodon CREATEDB;
\q

 

Niginxの設定ファイルをviで開くので、以下の内容を貼り付けてください(<ドメイン>のところは取得したドメインに書き換えてください)

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  listen 80;
  listen [::]:80;
  server_name <ドメイン>;
  root /home/mastodon/live/public;
  # Useful for Let's Encrypt
  location /.well-known/acme-challenge/ { allow all; }
  location / { return 301 https://$host$request_uri; }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name <ドメイン>;

  ssl_protocols TLSv1.2;
  ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;

  ssl_certificate     /etc/letsencrypt/live/<ドメイン>/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/<ドメイン>/privkey.pem;

  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 8m;

  root /home/mastodon/live/public;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  add_header Strict-Transport-Security "max-age=31536000";

  location / {
    try_files $uri @proxy;
  }

  location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
    add_header Cache-Control "public, max-age=31536000, immutable";
    try_files $uri @proxy;
  }
  
  location /sw.js {
    add_header Cache-Control "public, max-age=0";
    try_files $uri @proxy;
  }

  location @proxy {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";
    proxy_pass_header Server;

    proxy_pass http://127.0.0.1:3000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  location /api/v1/streaming {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";

    proxy_pass http://127.0.0.1:4000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  error_page 500 501 502 503 504 /500.html;
}

 

その後、Letsencryptが起動し、メールアドレスと規約の確認を要求されます。 メールアドレスを入力して進んでください。

これでSSL対応が完了します。

 

再びmastodonアカウントにログインし、以下のコマンドでMastodonの本番環境を構築します

cd ~/live && RAILS_ENV=production bundle exec rake mastodon:setup
exit

 

最後に、Mastodonのserviceファイル作成のためにviが三回起動しますので、以下の内容を上から順に貼り付けてください

 

[Unit]
Description=mastodon-web
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="PORT=3000"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb
ExecReload=/bin/kill -SIGUSR1 $MAINPID
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target

 

[Unit]
Description=mastodon-sidekiq
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="DB_POOL=5"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target

 

[Unit]
Description=mastodon-streaming
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="NODE_ENV=production"
Environment="PORT=4000"
ExecStart=/usr/bin/npm run start
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target

 

あとは、取得したドメインにアクセスするだけです。

 

さいごに

DNSなどの設定は必要ですが、Mastodon Scriptを使うことで比較的簡単にMastodonの構築ができるようになります

 

ちなみに、鯖缶工場というMastodonの猛者が集う場所があります。

独自機能の実装や海外サーバでの構築、自宅サーバでの運用などはそちらで相談などをしてみるよ良いかもしれません

 

Rails Girls Matsue 4thにコーチとして参加してきた

はじめに

Rails Girls Matsue 4th にコーチとして参加してきたー

railsgirls.com

 

これはその時の思ったことなどを書き綴ったもの

 

Rails Girls って?

Rails Girlsはより多くの女性がプログラミングに親しみ、アイデアを形にできる技術を身につける手助けをするコミュニティです。

 

Rails Girls - Japanese

 

 

参加する際に必要なものはノートパソコンとやる気です。

 

参加するに至った経緯

 

Mastodonで「RailsGirlsのお手伝いとかしてみたいなぁ」と呟いたのがきっかけで、「コーチやりませんか?」というお誘いがきたのが事の始まり。

 

何がきっかけで縁ができるのかわからないもんだなぁと思った。

 

何をしたか

基本的には、当日のRailsGirlsでのコーチングと設営関係。

あと、当日に使用する環境関係で二、三調べものをした感じ。

 

僕が少し遠方ということもあり、直接的なお手伝いができなくて少し心苦しい面もあったかな。

 

当日のコーチングに関しては、RailsGirlsのガイドがあるのでそれにならって進めていく感じ。

ときたまコードでエラーになったり、うまく動かないときにフォローに入ったりしたね。

 

思ったことなど

こう、会場全体がなごやかーな雰囲気でいいなぁと思った。

勉強会とか体験会とかいうと少し堅苦しい感じなってしまうこともあるけど、そういった敷居の高さみたいなものは感じられなかったね。

 

 

あとハンズオンとかと違って、RailsGirlsは「自由に弄ってみよう」って場面があってこれもいいなと思った。

 

型通りの体験だと「どうコードを弄れば、思った通りにうごくか?」っていう部分がどうしても難しくなってくる。

そういった部分を和やかな雰囲気で試せるってのは参加する側からみるとかなり良かったんじゃないかと思う。

 

さいごに

こういういいイベントが近場で開催されてるってのはやっぱりいいなぁ。

今後も開催されるときが来るだろうから、その時もぜひコーチとして参加したいなと思った。

 

あと、個人的にRailsのハンズオンとか体験会やってみたくなったねー

Mastodonに自動NSFW機能を実装した

はじめに

以前から、Mastodonでの画像のNSFW機能を使わない投稿が物議を醸していたりしたのを、ちょっとソースを弄って解消できないか試してみた。

なお、実装にあたってはGoogle Cloud Vision APIを使用しています

変更コミット&使い方

これになる

ffea62acba75a0f23be3e1f89f803da7319fe4db

これを取り込みたい方は以下のコマンドを実行してみてください。

git remote add creatodon https://github.com/S-H-GAMELINKS/mastodon.git
git fetch creatodon
git cherry-pick ffea62acba75a0f23be3e1f89f803da7319fe4db

これで自動NSFWの実装は取り込まれます。

次に、使用するGoogle Cloud Vision API のキーなどを取得します。

キーの取得に関しては、この辺の記事が参考になります。

qiita.com

qiita.com

APIキーを取得後、key.jsonmastodonのソース内に作成(.env.productionなどがある位置でOK)

作成した key.json へ取得したAPIキーの中身を貼り付けます(SSHとかWebコンソールでよしなにしてください)

あとは、.env.productionに以下のように追加。

VISION_KEYFILE="./key.json"

これで画像を投稿すると、自動的に不適切な内容のものか判定しNSFWをつけてくれます。

外したい場合は

git revert ffea62acba75a0f23be3e1f89f803da7319fe4db

と実行してください

やったこと

基本的にはコミットを見ていただければわかりますが、MediaAttachment.find を使って画像のファイル名などを取得。

その後、S3を使っているかどうかで場合分けし、それぞれのファイルパスを生成。

生成したファイルパスは配列:pathsに格納し、return させています。

その後、check_mediaメソッドでGoogleCloudVision API を使う準備を行い、受け取ってきたファイルパスをpaths.each でそれぞれ判定。

adult?やviolence?メソッドで性的な画像や暴力的な画像かを判定し、どれかが true だった場合にNSFWが有効になるようにしています。

さいごに

とりあえずの実装はこれでOKですが、今のままだと管理者が自動機NSFW機能をOFFにしたりするのが面倒かなと思います。 今後はUI側でそのあたりの変更ができるようにしていきたいと思いますね

C++/Vue.js/Webpack/FireBaseで自作のナレッジベースを作った。

C++/Vue.js/Webpack/FireBaseで自作のナレッジベースを作ってみた。

 

github.com

 

バックエンドをcpp-httplibを使ってる。

 

github.com

 

といってもC++側での処理は、assetsディレクトリ以下のindex.htmlを展開させるようにルーティングしてるだけ。

なので、C++のコード自体は非常に短い。

 

で、フロントエンドを最近はまってるVue.jsで書いた。

github.com

 

assets以下にwebpack.config.jsとpackage.jsonを作成してyarn経由でライブラリを追加してコーディングしていった。

おおよその手順は、こちらでまとめたものと同じ。

qiita.com

 

ただ、上記の記事で使ったLunaってWebフレームワークと違い、cpp-httplibはSPA風にルーティングを処理させるのができなかった(ほんとはできるかもしれない・・・・・・)

 

なので、Bootstrapのtabsを使い、タブで画面切り替えを実装。

getbootstrap.com

 

最後に、ナレッジを保存するDBとかの処理をどうしようかと考えてたんだけど

firebase.google.com

そういや、FireBase使ったことないなと思い、FireBaseでやってみた。

 

キーとかをソースに直接書きたくなかったのでdotenv-webpackを使い、環境変数で処理。

github.com

 

あとは、assets/components/web/tabs/index.vueでFireBaseのキーを使う。

github.com

 

残りのフロント周りのデザインとかはBootstrapでよしなにさせた。

 

 

 

今後はPWA対応とかを勧めていこうかと思う

Creatodonを運用しているさくらのクラウドのリージョンを変更した話

はじめに

 

2018年9月6日未明、北海道で地震が起きたのが今回の事の発端。

www.sankei.com

 

僕が管理人をしているMasotodonインスタンス「Creatodon」はさくらのクラウドの石狩データセンターをお借りして運用していた。

 

その石狩データセンターも今回の地震で被災し、データセンター内での自家発電などでとりあえず事なきを得ていると聞いた。

一応、石狩データセンターでの自家発電では電力は48時間は持つとのこと。

 

とりあえず、地震のニュースとさくらインターネットからの障害情報などを聞き、「いざとなれば別のクラウドへの移行をするべきか」と検討してた。

 

そんな時、下記の記事が見つかり、東京のデータセンターへと移行できるかもしれないと分かった。

qiita.com

 

これはその時の手順をまとめたもの。

 

実際の手順

アーカイブの作成

まず、さくらのクラウドへとログイン。

cloud.sakura.ad.jp

 

コントロールパネルから「さくらのクラウド」を選択し、「石狩第2ゾーン」を開く。

左のタブに「ストレージ」という項目があり、その中に「アーカイブ」という項目があるので、それをクリックする。

 

画面右上の「追加」をクリックし、アーカイブを作成する。

このとき「アーカイブソース」は「ディスク」を選び、現在使用しているディスクを選択する。

あとは、「作成」ボタンを押してアーカイブが作成されるのを待つ。

 

②リージョンを超えてアーカイブを移動

次に、「東京第1ゾーン」へとリージョンを切り替える。

その後、再び「ストレージ/アーカイブ」をクリック。画面右上の「追加」を同様に押す。

 

アーカイブソース」は「アーカイブ」を選択し、「石狩第2ゾーン」にチェックを入れる。

先ほど作成したアーカイブが表示されるので、それを選択肢、「作成」を押してアーカイブを作成。

 

③移行したアーカイブからディスクを作成

「ストレージ」内の「ディスク」を選択。

画面右上のの「追加」をクリックし、「ディスクソース」の項目で「マイアーカイブ」を選択。先ほど先ほど東京リージョンで作成したアーカイブを選んで、「作成」を押す。

これでリージョンを超えて、Masotodonインスタンスのデータなどを移行できた。

 

④サーバの設定

次に、東京リージョンで使用するサーバを作成する。

 

「サーバ」をクリックし、画面右上の「追加」を選択。

マイディスクというタブがあるのでそれを選び、先ほど作成したディスクを選び、「サーバプラン」「ディスクプラン」「ホスト名」を設定する。

あとは、「作成」を押してサーバが作成されるのを待つ。

 

⑤サーバのIPなどの設定

このままだと以前のリージョンでのIPアドレスなどのままでアクセスできない。

なのでIPアドレスなどを変更していく。

 

さくらのクラウドの場合、DNSの設定はリージョンをまたいで適用されているのでドメインDNS設定はそのままでいい。

 

変更するのはサーバ内のNIC設定とDNSゾーンくらい

 

まず、「グローバル」内の「DNS」を選択する。

すると現在使っているインスタンスドメインが表示されていると思う。

 

「リリースレコード」というタブがあるので、それを選択。

以下のように表示されているので

<IPアドレス>

10 <ドメイン>

v=spf1 +ip4:<IPアドレス> -all

IPアドレスの部分を先ほど東京リージョンで作成したサーバのIPアドレスに書き換える。

ちなみにIPアドレスは「サーバ」をクリックした後に表示される一覧画面の「インターフェース」という項目の下にある

 

書き換えた後は、画面右上の「反映」を押す。

これでさくらのクラウドの側でのIPの変更は完了。

 

次に、サーバ内のNICを編集する。

SSHでも「コンソール」からでもいいのでサーバへとログインする。

 

で、以下のコマンドを実行してNICを編集する

sudo vi /etc/sysconfig/network-scripts/ifcfg-eth0 

こんな感じで編集して保存すればOK

GATEWAY=11.42.231.1

DNS2=11.42.0.4

DNS1=11.42.0.3

IPADDR=11.42.231.50

IPアドレスが11.42.231.50の場合だとこんな感じ

これを保存して、サーバを再起動すれば元々のドメインインスタンスにログインできる。

 

おわりに

今後のさくらインターネットさんの対応にもよるけど、できるだけ現状を維持したいって人はこの手順でリージョンを移行すればいいと思う。

 

かわりに結構時間かかるので、待機状態とかがたまると思うのでそこは注意されたし

 

参考

qiita.com

 

cloudrop.jp