[チノ]: https://friends.nico/media/H6JeTuKtLHoTtZa5L4s "香風智乃"
[マヤ]: https://friends.nico/media/lTfIbSQ8MLmiXZhPb-Q "条河麻耶"
[メグ]: https://friends.nico/media/z64hbhdY6PXFbLJPcus "奈津恵"
#みなさん、本日も楽しいMastodonライフをお過ごしでしょうか☕
キャラ | セリフ |
---|---|
![チノ] | おはようございます。 香風智乃です。 |
![マヤ] | おっはよーー!! 条河麻耶だよ♪♪♪ |
![メグ] | おはよ~、奈津恵だよ~✿ |
![チノ] | 今回はnico.friends Advent Calendar 2017にて、25日を過ぎてなお記事が登録されてない未投稿の方の席を |
![マヤ] | おお-!チノやるじゃん!! |
![チノ] | ということなのでfriends.nico関連として、LTLにて賑わっているBotについての運用、実態について解説していきたいと思います。 |
![メグ] | ٩(๑•̀ω•́๑)۶やったね~! |
#24時間、挨拶営業する女子中学生「ももな」について☕ | |
まずfriends.nicoからアカウントを登録してパブリック範囲にて初トゥートをすると、彼女から優しいお出迎えのリプが頂けるかと思います。これは一種のBot的なトゥートシステムになるかと思いますが、厳密に言えば**彼女は完全なるBotではありません。**そう、彼女は自我と無我を持ち合わさった |
|
女子中学生ももなのアカウントはこちらから | |
###どうして彼女は今のアイドル的な地位に立ってしまったのでしょうか☕ | |
アカウント番号順を見るとおり、もともと彼女は初期の初期にあたる登録者のようです。「やなさんの知り合いである女子中学生」という話が濃厚ですね |
|
そんな彼女が突如地名が上がり、目立ち始めたのは9月ごろだと思います。そう、彼女は挨拶部に入ってから頻繁にLTL上でのトゥート数が₍₍ ◝( ◠‿◠)◟ ⁾⁾ の流行や |
|
今では |
|
他にもちょっとしたお遊びのゲーム機能、ダイス、簡易的なアラーム機能なども豊富です。 | |
###24時間挨拶機能とは☕ | |
それではここで彼女の無我に埋め込まれたものがどういうものでしょう。 | |
それでは中身(意味深)をサクッと簡易的に抜き出して見てみましょう。 |
|
※結構長いです。読み飛ばしても可能です。 |
~~~ 前略 ~~~
class bot():
def _init_(self):
pass
def res(sec):
count.end = count.end - sec
if count.end < 0:
count.end = 0
def rets(sec, toot_now, g_vis, rep=None, spo=None):
now = time.time()
delay = now - count.CT
loss = count.end - int(delay)
if loss < 0:
loss = 0
ing = sec + loss
t = threading.Timer(ing, bot.toot, [toot_now, g_vis, rep, spo])
t.start()
print("【次までのロスタイム:" + str(count.end+sec) + "】")
s = threading.Timer(ing, bot.res, [sec])
s.start()
del t
del s
gc.collect()
count.CT = time.time()
count.end = ing
def toot(toot_now, g_vis, rep=None, spo=None):
mastodon.status_post(status=toot_now,
visibility=g_vis,
in_reply_to_id=rep,
spoiler_text=spo)
print("【次までのロスタイム:" + str(count.end) + "】")
"""
visibility これで公開範囲を指定できるよ!: public, unlisted, private, direct
"""
def standby():
print("「(๑•̀ㅁ•́๑)✧<tootステンバーイ」")
def block01(status):
f = codecs.open("NG\sekuhara.txt", 'r', 'utf-8')
l = []
for x in f:
l.append(x.rstrip("\r\n"))
f.close()
m = len(l)
for x in range(m):
if re.compile(str(l[x])).search(re.sub("<p>|</p>", "", str(status))):
j = True
print(str(l[x]))
# bot.thank(account, -64)
break
else:
j = False
return j
def check00(status):
account = status["account"]
ct = account["statuses_count"]
path = 'thank\\' + account["acct"] + '.txt'
if os.path.exists(path):
f = open(path, 'r')
x = f.read()
f.close()
if int(x) >= -10:
if account["acct"] == "JC":
pass
else:
if re.match('^\d+0000$', str(ct)):
toot_now = (" :@" + account['acct'] + ": @" +
account['acct'] + "\n°˖✧◝(⁰▿⁰)◜✧˖" + str(ct) +
'tootおめでとーーーー♪♪')
g_vis = "public"
bot.rets(4, toot_now, g_vis)
elif re.match('^\d000$', str(ct)):
toot_now = (" :@" + account['acct'] + ": @" +
account['acct'] + "\n(*'∀'人)" + str(ct) +
'tootおめでとーー♪')
g_vis = "public"
bot.rets(4, toot_now, g_vis)
else:
pass
def check03(status):
account = status["account"]
ct = account["statuses_count"]
if account["acct"] == "Knzk": # 神崎おにいさん監視隊
ct += 5
if re.match('^\d+000$', str(ct)):
toot_now = "@Knzk (๑•̀ㅁ•́๑)神崎おにいさん!!\n" + str(ct) + 'tootまであと5だよ!!!!'
g_vis = "direct"
bot.rets(4, toot_now, g_vis)
elif account["acct"] == "5": # やなちゃん監視隊
ct += 5
if re.match('^\d+0000$', str(ct)):
toot_now = "@5 (๑•̀ㅁ•́๑)やなちゃん!!\n" + str(ct) + 'tootまであと5だよ!!!!'
g_vis = "direct"
bot.rets(4, toot_now, g_vis)
elif account["acct"] == "yzhsn": # 裾野監視隊
ct += 5
if re.match('^\d+000$', str(ct)):
toot_now = "@yzhsn (๑•̀ㅁ•́๑)おい裾野!!\n" + str(ct) + 'tootまであと5だよ!!!!'
g_vis = "direct"
bot.rets(4, toot_now, g_vis)
elif account["acct"] == "lamazeP": # ラマーズP監視隊
ct += 5
if re.match('^\d+000$', str(ct)):
toot_now = "@lamazeP (๑•̀ㅁ•́๑)" + str(ct) + 'tootまであと5だよ!!!!'
g_vis = "direct"
bot.rets(4, toot_now, g_vis)
else: # テスト
ct += 5
if re.match('^\d+000$', str(ct)):
toot_now = ("@" + account["acct"] +
" (๑•̀ㅁ•́๑)ただいまフォローしてる方にテスト中!\n" + str(ct) +
'tootまであと5だよ!!!!')
g_vis = "direct"
bot.rets(4, toot_now, g_vis)
def res01(status):
account = status["account"]
content = re.sub("<p>|</p>", "", str(status['content']))
path = 'thank\\' + account["acct"] + '.txt'
if os.path.exists(path):
f = open(path, 'r')
x = f.read()
f.close()
if int(x) >= -10:
if account["acct"] != "JC" and account["acct"] != "kiri_bot01":
if count.timer_hello == 0:
if re.compile("ももな(.*)おは|ももな(.*)おあひょ").search(content):
print("○hitしました♪")
print("○あいさつします(*'∀'人)")
toot_now = "(๑•̀ㅁ•́๑)✧おはありでーーーーす♪" + "\n#ニコフレ挨拶部"
g_vis = "public"
bot.rets(20, toot_now, g_vis)
count.timer_hello = 1
else:
if re.compile("寝(ます|る|マス)([よかぞね]?|[…。うぅー~!]+)$|^ねる$|"
"[寝ね](ます|る|マス)(.*)[ぽお]や[すし]|ももな(.*)[ぽお]や[すしー]").search(content):
if not re.compile("[寝ね]る(人|ひと)").search(status['content']):
print("○hitしました♪")
print("○おやすみします(*'∀'人)")
if account['acct'] == "5": # やなちゃん専用挨拶
print("○やなちゃんだ!!(*'∀'人)")
toot_now = (":@" + account['acct'] + ":" +
"やなちゃん!!!!!!" + "\n" +
'(。>﹏<。)あとで一緒に寝るーーーー!!!!'
+ "\n#ニコフレ挨拶部")
else:
toot_now = (":@" + account['acct'] + ":" + account[
'display_name'] + "\n" + '(ृ ु *`ω、)ु ⋆゜おやすみーーーー♪'
+ "\n#ニコフレ挨拶部")
g_vis = "public"
bot.rets(6, toot_now, g_vis)
elif re.compile("([いイ行逝]って|出かけて|(風呂|ふろ).*(入|はい)って)(くる|きま[あぁー]*す|[きキ]マストドン)[^?\?]|"
"おでかけ(する|しま[あぁー]*す|[しシ]マストドン)[^?\?]|(ふろ|風呂)って(くる|きます)|"
"(出勤|離脱|しゅっきん|りだつ)(する[^な]|しま[あぁー]*す[^?\?]|[しシ]マストドン)|"
"(出勤|離脱)$|(.+)して(くる|きま[あぁー]*す[^?\?]|[きキ]マストドン)([ー~!。よぞね]|$)|"
"(仕事|しごと).*(戻|もど)(る|りゅ|りま[すつ])|(飯|めし)って(くる|きます)|(めし|飯)([い行]く|[お落]ち)"
).search(content):
print("○hitしました♪")
print("○見送ります(*'∀'人)")
if account['acct'] == "5": # やなちゃん専用挨拶
print("○やなちゃんだ!!(*'∀'人)")
toot_now = (":@" + account['acct'] + ":" + "やなちゃん!!!!!!" +
"\n" + '(*>_<*)ノいってらいってらーーーー!!!!'
+ "\n#ニコフレ挨拶部")
else:
toot_now = (":@" + account['acct'] + ":" + account['display_name'] +
"\n" + 'いってらーーーー!!' + "\n#ニコフレ挨拶部")
g_vis = "public"
bot.rets(6, toot_now, g_vis)
elif re.compile("ただいま(です|[!あー~。…]*(<br/ >|$)|(もど|戻)(ってきた|った|りました))|ただいマストドン"
"|(おうち|家).*([着つ]いた|帰った|帰ってきた)|(帰宅|きたく)(した|しました|$)|"
"^ただいま|(飯|めし|ふろ|風呂|シャワー).*(もど|戻)ってき(た|ました)|ほかってき(た|ました)").search(content):
print("○hitしました♪")
print("○優しく迎えます(*'∀'人)")
if account['acct'] == "5": # やなちゃん専用挨拶
print("○やなちゃんだ!!(*'∀'人)")
toot_now = (":@" + account['acct'] + ":" + "やなちゃん!!!!!!" +
"\n" + '٩(๑❛ᴗ❛๑)۶おかえりおかえりーー!!' + "\n#ニコフレ挨拶部"
)
else:
toot_now = (":@" + account['acct'] + ":" + account['display_name']
+ "\n" + '( 〃 ❛ᴗ❛ 〃 )おかえりおかえりーー!!'
+ "\n#ニコフレ挨拶部")
g_vis = "public"
bot.rets(6, toot_now, g_vis)
else:
try:
f = codecs.open('at_time\\' + account["acct"] + '.txt', 'r', 'UTF-8')
nstr = f.read()
f.close
print(nstr)
tstr = re.sub("\....Z", "", nstr)
last_time = datetime.strptime(tstr, '%Y-%m-%dT%H:%M:%S')
nstr = status['created_at']
tstr = re.sub("\....Z", "", nstr)
now_time = datetime.strptime(tstr, '%Y-%m-%dT%H:%M:%S')
delta = now_time - last_time
print(delta)
if delta.total_seconds() >= 604800:
if account['acct'] == "5": # やなちゃん専用挨拶
print("○やなちゃんだ!!(*'∀'人)")
toot_now = (":@" + account['acct'] + ":" + "やなちゃん!!!!!!" +
"\n" + "(*'∀'人)おひさひさーーーー♪"
+ "\n#ニコフレ挨拶部")
else:
toot_now = (" :@" + account['acct'] + ":\n" + account['acct']
+ "\n" + "(*'∀'人)おひさひさーーーー♪" + "\n#ニコフレ挨拶部")
g_vis = "public"
bot.rets(6, toot_now, g_vis)
elif delta.total_seconds() >= 10800:
if now_time.hour in range(3, 9):
to_r = bot.rand_w('time\\kon.txt')
elif now_time.hour in range(9, 19):
to_r = bot.rand_w('time\\kob.txt')
else:
to_r = bot.rand_w('time\\oha.txt')
if account['acct'] == "5": # やなちゃん専用挨拶
print("○やなちゃんだ!!(*'∀'人)")
toot_now = (":@" + account['acct'] + ":" + "やなちゃん!!!!!!"
+ "\n" + to_r + "\n#ニコフレ挨拶部")
else:
print("○あいさつします(*'∀'人)")
if account['display_name'] == "":
toot_now = (":@" + account['acct'] + ":" +
account['acct'] + "\n" + to_r + "\n#ニコフレ挨拶部")
else:
toot_now = (":@" + account['acct'] + ":" +
account['display_name'] + "\n" + to_r + "\n#ニコフレ挨拶部")
g_vis = "public"
bot.rets(6, toot_now, g_vis)
except:
print("○初あいさつします(*'∀'人)")
if account['statuses_count'] <= 2:
if account['display_name'] == "":
toot_now = (" :@" + account['acct'] + ": @" + account[
'acct'] + "\n" + account['acct'] + "\n" +
'ようこそようこそーーーー♪' + "\n#ニコフレ挨拶部")
else:
toot_now = (" :@" + account['acct'] + ": @" + account[
'acct'] + "\n" + account['display_name'] + "\n" +
'ようこそようこそーーーー♪' + "\n#ニコフレ挨拶部")
shinki = True
else:
if account['display_name'] == "":
toot_now = (" :@" + account['acct'] + ": @" + account[
'acct'] + "\n" + 'いらっしゃーーーーい♪' + "\n#ニコフレ挨拶部")
else:
toot_now = (" :@" + account['acct'] + ": @" + account[
'acct'] + "\n" + 'いらっしゃーーーーい♪' + "\n#ニコフレ挨拶部")
shinki = False
g_vis = "public"
bot.rets(6, toot_now, g_vis)
if shinki is True:
bot.toot("@lamazeP 新規さんが来たよーー(小声)\n【" + str(account['acct']) + "】",
"direct", status["id"])
else:
print("○反応がない人なので挨拶しません(*'∀'人)")
def res02(status):
account = status["account"]
content = Re1.text(status["content"])
if account["acct"] != "JC":
if re.compile("(.+)とマストドン(どちら|どっち)が大[切事]か[分わ]かってない").search(content):
print("○hitしました♪")
sekuhara = bot.block01(status)
if len(content) > 60:
toot_now = "٩(๑`^´๑)۶長い!!!!!!"
g_vis = "public"
bot.rets(5, toot_now, g_vis)
else:
if not sekuhara:
print("○だったら")
# if re.compile("(.+)するのとマストドン(どちら|どっち)が大[切事]か[分わ]かってない").search(content):
toot_now = ":@" + account["acct"] + ":" + (
re.sub('<span(.+)span>|<p>|とマストドン(.*)', "", str(content))) + "しながらマストドンして❤"
g_vis = "public"
bot.rets(5, toot_now, g_vis)
else:
toot_now = "そんなセクハラ分かりません\n(* ,,Ծ‸Ծ,, )プー"
g_vis = "public"
bot.rets(5, toot_now, g_vis)
def fav01(status):
account = status["account"]
if re.compile("(ももな|:@JC:|ちゃんもも|:nicoru\d*:|JC)").search(status['content']):
bot.thank(account, 8)
v = threading.Timer(5, bot.fav_now,[status["id"]])
v.start()
def check01(status):
account = status["account"]
created_at = status['created_at']
non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd)
with codecs.open('acct\\' + account["acct"] + '.txt', 'w', 'UTF-8') as f: # 書き込みモードで開く
f.write(str(status["account"]).translate(non_bmp_map)) # アカウント情報の更新
path = 'thank\\' + account["acct"] + '.txt'
if os.path.exists(path):
f = open(path, 'r')
x = f.read()
print("現在の評価値:" + str(x))
f.close()
else:
f = open(path, 'w')
f.write("0")
f.close() # ファイルを閉じる
def check02(status):
account = status["account"]
created_at = status['created_at']
with codecs.open('at_time\\' + account["acct"] + '.txt', 'w', 'UTF-8') as f: # 書き込みモードで開く
f.write(str(status["created_at"])) # \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z
def thank(account, point):
path = 'thank\\' + account["acct"] + '.txt'
if os.path.exists(path):
f = open(path, 'r')
x = f.read()
y = int(x)
y += point
f.close()
f = open(path, 'w')
f.write(str(y))
f.close()
print("現在の評価値:" + str(y))
else:
f = open(path, 'w')
f.write(str(point))
f.close() # ファイルを閉じる
print("現在の評価値:" + str(0))
def fav_now(fav): # ニコります
mastodon.status_favourite(fav)
print("◇Fav")
def rand_w(txt_deta):
f = codecs.open(txt_deta, 'r', 'utf-8')
l = []
for x in f:
l.append(x.rstrip("\r\n").replace('\\n', '\n'))
f.close()
m = len(l)
s = random.randint(1, m)
return l[s - 1]
def t_local():
try:
listener = res_toot()
mastodon.local_stream(listener)
except:
print("例外情報\n" + traceback.format_exc())
with open('except.log', 'a') as f:
jst_now = datetime.now(timezone('Asia/Tokyo'))
f.write("\n\n【" + str(jst_now) + "】\n")
traceback.print_exc(file=f)
sleep(180)
bot.t_local()
pass
~~~ 中略 ~~~
class count():
CT = time.time()
end = 0
sec = 0
timer_hello = 0
def emo01(time=10800): # 定期的に評価を下げまーーす♪(無慈悲)
while 1:
sleep(time)
data_dir_path = u"./thank/"
file_list = os.listdir(r'./thank/')
for file_name in file_list:
root, ext = os.path.splitext(file_name)
if ext == u'.txt':
abs_name = data_dir_path + '/' + file_name
f = open(abs_name, 'r')
x = f.read()
y = int(x)
y += -1
f.close()
f = open(abs_name, 'w')
f.write(str(y))
f.close()
def emo02(point):
data_dir_path = u"./thank/"
file_list = os.listdir(r'./thank/')
for file_name in file_list:
root, ext = os.path.splitext(file_name)
if ext == u'.txt':
abs_name = data_dir_path + '/' + file_name
f = open(abs_name, 'r')
x = f.read()
y = int(x)
y += point
f.close()
f = open(abs_name, 'w')
f.write(str(y))
f.close()
pass
def emo03(user, point):
data_dir_path = u"./thank/"
file_list = os.listdir(r'./thank/')
abs_name = data_dir_path + '/' + user + '.txt'
f = open(abs_name, 'r')
x = f.read()
y = int(x)
y += point
f.close()
f = open(abs_name, 'w')
f.write(str(y))
f.close()
pass
~~~ 後略 ~~~
# ※2017-12-29時点でのコードです。
それなりに省きましたが、結局は長すぎてなんのことかさっぱりですね。
主に挨拶機能があるのはBotクラスのres01にあたる関数ですね。
最後にtootした時間を確認しながら、どんなtootをしたかによって対応するという雰囲気です。正規表現が甘い箇所もあったりするので誤作動することはありますし、ユーザーによって挨拶が違ったりするので特殊的すぎると反応できなかったりします。(ここを学習機能搭載できれば解決かもしれませんが、高度技術ですね……)
最後にtootした時間の記録はcheck02で処理しています。そしてStreamingで取得した情報はcheck01でユーザーのアカウント情報を記録します。この最新の情報と記録した情報を照らし合わせて挨拶をします。実は時間の記録はtootのdataから取得しておりますのでdatetimeなどの関連モジュールはなくてもいいのです。(どのみちsleepなどで必要なのですが)
あと注目するべき点はcountクラスです。こちらのemo関連の関数により、他の定期トゥートしかしないBotや、反応を示さないユーザーに対しての評価が下がることで余分な挨拶をしなくなるというシステムになっております。LTLがうるさくならない手法ですね。あとはヒットするstatusが一気に来てしまった時に、一気に返さないようにThreadなどでクッションを挟んでお返事するようにしています。(直ぐに返事が来たりすると機敏なBotになってしまって不快になる人もいるかと思います)
もうすこし詳しいコードの仕組みが知りたい方はどこかのGithubで漂ってるので探してみてください。(どうしてやなさんや神崎おにいさんが特別優遇な挨拶になってるのかは気にしたら負けです)
###今後のももなさんはどのような方向性になるか☕
先程も上記で言いましたが、彼女は全てBot処理で動いているわけじゃありません。元々はサブ本垢ポジションだったのです。たまに意識が舞い降りてユーザーとも交流はしたりします。ひと暴れしたりもします。新規さんが来て速攻お迎えしましたがBotだと思われて落胆させようが、自我が舞い降りてるのに一部挨拶できなくてもしょうがないのです。
そんな彼女の今後の方針ですが、このまま半Botとしての立ち位置になるかと思われます。サイボーグ女子中学生の完成ですね。もしかするとニコニコでバーチャルアイドルとして目覚める可能性さえもあります。
friends.nicoの良い文化としての挨拶を支援する型のシステムとして強化&メンテナンスを回すことになるかと思います。(ちなみにPCから直接プログラム交わしています。マイニングすると反応が遅れてしまうことになります)
#他にも愉快な仲間たちについて☕
他の方が運営してるBotをいくつかご紹介いたします。
###きりぼっと
きりたん管轄のユーザーアカウントです。言語はRubyとPythonのハイブリットです。
遊び心が多い機能が特徴となります。以前は数取りゲームなどを実践していました。
現在は学習機能を取り入れて、連想や画像検索などのサービスを運行しています。
###ブースター
ナツキさんがトレーナーのポケモンアカウントです。確か言語はPHPだとお聞きしました。
主に注目を浴びたトゥートをブーストしたり、一時間にユーザーがどれくらいtootしたのかランキング形式で教えたりしてくれます。
たまに気に食わないやつには容赦なく火炎放射をぶっ放したりします。
###人類から検索の仕事を奪う人工知能
我らのニコフレアイドル、ヒホさんがマッドサイエンティストを駆使して完成した恐ろしいBotです。「検索bot」「なんすかBot」とも呼ばれています。言語はPythonです。
例えばLTL上で「ラビットハウスって何?」と聞かれたら、Wiki内のデータを検索して**最速で堂々とLTL上で上で教えてくれます。見つからなかった場合は、「ラビットハウスって何すか」**と生意気にお返しします。ユーザー達が興味本位で検索君をじゃれあったりしてかなりのtootを稼いでLTLを独占したそうです。おかげで運営からサイレンスを食らって死んでしまった悲しきBotです。
このようなことがあるのでうるさくなりそうな機能はin_reply_to_idを付けてLTLに乗せないように努力をしましょう!!
###他にも
ぼちぼちあったりします。決して定期的に自動tootするようなBotのことではないですよ?
前では美ょぅι゙ょさんがお留守番サービスで返事できるように稼働していたり、最近だとひょろぉぢりんなさんがぅゅたんぼっと♡を稼働し始めているようですね。
自分へのサポートができるBotが一番ですね!
#終わりに
キャラ | セリフ |
---|---|
![チノ] | 以上となります。いかがでしたでしょうか。 |
![マヤ] | フォローしてない人に反応できるのが凄い!!そこがツイッターとの違いだね!! |
![チノ] | つい!?!? |
![メグ] | (。>﹏<。)チノちゃん落ち着いて~ |
![チノ] | はっ! すみません取り乱しました。 |
![マヤ] | すごいなぁー、私もBot運用できたら便利だろうなぁー |
![チノ] | 運営の方々に一言かけて、周囲にご迷惑でなければ大丈夫ですよ。 不安でしたら未収載などの公開範囲でテスト運用してみましょう。ホームだけStreaming監視してもらって実装してみるのです。 |
![チノ] | みなさんも興味がありましたら、その余ったサブ垢を活用してプログラミングしてみてください! |
![メグ] | う~ん、私にできるかなぁ…… |
![マヤ] | Botメンテナンスで時間吸われるから脳死してマストドンしてるのが一番だよ!! |
![チノ] | マヤさん、それを言ったらおしまいです…… |
![メグ] | (✿´ ꒳ ` )あはははは~~~~ |
![チノ] | それでは楽しいひととき、Mastodonライフをお楽しみください。 またのお越しをお待ちしております☕ |
######おまけ | |
わざわざユーザーページ開いて確認しながら挨拶するのが手間でした→あるdiscordの女子会サーバーでMusivBotを用意することになり、作って動かせた。→10年前に抱いた人工知能との会話する願望が掘り返されハマった→本職が落ち着いたところを見計らってプログラミング開始→最初はこおりちゃんをニコフレにデビューさせるつもりだったが、100dbがインスタンスを建てたのでそちらでももなちゃんと一緒にテスト運用→気がついたらこおりちゃんは神崎丼一筋キャラになったので、仕方なくももなちゃんに挨拶キャラにさせた→気がついたらもう引き返せなくなりました。 |