8月 2012 | 忘れたらググればいい

2012年8月26日日曜日

DQ10のキャラ情報をツイートするサービスを公開

公開

前回の記事で作っていたものをサービスとして公開した.

DQXなう!

機能

レベルアップ情報の投稿

レベルが上がった時にツイートする。

サポート仲間とうろく情報の投稿

サポート仲間に登録した時と、キッズタイムの15分前 (平日は15:45,土日は12:45) にツイートする。

アカウントの認証方法

懸念していたアカウントの認証は, フリーコメント欄にtwitterのIDを書かせることによって実現した.

ゲーム内のフリーコメント欄に書いたメッセージは, キャラの公開ページのメッセージ欄に反映される. 従って,ここにtwitterIDを書かせるようにすれば,このキャラの持ち主のtwitterアカウントを確認することができる.

ちなみに screenname (@fukubayaとか) は変更可能なので認証には使わない.

今後の予定

ツイートのフォーマットが固定なので,各自設定できるようにしたい, けど,この実装でこの一週間プレイできなかったので, まずは久しぶりにプレイしたい.レベル上げする.

2012年8月14日火曜日

DQ10のレベルアップを自動でツイート

レベルが上がると自動でTwitterにツイート

レベルが上がると自動でツイートする.新たに覚えた呪文がある場合はそれも含める.

仕組み

今回のドラクエは,オンラインになったのでインターネットとの連携もあり, プレイヤー専用のサイトとして,「目覚めし冒険者の広場」が用意されている.

目覚めし冒険者の広場-ドラゴンクエストⅩプレイヤー専用サイト

このサイトでログインすると, プレイヤー同志の交流ができたり,自分のキャラの状況を確認できるようになっている. このサイトで公開の設定をすると,自分のキャラのステータスをログインしていないユーザにも公開できるようになっている.

ふくばやのTOP|目覚めし冒険者の広場
僕のキャラの公開ページ.TOPとステータスはインターネットから誰でも見られる.各種SNSボタンで共有も可能.

要はこのページを15分ごとにチェックし,レベルが上がっていたらツイートする,というだけ. ただし,転職をするとレベルが下がったり上がったりする (レベルは職業ごとに違う) ので, 職業が変わっていないかはチェックしておかないといけない (転職した場合もツイートするようにしたけど,まだ転職していないのでツイートされてはいない).

実装

実装には,Google App Engine (Python) を使った.特に難しいことはしていない.

ステータス情報を取得するモジュール: python-dqx

上記「目覚めし冒険者の広場」からステータス情報を取得してくるPythonモジュールを作った.

fukubaya/python-dqx · GitHub
github

使い方

>>> from dqx import dqx
>>> dqx_user = dqx.User('499148186426')
# http://hiroba.dqx.jp/sc/character/XXXXXXXXXXXX の XXXXXXXXX を文字列で指定

>>> print dqx_user.name
None
# オブジェクト作成直後は情報なし

>>> dqx_user.retrieve_and_update()
# サイトから情報を取得しオブジェクトを更新.

>>> print dqx_user.uid
499148186426
# サイトでのID

>>> print dqx_user.title
初心者
# かたがき

>>> print dqx_user.name
ふくばや
# なまえ

>>> print dqx_user.cid
XH349-176
# キャラID

>>> print dqx_user.race
ドワーフ
# 種族

>>> print dqx_user.sex
男
# 性別

>>> print dqx_user.job
僧侶
# 職業

>>> print dqx_user.level
17
# レベル

>>> print dqx_user.imglastupdate
2012-08-12 06:11:00
# 画像の最終更新日

>>> print dqx_user.welcomefriend
ヤリ装備で攻撃力+10です。おはらい可。
# サポート仲間とうろく状況のメッセージ.とうろくしていない場合はNone

>>> print dqx_user.message
みせってい
# メッセージ


>>> print dqx_user.equipment
みぎて:せいどうのやり, ひだりて:(せいどうのやり), アタマ:せいどうのかぶと, からだ上:うろこのよろい上+1, からだ下:うろこのよろい下, ウデ:せいどうのこて, 足:うろこのブーツ, 顔アクセ:そうびなし, 首アクセ:そうびなし, 指アクセ:そうびなし, 他アクセ:そうびなし, しょくにん:銅の錬金ランプ☆☆☆
# そうび

>>> print dqx_user.equipment.rhand
せいどうのやり
# そうびのみぎて

>>> print dqx_user.equipment.lhand
(せいどうのやり)
# そうびにひだりて
# 他は head, ubody, lbody, arm, foot, faceacc, neckacc, fingacc, othacc, art

>>> print dqx_user.location
サーバー:サーバー16, フィールド:岳都ガタラ
# いる場所

>>> print dqx_user.location.server
サーバー16
# いる場所のサーバー

>>> print dqx_user.location.field
岳都ガタラ
# いる場所のフィールド

>>> print dqx_user.parameter
さいだいHP:66, さいだいMP:38, こうげき力:57, しゅび力:59, こうげき魔力:5, かいふく魔力:48, ちから:36, すばやさ:43, みのまもり:37, きようさ:34, みりょく:23, おしゃれさ:31, おもさ:133
# パラメータ

>>> print dqx_user.parameter.maxhp
66
# さいだいHP
# 他は maxmp, attack, defend, mattack, mhealing, power, speed, guard, dext, charm, appearance, weight 

>>> print dqx_user.skillpoint
{u'\u30e4\u30ea': 3, u'\u30b9\u30c6\u30a3\u30c3\u30af': 3, u'\u68cd': 3, u'\u3057\u3093\u3053\u3046\u5fc3': 12, u'\u76fe': 0}
# スキルポイント.辞書形式.

>>> print dqx_user.skillpoint[u'ヤリ']
3

>>> print dqx_user.skills[u'しんこう心']
[u'\u304a\u306f\u3089\u3044']
# とくぎ.辞書形式で中身はリスト.

>>> print dqx_user.skills[u'しんこう心'][0]
おはらい

>>> print dqx_user.skilleffects
{u'\u30e4\u30ea': [u'\u3053\u3046\u3052\u304d\u529b+10']}
# スキル効果.辞書形式で中身はリスト.

>>> print dqx_user.skilleffects[u'ヤリ'][0]
こうげき力+10

>>> print dqx_user.spells
[u'\u30db\u30a4\u30df', u'\u30ad\u30a2\u30ea\u30fc', u'\u30ea\u30db\u30a4\u30df', u'\u30b6\u30e1\u30cf', u'\u30b6\u30aa', u'\u30de\u30db\u30ea\u30fc', u'\u30ba\u30c3\u30b7\u30fc\u30c9']
# じゅもん.リスト形式.

>>> print dqx_user.spells[0]
ホイミ

存在しないユーザの情報を取得しようとした場合はエラーを返す.

>>> from dqx import dqx
>>> noexistent_user = dqx.User('000000')
# 存在しないユーザ
>>> noexistent_user.retrieve_and_update()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "dqx/dqx.py", line 54, in retrieve_and_update
    self.update_profile(profile_res.read())
  File "dqx/dqx.py", line 66, in update_profile
    checkErrorPage(soup)
  File "dqx/dqx.py", line 295, in checkErrorPage
    raise ParseError('%s' % (getErrorMessage(error[0])))
dqx.dqx.ParseError: キャラクターが存在しません。
>>>

ログインユーザのみに公開のユーザの場合は,ログインページにリダイレクトされるので, エラーを返す.

>>> from dqx import dqx
>>> hidden_user = dqx.User('XXXXXX')
# 非公開のユーザ
>>> hidden_user.retrieve_and_update()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "dqx/dqx.py", line 52, in retrieve_and_update
    raise RetrieveError(u'redirected from %s to %s' % (self.url_profile, profile_res.geturl()))
dqx.dqx.RetrieveError: redirected from http://hiroba.dqx.jp/sc/character/XXXXXX/ to https://secure.square-enix.com/account/app/svc/login?...
>>> 

利用例:サポート仲間とうろく状況のツイート

このモジュールを利用して,サポート仲間にとうろくしている間は自分の状況をキッズタイムの15分前 (平日は15:45,土日は12:45) にツイートするようにした.よかったらやとってやってください.

サービス化したいんだけど...

自動ツイート機能は,一応,自分以外の誰でも使えるように実装してあるけど, 今のところDQXのユーザとツイッターアカウントが同じ人のものであると確認するうまい方法がない (他人のキャラのステータスを自分のものとして勝手にツイートしたりできてしまう) ので一般公開ができていない. 「あしあと伝言板」にツイッターアカウントを申告してもらうようにして,利用開始時に確認させれば可能かもしれないけど,登録がちょっと面倒だな... あとGoogle App Engineの無料枠だとそれほど収容できないかも.


ドラゴンクエストX 目覚めし五つの種族 オンライン(通常版)
スクウェア・エニックス (2012-08-02)
売り上げランキング: 7

2012年8月9日木曜日

bloggerにZenbackを導入+デザインをカスタマイズ

Zenbackを導入

ブログに関連記事やtwitter,facebookのコメントなどを表示させるブログパーツのZenbackを導入した.

Zenbackであなたのブログに全てのフィードバックを。

bloggerへの導入は以下のサイトを参考に.

Blogger での zenback 利用方法 | slumbers

ただし,位置は footer のあとにしたかったので,挿入位置は以下に.

...
    </div>
  </div>

<b:if cond='data:blog.pageType == &quot;item&quot;'>
<!-- X:S ZenBackWidget --><script type='text/javascript'>
// <![CDATA[
document.write(unescape(...));
// ]]>
</script><!-- X:E ZenBackWidget -->
</b:if> 

</b:includable>
<b:includable id='status-message'>
  <b:if cond='data:navMessage'>
...

デザインをカスタマイズ

このブログでは,色彩を #6bd を基調にしているけど, デフォルトのパーツは色がバラバラ. ということで,CSSをイジってカスタマイズした.

以下のCSSをテンプレートの適当なところに追加した. 色以外にも少し修正してある.

  • 「関連する記事」と「関連するみんなの記事」のアイコンは背景が黄緑色で塗られていて, CSSを変更しただけでは使えないので, どんな背景でも使えるようにバックを透明に修正したものを使う (なおtwitterのアイコンはすでに背景が透明になっている).
  • ラベルの幅がまちまちなので,一番長くなるはてなブックマークに合わせて 175px にしておいた. 数が増えると幅が長くなるので一応 min-width として指定した.
  • facebookだけラベルの高さが違うので全部 1.8em に統一した.

アイコン

icon-article-trans.png

icon-link-trans.png

CSS

#zenback-widget #zenback-related-article .zenback-module-label {
    background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2ewfWFOx0JUrGZKRlCCxisIiBJtaIyXckV80qaKZ4HjYOFamWLnOiO8Rzaowl49K23N6xpcbSWDKSVlNMd5tP5BAJ6L0uv5ggPWGIu7Ilz6IGW6jaX4VORbeBvJuEuWM-igMrvcBH5cpe/s1600/icon-article-trans.png) !important;
    background-color: #6bd !important;
    min-width: 175px;
    height: 1.8em; // 2.0em * 0.9
}
#zenback-widget #zenback-related-article .zenback-module-content {
    border-color: #6bd !important;
}
#zenback-widget #zenback-related-links .zenback-module-label {
    background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhP1xAkVBl3zGreivMJHxw12_hRBYEK8WDLBp8Lh0crvv66ynch9DHi7rX2MbsLR6n-TvYuI9EqxJzwQV3L2Tr46_SRaqjx1a2hPA-CbvlPmrxela4zol-6GfOZrNwhTA0A4-3aVQMHpEjB/s1600/icon-link-trans.png) !important;
    background-color: #6bd !important;
    min-width: 175px;
    height: 1.8em; // 2.0em * 0.9
}
#zenback-widget #zenback-related-links .zenback-module-content {
    border-color: #6bd !important;
}
#zenback-widget #zenback-twitter .zenback-module-label {
    background-color: #6bd !important;
    min-width: 175px;
    height: 1.8em; // 2.0em * 0.9
}
#zenback-widget #zenback-twitter .zenback-module-content {
    border-color: #6bd !important;
}
#zenback-widget #zenback-hatena-bookmark .zenback-module-label {
    background-color: #6bd !important;
    min-width: 175px;
    height: 1.8em; // 2.0em * 0.9
}
#zenback-widget #zenback-hatena-bookmark .zenback-module-content {
    border-color: #6bd !important;
}
#zenback-widget #zenback-facebook-comment .zenback-module-label {
    background-color: #6bd !important;
    min-width: 175px;
    height: 1.8em; // 2.0em * 0.9
}
#zenback-widget #zenback-facebook-comment .zenback-module-content {
    border-color: #6bd !important;
}
#zenback-widget #zenback-powered {
    border-top: 1px solid #6bd !important;
}
#zenback-widget #zenback-powered img {
    background-color: #6bd !important;
}

カスタマイズ完了

CSSを適用して以下のようになった.少しは統一感が増しただろうか.