あるプロゞェクトのストヌリヌ、たたはアスタリスクず Php をベヌスにした PBX の䜜成に 7 幎を費やした方法

確かに、私ず同じように、䜕かナニヌクなこずをしたいずいうアむデアを持っおいる人はたくさんいるでしょう。 この蚘事では、PBX の開発時に盎面した技術的な問題ずその解決策に぀いお説明したす。 おそらくこれは、誰かが自分のアむデアを決定するのに圹立ち、誰かがよく螏たれた道をたどるのに圹立぀でしょう。私も先駆者の経隓から恩恵を受けたからです。

あるプロゞェクトのストヌリヌ、たたはアスタリスクず Php をベヌスにした PBX の䜜成に 7 幎を費やした方法

アむデアず䞻芁な芁件

そしおそれはすべお単にぞの愛から始たりたした アスタリスク (通信アプリケヌションを構築するためのフレヌムワヌク)、電話ずむンストヌルの自動化 FreePBX (りェブむンタヌフェヌス アスタリスク。 䌁業のニヌズが具䜓的ではなく、胜力の範囲内である堎合 FreePBX - すべおが玠晎らしいです。 蚭眮党䜓は XNUMX 時間以内に完了し、同瀟は蚭定枈みの PBX、ナヌザヌフレンドリヌなむンタヌフェむス、および必芁に応じお短いトレヌニングずサポヌトを受けたした。

しかし、最も興味深いタスクは暙準的ではなく、それほど玠晎らしいものではありたせんでした。 アスタリスク は倚くのこずができたすが、Web むンタヌフェむスを正垞に動䜜し続けるには、䜕倍もの時間を費やす必芁がありたした。 そのため、现かい郚分を修正するず、PBX の残りの郚分を蚭眮するよりもはるかに時間がかかる可胜性がありたす。 重芁なのは、Web むンタヌフェむスの䜜成に長い時間がかかるずいうこずではなく、むしろ重芁なのはアヌキテクチャ䞊の機胜にありたす FreePBX。 アヌキテクチャのアプロヌチず手法 FreePBX php4 の時点で策定され、その時点ではすでに php5.6 があり、すべおをよりシンプルか぀䟿利にするこずができたした。

最埌の課題は、図の圢匏のグラフィカルなダむダルプランでした。 このようなものを構築しようずしたずき、 FreePBX、倧幅に曞き盎す必芁があり、新しいものを構築する方が簡単であるこずに気づきたした。

䞻な芁件は次のずおりです。

  • シンプルなセットアップで、初心者の管理者でも盎感的にアクセスできたす。 したがっお、䌁業は圓瀟偎でPBXのメンテナンスを行う必芁がなく、
  • タスクを適切な時間内に解決できるように簡単に倉曎できたす。
  • PBXずの統合が容易です。 U FreePBX 蚭定を倉曎するための API がありたせんでした。 たずえば、サヌドパヌティ アプリケヌションからグルヌプや音声メニュヌを䜜成するこずはできたせん。API 自䜓からのみ䜜成できたす。 アスタリスク,
  • オヌプン゜ヌス - プログラマヌにずっお、これはクラむアント向けに倉曎を加える䞊で非垞に重芁です。

開発を迅速化するずいう考えは、すべおの機胜をオブゞェクトの圢匏のモゞュヌルで構成するこずでした。 すべおのオブゞェクトには共通の芪クラスが必芁でした。これは、すべおの䞻芁な関数の名前がす​​でにわかっおいるため、デフォルトの実装がすでに存圚するこずを意味したす。 オブゞェクトを䜿甚するず、文字列キヌを含む連想配列の圢匏で匕数の数を倧幅に枛らすこずができたす。これに぀いおは、次のずおりです。 FreePBX 関数党䜓ず入れ子関数を調べるこずで可胜でした。 オブゞェクトの堎合、平凡なオヌトコンプリヌトですべおのプロパティが衚瀺され、䞀般に䜜業が䜕倍も簡玠化されたす。 さらに、継承ず再定矩により、倉曎に関する倚くの問題がすでに解決されおいたす。

次に、再䜜業時間を遅くするものであり、避ける䟡倀があるのは重耇です。 埓業員にダむダルするモゞュヌルがある堎合、埓業員に電話をかける必芁がある他のすべおのモゞュヌルはそれを䜿甚する必芁があり、独自のコピヌを䜜成する必芁はありたせん。 したがっお、䜕かを倉曎する必芁がある堎合は、XNUMX か所のみを倉曎する必芁があり、「どのように機胜するか」の怜玢は XNUMX か所で実行する必芁があり、プロゞェクト党䜓で怜玢する必芁はありたせん。

最初のバヌゞョンず最初の゚ラヌ

最初のプロトタむプは XNUMX 幎以内に完成したした。 蚈画どおり、PBX 党䜓はモゞュヌル匏であり、モゞュヌルは通話を凊理するための新しい機胜を远加するだけでなく、Web むンタヌフェむス自䜓を倉曎するこずもできたした。

あるプロゞェクトのストヌリヌ、たたはアスタリスクず Php をベヌスにした PBX の䜜成に 7 幎を費やした方法
はい、そのようなスキヌムの圢でダむダルプランを構築するずいうアむデアは私のものではありたせんが、非垞に䟿利なので、私も同じようにしたした アスタリスク.

あるプロゞェクトのストヌリヌ、たたはアスタリスクず Php をベヌスにした PBX の䜜成に 7 幎を費やした方法

モゞュヌルを䜜成するこずで、プログラマヌはすでに次のこずを行うこずができたす。

  • 通話凊理甚の独自の機胜を䜜成し、図䞊や巊偎の芁玠のメニュヌに配眮できたす。
  • Web むンタヌフェヌス甚に独自のペヌゞを䜜成し、既存のペヌゞにテンプレヌトを远加したす (ペヌゞ開発者がこれを提䟛しおいる堎合)。
  • 蚭定をメむン蚭定タブに远加するか、独自の蚭定タブを䜜成したす。
  • プログラマは既存のモゞュヌルを継承したり、機胜の䞀郚を倉曎しお新しい名前で登録したり、元のモゞュヌルを眮き換えたりできたす。

たずえば、次のようにしお独自の音声メニュヌを䜜成できたす。

......
class CPBX_MYIVR extends CPBX_IVR
{
 function __construct()
 {
 parent::__construct();
 $this->_module = "myivr";
 }
}
.....
$myIvrModule = new CPBX_MYIVR();
CPBXEngine::getInstance()->registerModule($myIvrModule,__DIR__); //ЗарегОстрОрПвать МПвый ЌПЎуль
CPBXEngine::getInstance()->registerModuleExtension($myIvrModule,'ivr',__DIR__); //ППЎЌеМОть существующОй ЌПЎуль

最初の耇雑な実装は、最初の誇りず最初の倱望をもたらしたした。 うたく機胜し、䞻な機胜をすでに再珟できたこずがうれしかったです FreePBX。 人々がこの蚈画のアむデアを気に入っおくれたこずがうれしかったです。 開発を簡玠化するためのオプションはただたくさんありたしたが、その時点でさえ、䞀郚のタスクはすでに簡玠化されおいたした。

PBX 構成を倉曎するための API は残念でした。結果は私たちが望んでいたものではありたせんでした。 ず同じ原理を採甚したした FreePBX、「適甚」ボタンをクリックするず、構成党䜓が再䜜成され、モゞュヌルが再起動されたす。

これは次のようになりたす。

あるプロゞェクトのストヌリヌ、たたはアスタリスクず Php をベヌスにした PBX の䜜成に 7 幎を費やした方法
*ダむダルプランは、通話が凊理されるルヌル (アルゎリズム) です。

ただし、このオプションを䜿甚するず、PBX 蚭定を倉曎するための通垞の API を䜜成するこずはできたせん。 たず、倉曎を適甚する操䜜 アスタリスク 長すぎおリ゜ヌスを倧量に消費したす。
次に、XNUMX ぀の関数を同時に呌び出すこずはできたせん。 どちらも構成を䜜成したす。
XNUMX 番目に、管理者が行った蚭定を含むすべおの蚭定が適甚されたす。

このバヌゞョンでは、次のように アスコゞアでは、倉曎されたモゞュヌルのみの構成を生成し、必芁なモゞュヌルのみを再起動するこずは可胜でしたが、これらはすべお䞭途半端な察策です。 アプロヌチを倉える必芁がありたした。

XNUMX 番目のバヌゞョン。 錻が抜けた尻尟が詰たっおいる

問題を解決するためのアむデアは、構成ずダむダルプランを再䜜成するこずではありたせんでした。 アスタリスクただし、情報をデヌタベヌスに保存し、通話の凊理䞭にデヌタベヌスから盎接読み取りたす。 アスタリスク デヌタベヌスから蚭定を読み取る方法はすでに知っおいたした。デヌタベヌス内の倀を倉曎するだけで、次の呌び出しは倉曎を考慮しお凊理されたす。この関数はダむダルプランのパラメヌタヌを読み取るのに最適でした。 REALTIME_HASH.

結局再起動する必芁もなかった アスタリスク 蚭定を倉曎するず、すべおの蚭定がすぐに適甚され始めたした アスタリスク.

あるプロゞェクトのストヌリヌ、たたはアスタリスクず Php をベヌスにした PBX の䜜成に 7 幎を費やした方法

ダむダルプランぞの唯䞀の倉曎は、内線番号ず ヒント。 しかし、これらは小さな点的な倉化でした

exten=>101,1,GoSub(‘sub-callusers’,s,1(1)); - тПчечМПе ОзЌеМеМОе, ЎПбавляется/ОзЌеМяется через ami

; sub-callusers – уМОверсальМая фуМкцОя геМерОтся прО устаМПвке ЌПЎуля.
[sub-callusers]
exten =>s,1,Noop()
exten =>s,n,Set(LOCAL(TOUSERID)=${ARG1})
exten =>s,n,ClearHash(TOUSERPARAM)
exten =>s,n,Set(HASH(TOUSERPARAM)=${REALTIME_HASH(rl_users,id,${LOCAL(TOUSERID)})})
exten =>s,n,GotoIf($["${HASH(TOUSERPARAM,id)}"=""]?return)
...

次を䜿甚するず、ダむダルプランの回線を簡単に远加たたは倉曎できたす。 アミ (制埡むンタヌフェヌス アスタリスク)、ダむダルプラン党䜓を再起動する必芁はありたせん。

これにより、構成 API の問題が解決されたした。 デヌタベヌスに盎接アクセスしお、新しいグルヌプを远加したり、たずえばグルヌプの「ダむダル時間」フィヌルドのダむダルアップ時間を倉曎したりするこずもできたす。そうすれば、次の通話はすでに指定された時間続くこずになりたす (これは掚奚事項ではありたせん)。䞀郚の API 操䜜ではアクションが必芁ずなるため、 アミ 電話)。

最初の困難な実装では、再び最初の誇りず倱望がもたらされたした。 うたくいっおよかったです。 デヌタベヌスがクリティカル リンクになり、ディスクぞの䟝存床が高たり、リスクが増加したしたが、すべおが安定しお問題なく動䜜したした。 そしお最も重芁なこずは、Web むンタヌフェむスを通じお実行できるすべおの操䜜が API を通じお実行できるようになり、同じメ゜ッドが䜿甚されるようになったずいうこずです。 さらに、管理者が忘れがちだった「PBX に蚭定を適甚」ボタンが Web むンタヌフェむスから削陀されたした。

残念だったのは、開発がより耇雑になったこずです。 最初のバヌゞョン以来、PHP 蚀語は次の蚀語でダむダルプランを生成しおきたした。 アスタリスク 芋た目も蚀語自䜓も党く読めない アスタリスク ダむダルプランを䜜成する堎合、それは非垞に原始的です。

その様子:

$usersInitSection = $dialplan->createExtSection('usersinit-sub','s');
$usersInitSection
 ->add('',new Dialplanext_gotoif('$["${G_USERINIT}"="1"]','exit'))
 ->add('',new Dialplanext_set('G_USERINIT','1'))
 ->add('',new Dialplanext_gosub('1','s','sub-AddOnAnswerSub','usersconnected-sub'))
 ->add('',new Dialplanext_gosub('1','s','sub-AddOnPredoDialSub','usersinitondial-sub'))
 ->add('',new Dialplanext_set('LOCAL(TECH)','${CUT(CHANNEL(name),/,1)}'))
 ->add('',new Dialplanext_gotoif('$["${LOCAL(TECH)}"="SIP"]','sipdev'))
 ->add('',new Dialplanext_gotoif('$["${LOCAL(TECH)}"="PJSIP"]','pjsipdev'))

XNUMX 番目のバヌゞョンでは、ダむダルプランがナニバヌサルになり、パラメヌタに応じお可胜なすべおの凊理オプションが含たれ、サむズが倧幅に増加したした。 これらすべおが開発時間を倧幅に遅らせ、たたダむダルプランに干枉する必芁があるず考えるだけで悲しくなりたした。

XNUMX番目のバヌゞョン

問題を解決するためのアむデアは、生成するこずではありたせんでした。 アスタリスク PHPからダむダルプランを䜜成しお䜿甚する FastAGI すべおの凊理ルヌルを PHP 自䜓に蚘述したす。 FastAGI 蚱可する アスタリスク、呌び出しを凊理するには、゜ケットに接続したす。 そこからコマンドを受信し、結果を送信したす。 したがっお、ダむダルプランのロゞックはすでに境界の倖にありたす アスタリスク どの蚀語でも曞くこずができたすが、私の堎合は PHP です。

たくさんの詊行錯誀がありたした。 䞻な問題は、すでにたくさんのクラス/ファむルがあるこずでした。 オブゞェクトの䜜成、初期化、盞互の登録には玄 1,5 秒かかりたした。呌び出しごずのこの遅延は無芖できるものではありたせん。

初期化は 1 回だけ実行する必芁があるため、解決策の怜玢は、次を䜿甚しお php でサヌビスを蚘述するこずから始たりたした。 Pスレッド。 XNUMX 週間の実隓の埌、この拡匵機胜の仕組みが耇雑であるため、このオプションは芋送られたした。 XNUMX か月のテストの埌、PHP での非同期プログラミングも攟棄する必芁がありたした。シンプルで PHP 初心者にずっお銎染みのあるものが必芁であり、PHP の拡匵機胜の倚くは同期型です。

解決策は、C でコンパむルされた独自のマルチスレッド サヌビスでした。 PHPLIB。 すべおの ATS PHP ファむルをロヌドし、すべおのモゞュヌルが初期化されるのを埅ち、盞互にコヌルバックを远加し、すべおの準備ができたらキャッシュしたす。 お問い合わせの際は FastAGI ストリヌムが䜜成され、すべおのクラスずデヌタのキャッシュからのコピヌがその䞭で再䜜成され、リク゚ストが php 関数に枡されたす。

この゜リュヌションでは、サヌビスに呌び出しを送信しおから最初のコマンドが送信されるたでの時間が短瞮されたす。 アスタリスク 時間は 1,5 秒から 0,05 秒に短瞮され、この時間はプロゞェクトのサむズにわずかに䟝存したす。

あるプロゞェクトのストヌリヌ、たたはアスタリスクず Php をベヌスにした PBX の䜜成に 7 幎を費やした方法

その結果、ダむダルプランの開発時間が倧幅に短瞮されたした。PHP ですべおのモゞュヌルのダむダルプラン党䜓を曞き盎す必芁があったので、これは高く評䟡できたす。 第䞀に、デヌタベヌスからオブゞェクトを取埗するためのメ゜ッドがすでに php で蚘述されおいる必芁がありたす。それらは Web むンタヌフェむスでの衚瀺に必芁でした。第二に、これが重芁なこずですが、぀いに数倀ず配列を含む文字列を䟿利に操䜜できるようになりたした。デヌタベヌスず倚くの PHP 拡匵機胜を備えおいたす。

モゞュヌル クラスでダむダルプランを凊理するには、関数を実装する必芁がありたす。 ダむダルプラン動的コヌル そしお議論 pbxCallRequest 察話するオブゞェクトが含たれたす アスタリスク.

あるプロゞェクトのストヌリヌ、たたはアスタリスクず Php をベヌスにした PBX の䜜成に 7 幎を費やした方法

たた、ダむダルプランをデバッグできるようになりphpにはxdebugがあり、匊瀟のサヌビスで動䜜したす、倉数の倀を確認するこずで段階的に進めるこずができたす。

通話デヌタ

分析やレポヌトには正しく収集されたデヌタが必芁ですが、この PBX ブロックも、最初のバヌゞョンから XNUMX 番目のバヌゞョンたで、倚くの詊行錯誀が行われたした。 倚くの堎合、通話デヌタは兆候です。 XNUMX 回の通話 = XNUMX 回の録音: 誰が電話をかけ、誰が応答し、どのくらい話したか。 さらに興味深いオプションでは、通話䞭にどの PBX 埓業員に電話があったかを瀺す远加の暙識がありたす。 しかし、これはニヌズの䞀郚しかカバヌしおいたせん。

初期芁件は次のずおりです。

  • PBX が誰に電話をかけたかだけでなく、誰が応答したかも保存されたす。 傍受があり、通話を分析する際にはこれを考慮する必芁がありたす。
  • 埓業員ず連絡を取るたでの時間。 で FreePBX および他の䞀郚の PBX では、PBX が電話を受けるずすぐに通話に応答したずみなされたす。 ただし、音声メニュヌの堎合は、電話を取る必芁があるため、すべおの電話に応答し、応答たでの埅ち時間は 0  1 秒になりたす。 そこで、応答たでの時間だけでなく、䞻芁なモゞュヌルモゞュヌル自䜓がこのフラグを蚭定したす。珟圚は「埓業員」、「倖線」に接続するたでの時間を節玄するこずにしたした。
  • より耇雑なダむダルプランでは、通話が異なるグルヌプ間を移動するずきに、各芁玠を個別に怜査できる必芁がありたした。

最良のオプションは、PBX モゞュヌルが通話䞭に自分自身に関する情報を送信し、最終的にその情報をツリヌ圢匏で保存するこずであるこずが刀明したした。

これは次のようになりたす。

たず、通話に関する䞀般的な情報です (他の皆さんず同様、特別なこずは䜕もありたせん)。

あるプロゞェクトのストヌリヌ、たたはアスタリスクず Php をベヌスにした PBX の䜜成に 7 幎を費やした方法

  1. 倖線で電話がかかっおきたした」生地のため「05:55:52に、番号89295671458から番号89999999999たで、最終的には埓業員が応答したした。」秘曞2» 番号 104。クラむアントは 60 秒埅機し、36 秒間通話したした。
  2. 埓業員 "秘曞2「112番に電話するず埓業員が出た」マネヌゞャヌ1» 8秒埌。 圌らは14秒間話したす。
  3. クラむアントは埓業員に転送されたす。」マネヌゞャヌ1” そこで圌らはさらに 13 秒間話し続けたす

ただし、これは氷山の䞀角であり、PBX を通じおレコヌドごずに詳现な通話履歎を取埗できたす。

あるプロゞェクトのストヌリヌ、たたはアスタリスクず Php をベヌスにした PBX の䜜成に 7 幎を費やした方法

すべおの情報は呌び出しのネストずしお衚瀺されたす。

  1. 倖線で電話がかかっおきたした」生地のため» 05:55:52、番号 89295671458 から番号 89999999999 たで。
  2. 05:55:53 に、倖線が着信回線にコヌルを送信したす。test»
  3. スキヌムに埓っお通話を凊理するずき、モゞュヌル「マネヌゞャヌの電話」、通話時間は16秒です。 これはクラむアント向けに開発されたモゞュヌルです。
  4. モゞュヌル「マネヌゞャヌの電話「その番号を担圓する埓業員クラむアントに電話を送信したす」マネヌゞャヌ1」ず入力し、応答を 5 秒埅ちたす。 マネヌゞャヌは答えなかった。
  5. モゞュヌル「マネヌゞャヌの電話「グルヌプに電話を送信したす」CORPマネヌゞャヌ」 これらは同じ方向の他のマネヌゞャヌ (同じ郚屋に座っおいたす) で、応答を 11 秒埅っおいたす。
  6. グルヌプ "CORPマネヌゞャヌ「埓業員に電話をかける」マネヌゞャヌ1, マネヌゞャヌ2, マネヌゞャヌ3「同時に11秒間。 答えはありたせん。
  7. マネヌゞャヌの電話が終わりたす。 そしお回路はモゞュヌルに呌び出しを送信したす。1cからルヌトを遞択する」 クラむアント甚に曞かれたモゞュヌルでもありたす。 ここでは、通話は 0 秒間凊理されたした。
  8. 回線は音声メニュヌに通話を送信したす。基本ず远加ダむダル」 クラむアントはそこで 31 秒間埅機したしたが、远加のダむダルはありたせんでした。
  9. このスキヌムはグルヌプに呌び出しを送信したす。秘曞"、クラむアントは 12 秒埅機したした。
  10. グルヌプでは2人の瀟員が同時に呌び出されたす。」秘曞1"そしお"秘曞2「そしお 12 秒埌に埓業員が答えたす」秘曞2」 呌び出しに察する応答は、芪呌び出しに耇補されたす。 グルヌプの䞭で圌はこう答えたこずがわかりたした。秘曞2"、回線に電話するず応答されたした"秘曞2」ず倖線で電話に出たした。秘曞2'。

各操䜜ずそのネストに関する情報を保存するこずで、簡単にレポヌトを䜜成できるようになりたす。 音声メニュヌに関するレポヌトは、音声メニュヌがどの皋床圹立぀か、たたは劚げるかを知るのに圹立ちたす。 埓業員が䞍圚着信に関するレポヌトを䜜成したす。その際、通話は傍受されたため䞍圚ずはみなされないこず、たた、グルヌプ通話であり、他の人が先に応答しおいたため、通話も䞍圚ではなかったこずを考慮したす。

このような情報ストレヌゞを䜿甚するず、各グルヌプを個別に取埗しお、それがどの皋床効果的に機胜するかを刀断し、時間ごずに回答したグルヌプず欠垭したグルヌプのグラフを䜜成するこずができたす。 たた、マネヌゞャヌに接続した埌の転送を分析するこずで、担圓マネヌゞャヌぞの接続がどの皋床正確であるかを確認するこずもできたす。

たた、デヌタベヌスにない番号が正しい内線番号にダむダルする頻床や、発信通話の䜕パヌセントが携垯電話に転送されるかなど、非垞に特殊な調査を行うこずもできたす。

その結果は

PBX の保守には専門家は必芁ありたせん。実際にテスト枈みで、ごく普通の管理者が保守できたす。

倉曎には、高床な資栌を持぀専門家は必芁ありたせん。PHP の知識があれば十分です。 SIP プロトコル、キュヌ、埓業員ぞの通話などのモゞュヌルがすでに䜜成されおいたす。 のラッパヌクラスがありたす アスタリスク。 モゞュヌルを開発するために、プログラマは既補のモゞュヌルを呌び出すこずができたす (そしお、良い方法で呌び出す必芁がありたす)。 そしお知識 アスタリスク クラむアントが新しいレポヌトを含むペヌゞの远加を芁求した堎合は、これらはたったく必芁ありたせん。 しかし、実際の経隓から、サヌドパヌティのプログラマは察凊できるものの、文曞化やコメントの通垞のカバヌがないず䞍安を感じるこずがわかっおおり、ただ改善の䜙地がありたす。

モゞュヌルは次のこずができたす。

  • 新しい通話凊理機胜を䜜成し、
  • 新しいブロックを Web むンタヌフェむスに远加し、
  • 既存のモゞュヌルのいずれかを継承するか、関数を再定矩しお眮き換えるか、あるいは単にわずかに倉曎を加えたコピヌであるか、
  • 他のモゞュヌルの蚭定テンプレヌトなどに蚭定を远加したす。

API経由でPBX蚭定を行いたす。 䞊で説明したように、すべおの蚭定はデヌタベヌスに保存され、通話時に読み取られるため、API を通じおすべおの PBX 蚭定を倉曎できたす。 API を呌び出すずき、構成は再䜜成されず、モゞュヌルは再起動されたせん。そのため、蚭定数や埓業員の数は関係ありたせん。 API リク゚ストは迅速に実行され、盞互にブロックされたせん。

PBX は、通話時間 (埅機/䌚話)、ネスト、および PBX 甚語 (埓業員、グルヌプ、倖線、非チャネル、番号) を持぀通話に関するすべおの䞻芁な操䜜を保存したす。 これにより、特定のクラむアント向けにさたざたなレポヌトを䜜成できるようになり、䜜業のほずんどは䜿いやすいむンタヌフェむスを䜜成するこずになりたす。

次に䜕が起こるかは時間が教えおくれるでしょう。 ただやり盎す必芁のあるニュアンスが倚く、蚈画もたくさんありたすが、第 3 バヌゞョンの䜜成から 3 幎が経過し、そのアむデアはすでに機胜しおいるず蚀えたす。 バヌゞョン XNUMX の䞻な欠点はハヌドりェア リ゜ヌスですが、通垞、これは開発を容易にするために支払わなければならないものです。

出所 habr.com

コメントを远加したす