「備忘録 : Twitch データの日本語デコード (2025/01/29)」
さて。私は配信サイトTwitchを見る時には


プロキシーソフト
Titanium.Web.Proxy (以下 TWP)

を間にかませて、NGフィルターをかけています。
あらためてTwitch用 NGコードの解説:
Twitchを開くて出てくる。このようなトップ画面ですが

ここのデータは、ブラウザが
url = "gql.twitch.tv/gql";
content_type = "application/json";
から取得しています。
要するにそこのテキストを、
TWPで監視して。書き換えてやれば
NG処理を行えるようになるのです。
もっと具体的には。
一個一個のアイテムは

[
{
"trackingID":"abc...",
"promotionsCampaignID":"",
"user":
{
"id":"abc...",
"login":"abc...",
"displayName":"abc...",
"profileImageURL":"abc....",
"primaryColorHex":null,
"broadcastSettings":
{
"id":"abc...",
"title":"TITLE",
"__typename":"BroadcastSettings"
},
"__typename":"User"
},
"label":"NONE",
"content":
{
"id":"abc...",
"previewImageURL":"abc...",
"broadcaster":
{
"id":"abc...",
"broadcastSettings":
{
"id":"abc...",
"title":"TITLE",
"__typename":"BroadcastSettings"
},
"__typename":"User"
},
"viewersCount":abc...,
"game":
{
"id":"abc...",
"displayName":"Retro",
"name":"Retro",
"__typename":"Game"
},
"type":"live",
"__typename":"Stream"
},
"__typename":"PersonalSectionChannel"
},
]
{
"trackingID":"abc...",
"promotionsCampaignID":"",
"user":
{
"id":"abc...",
"login":"abc...",
"displayName":"abc...",
"profileImageURL":"abc....",
"primaryColorHex":null,
"broadcastSettings":
{
"id":"abc...",
"title":"TITLE",
"__typename":"BroadcastSettings"
},
"__typename":"User"
},
"label":"NONE",
"content":
{
"id":"abc...",
"previewImageURL":"abc...",
"broadcaster":
{
"id":"abc...",
"broadcastSettings":
{
"id":"abc...",
"title":"TITLE",
"__typename":"BroadcastSettings"
},
"__typename":"User"
},
"viewersCount":abc...,
"game":
{
"id":"abc...",
"displayName":"Retro",
"name":"Retro",
"__typename":"Game"
},
"type":"live",
"__typename":"Stream"
},
"__typename":"PersonalSectionChannel"
},
]
(一例)
こんな感じの。JsonObjectと対応していて。
それらのアイテムが、配列としてやってくる。
これがTwitchがトップ画面を表示している仕組みです。

このツリーの中で
#NGワード#
を見かけたら。
そのJsonObjectを入力データの中から
抹消すれば、画面から消えると言うわけです。
オリジナル画面

TWPによるNG処理後 画面

こんな感じで。NGワードにひっかかったアイテムは消えてくれます。
そもそも何故。私がこんな事をしているかと言うと。
Twitchにも「興味がない」機能はありますが

これがかなり貧弱。
・NGできるのは配信者個別であり、
#興味のないゲーム#
タイトルそのものをNGする機能は存在しない。
・「トップ掲載」はユーザーNGを貫通してやってくる。
・Twitchがこちらの興味のないゲームを

延々と羅列してくる。
これらの不満点があったので、
もう自分でNG機能を作りました。
特によく使うのが以下の3パターン:
#ゲーム名によるNG
*/game/displayname/#ゲーム名#
#配信タイトルによるNG
*/broadcastsettings/title/#タイトル#
#配信者によるNG
*/broadcaster/login/#配信者名#
*/game/displayname/#ゲーム名#
#配信タイトルによるNG
*/broadcastsettings/title/#タイトル#
#配信者によるNG
*/broadcaster/login/#配信者名#
で。ここからが今回の本題ですが。
この
url = "gql.twitch.tv/gql";
から取得できるテキスト。

・・・日本語が文字化けするんですよね。^^;
文字化けしてる該当部分をバイナリエディタで見たらこんな感じ。

・・・これは何でしょうか。
よく使われる日本語文字コード
UTF-8 / Sjis / Jis / EUC / ...
で解釈を試みても、全部失敗。
こんな文字コードは存在しない。
かと言って。それら以外。
「独自規格の文字コード」なんて聞いた事ありませんし。
(そんな面倒な事をする意味がない)
何だろうな。
しばらく考えて。
ちょっとした法則を発見。

0xC3、0xC2が明らかに多すぎます。
おそらくこれは「何らかのnamespace的な」。
やってるのは空間の指定であって、ここに意味は含まれてないと考え。

2バイト目だけに注目して文字コードを調べたら・・・
ビンゴ。
これはUTF-8の変形ですな。
//Twitch の入力データ、日本語デコード
byte[] decode(string content)
{
var output = new byte[content.Length];
var at = 0;
var to = 0;
for (; ; )
{
var c = read(content,ref at);
//0xC3だった場合、次の文字が「E6 → A6」みたいにUTF8コードから-0x40ずれてる
if (c == 0xC3)
{
var c2 = read(content, ref at);
write(output, ref to, (byte)(c2 + 0x40));
}
//0xC2だった場合は、次の文字がUTF8コードそのまま。
else if (c == 0xC2)
{
var c2 = read(content, ref at);
write(output, ref to, (byte)(c2));
}
//それ以外はアスキー
else
{
write(output, ref to, c);
}
}
return output;
}
byte read(string content, ref int at)
{
var c = content[at];
at++;
return (byte)c;
}
void write(byte[] output, ref int at,byte c)
{
output[at] = c;
at++;
}
理由はわかりませんが、なぜかUTF-8を
ちょっとしたエンコード・デコードしていました。
おそらく。UTF-8形式だと他のどこかの
処理で邪魔・ノイズになってしまうので。
文字をいったんエスケープしてるのかなー。
まぁ。よくある話。(^^A;