17 コミット

15個のファイルの変更542行の追加185行の削除
実行可能ファイル
バイナリ
ファイルの表示
バイナリファイルは表示されません.

変更後

幅:  |  高さ:  |  サイズ: 450 KiB

バイナリ
ファイルの表示
バイナリファイルは表示されません.
バイナリ
ファイルの表示
バイナリファイルは表示されません.

変更後

幅:  |  高さ:  |  サイズ: 40 KiB

バイナリ
ファイルの表示
バイナリファイルは表示されません.

変更後

幅:  |  高さ:  |  サイズ: 42 KiB

+44
ファイルの表示
@@ -0,0 +1,44 @@
export default class
CommonModule
{
static
isWide (chr)
{
return chr.match (/[^\x01-\x7f]/) !== null;
}
static
lenByFull (str)
{
return str.split ('').map (c => this.isWide (c) ? 1 : .5)
.reduce ((a, c) => a + c);
}
static
indexByFToC (str, index)
{
let i = 0;
let work = '';
for (let c of str)
{
work += c;
if (this.lenByFull (work) > index)
break;
i += 1;
}
return i;
}
static
midByFull (str, start, length)
{
const trimmedLeft = str.slice (this.indexByFToC (str, start));
return trimmedLeft.slice (0, this.indexByFToC (trimmedLeft, length));
}
}
+12 -37
ファイルの表示
@@ -22,6 +22,12 @@
</head> </head>
<body> <body>
<?php if (!($available)): ?>
<div class="alert alert-danger" role="alert">
<strong>【警報】</strong>AIニジカが落ちてるぬ゛〜゛ん゛(泣)
</div>
<?php endif ?>
<div class="container my-5"> <div class="container my-5">
<div class="accordion mb-5" id="accordion-filter"> <div class="accordion mb-5" id="accordion-filter">
<div class="accordion-item"> <div class="accordion-item">
@@ -42,7 +48,7 @@
<div class="col-sm"> <div class="col-sm">
<div class="row align-items-center"> <div class="row align-items-center">
<div class="col form-check"> <div class="col form-check">
<input class="form-check-input" type="radio" name="order" id="order-desc"<?= $asc ? '' : ' checked="checked"' ?> /> <input class="form-check-input" type="radio" name="order" id="order-desc" checked="checked" />
<label class="form-check-label" for="order-desc"> <label class="form-check-label" for="order-desc">
新しい順 新しい順
@@ -50,7 +56,7 @@
</div> </div>
<div class="col form-check"> <div class="col form-check">
<input class="form-check-input" type="radio" name="order" id="order-asc"<?= $asc ? ' checked="checked"' : '' ?> /> <input class="form-check-input" type="radio" name="order" id="order-asc" />
<label class="form-check-label" for="order-asc"> <label class="form-check-label" for="order-asc">
古い順 古い順
@@ -73,14 +79,12 @@
<input type="text" <input type="text"
class="form-control" class="form-control"
placeholder="YYYY-MM-DD" placeholder="YYYY-MM-DD"
id="filter-date-start" id="filter-date-start" />
value="<?= $date_start ?>" />
<span class="input-group-text">〜</span> <span class="input-group-text">〜</span>
<input type="text" <input type="text"
class="form-control" class="form-control"
placeholder="YYYY-MM-DD" placeholder="YYYY-MM-DD"
id="filter-date-end" id="filter-date-end" />
value="<?= $date_end ?>" />
</div> </div>
</div> </div>
@@ -93,8 +97,7 @@
<input type="text" <input type="text"
class="form-control" class="form-control"
placeholder="<?= $april_fool ? 'ムムムム!! クサタベテル!!!!!' : 'ぬ゛ぅ゛ぅ゛ぅ゛ぅ゛ぅ゛ん゛' ?>" placeholder="<?= $april_fool ? 'ムムムム!! クサタベテル!!!!!' : 'ぬ゛ぅ゛ぅ゛ぅ゛ぅ゛ぅ゛ん゛' ?>"
id="filter-keyword" id="filter-keyword" />
value="<?= $keyword ?>"/>
</div> </div>
</div> </div>
</div> </div>
@@ -113,44 +116,16 @@
</div> </div>
</div> </div>
<?php if (count ($log_data) > 0): ?>
<div class="mb-4"> <div class="mb-4">
<?php require 'pagination.cmp.php' ?> <?php require 'pagination.cmp.php' ?>
</div> </div>
<div> <div id="message-list">
<?php foreach (array_slice ($log_data,
($page - 1) * $length,
$length,
true)
as $record): ?>
<div class="mb-4">
<div>
<?= $record['date_time'] ?>
</div>
<div>
<img src="<?= $record['chat_icon'] ?>" width="64" height="64" />
<?= $record['chat_name'] ?>
</div>
<div style="color: blue">
&gt; <span style="font-style: italic"><?= $record['chat_message'] ?></span>
</div>
<div>
<?= $record['answer'] ?>
</div>
</div>
<?php endforeach ?>
</div> </div>
<div class="mt-5"> <div class="mt-5">
<?php require 'pagination.cmp.php' ?> <?php require 'pagination.cmp.php' ?>
</div> </div>
<?php else: ?>
何も見つかりませんでしたぬ゛ぅ゛ぅ゛ぅ゛ぅ゛ん゛
<?php endif ?>
</div> </div>
<script src="//cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script> <script src="//cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
+5 -53
ファイルの表示
@@ -7,59 +7,11 @@ const LOG_PATH = './log.txt';
$log_data = []; $log_data = [];
$page = (int) ($_GET['p'] ?? 1); exec (("(ps -Af | grep -e '^miteruzo' | grep 'python3 main.py')"
$length = (int) ($_GET['max'] ?? 20); . " && (ps -Af | grep -e '^miteruzo' | grep 'obs')"),
$asc = ($_GET['asc'] ?? 0) != 0; $output, $exit_code);
$keyword = trim ($_GET['q'] ?? ''); $available = $exit_code === 0;
$escaped = ($_GET['escaped'] ?? 0) != 0; unset ($output, $exit_code);
$date_start = ($_GET['start'] ?? null) ?: null;
$date_end = ($_GET['end'] ?? null) ?: null;
$f = fopen (LOG_PATH, 'r');
if ($f !== false)
{
while (($dt = fgetcsv ($f, 0, "\t")) !== false)
{
$chat_info = json_decode ($dt[1]);
$log_data[] = ['date_time' => $dt[0],
'chat_icon' => $chat_info -> author -> imageUrl,
'chat_name' => $escaped ? htmlspecialchars ($chat_info -> author -> name) : $chat_info -> author -> name,
'chat_message' => $escaped ? htmlspecialchars ($chat_info -> message) : $chat_info -> message,
'answer' => $escaped ? htmlspecialchars ($dt[2]) : $dt[2]];
}
}
fclose ($f);
unset ($f);
if ($keyword != '')
{
$log_data = array_filter ($log_data, fn ($row) => (
strpos ($row['chat_name'] . "\n" . $row['chat_message'] . "\n" . $row['answer'],
$keyword)
!== false));
}
if ($date_start)
{
$log_data = array_filter ($log_data, fn ($row) => (
substr ($row['date_time'], 0, 10) >= $date_start));
}
if ($date_end)
{
$log_data = array_filter ($log_data, fn ($row) => (
substr ($row['date_time'], 0, 10) <= $date_end));
}
$pages_max = (int) ((count ($log_data) - 1) / $length) + 1;
if (!($asc))
$log_data = array_reverse ($log_data);
require_once './index.frm.php'; require_once './index.frm.php';
+2 -59
ファイルの表示
@@ -1,63 +1,6 @@
<!-- vim:set tabstop=4 softtabstop=4 expandtab :--> <!-- vim:set tabstop=4 softtabstop=4 expandtab :-->
<nav class="d-flex justify-content-center" aria-label="..."> <nav class="d-flex justify-content-center d-none" aria-label="...">
<ul class="pagination opacity-0"> <ul class="pagination"></ul>
<?php if ($page > 1): ?>
<li class="page-item deerjika-tail">
<a class="page-link" href="javascript: void (0)" onclick="Script.jumpTo (1)">
<img src="./assets/page-first.png" />
<div class="page-link-text">|&lt;</div>
</a>
</li>
<?php else: ?>
<li class="page-item disabled deerjika-tail">
<span class="page-link">
<img src="./assets/page-first.png" />
<div class="page-link-text"></div>
</span>
</li>
<?php endif ?>
<?php for ($i = max (min ($page + 10, $pages_max) - 20, 1); $i < $page; ++$i): ?>
<li class="page-item page-<?= $page - $i ?>">
<a class="page-link" href="javascript: void (0)" onclick="Script.jumpTo (<?= $i ?>)">
<img src="./assets/page-body.png" />
<div class="page-link-text"><?= $i ?></div>
</a>
</li>
<?php endfor ?>
<li class="page-item active" aria-current="page">
<span class="page-link">
<img src="./assets/page-body.png" />
<div class="page-link-text"><?= $page ?></div>
</span>
</li>
<?php for ($i = $page + 1; $i <= min (max ($page - 10, 1) + 20, $pages_max); ++$i): ?>
<li class="page-item page-<?= $i - $page ?>">
<a class="page-link" href="javascript: void (0)" onclick="Script.jumpTo (<?= $i ?>)">
<img src="./assets/page-body.png" />
<div class="page-link-text"><?= $i ?></div>
</a>
</li>
<?php endfor ?>
<?php if ($page < $pages_max): ?>
<li class="page-item">
<a class="page-link" href="javascript: void (0)" onclick="Script.jumpTo (<?= $pages_max ?>)">
<img src="./assets/page-last.png" />
<div class="page-link-text">&gt;|</div>
</a>
</li>
<?php else: ?>
<li class="page-item disabled">
<span class="page-link">
<img src="./assets/page-last.png" />
<div class="page-link-text"></div>
</span>
</li>
<?php endif ?>
</ul>
</nav> </nav>
+200 -29
ファイルの表示
@@ -4,21 +4,28 @@ Script
static static
main () main ()
{ {
const self = this;
self.paramAsc = null;
self.paramStart = null;
self.paramEnd = null;
self.paramQ = null;
self.paramP = null;
self.fetchData ();
const dateOptions = {dateFormat: 'yy-mm-dd', const dateOptions = {dateFormat: 'yy-mm-dd',
firstDay: 6}; firstDay: 6};
$ ('#filter-date-start').datepicker (dateOptions); $ ('#filter-date-start').datepicker (dateOptions);
$ ('#filter-date-end').datepicker (dateOptions); $ ('#filter-date-end').datepicker (dateOptions);
const url = new URL (window.location.href);
const orderAsc = document.getElementById ('order-asc'); const orderAsc = document.getElementById ('order-asc');
const filterKeyword = document.getElementById ('filter-keyword'); const filterKeyword = document.getElementById ('filter-keyword');
const btnFilter = document.getElementById ('btn-filter'); const btnFilter = document.getElementById ('btn-filter');
const filter = ( const filter = function (e)
function (e)
{ {
let dateStart = $ ('#filter-date-start').val (); let dateStart = $ ('#filter-date-start').val ();
let dateEnd = $ ('#filter-date-end').val (); let dateEnd = $ ('#filter-date-end').val ();
@@ -28,31 +35,30 @@ Script
&& (dateStart > dateEnd)) && (dateStart > dateEnd))
[dateStart, dateEnd] = [dateEnd, dateStart]; [dateStart, dateEnd] = [dateEnd, dateStart];
url.searchParams.delete ('p'); self.paramAsc = orderAsc.checked ? '1' : '0';
self.paramQ = filterKeyword.value;
url.searchParams.delete ('asc');
url.searchParams.append ('asc', orderAsc.checked ? '1' : '0');
url.searchParams.delete ('q');
url.searchParams.append ('q', filterKeyword.value);
url.searchParams.delete ('start');
url.searchParams.delete ('end');
if (dateStart !== '') if (dateStart !== '')
url.searchParams.append ('start', dateStart); self.paramStart = dateStart;
if (dateEnd !== '') if (dateEnd !== '')
url.searchParams.append ('end', dateEnd); self.paramEnd = dateEnd;
window.location.href = url; self.paramP = null;
});
const resetFilter = ( self.fetchData ();
function () };
const resetFilter = function ()
{ {
window.location.href = '/'; self.paramAsc = null;
}); self.paramStart = null;
self.paramEnd = null;
self.paramQ = null;
self.paramP = null;
self.fetchData ();
};
filterKeyword.addEventListener ('keydown', filterKeyword.addEventListener ('keydown',
function (e) function (e)
@@ -65,8 +71,6 @@ Script
$ ('#btn-reset').on ('click', resetFilter); $ ('#btn-reset').on ('click', resetFilter);
$ (window).resize (this.setPagination); $ (window).resize (this.setPagination);
this.setPagination ();
$ ('.pagination').removeClass ('opacity-0');
$ ('#accordion-filter').on ('shown.bs.collapse', function () $ ('#accordion-filter').on ('shown.bs.collapse', function ()
{ {
@@ -83,17 +87,19 @@ Script
$ ('#collapse-filter').removeClass ('show'); $ ('#collapse-filter').removeClass ('show');
$ ('#accordion-filter .accordion-button').addClass ('collapsed'); $ ('#accordion-filter .accordion-button').addClass ('collapsed');
} }
window.setInterval (function ()
{
self.fetchData ();
}, 60000);
} }
static static
jumpTo (page) jumpTo (page)
{ {
const url = new URL (window.location.href); this.paramP = page;
url.searchParams.delete ('p'); this.fetchData ();
url.searchParams.append ('p', page);
window.location.href = url;
} }
static static
@@ -111,6 +117,171 @@ Script
$ (`.page-${i}`).addClass ('d-none'); $ (`.page-${i}`).addClass ('d-none');
} }
} }
static
fetchData ()
{
const self = this;
const postData = {}
if (this.paramAsc != null)
postData.asc = this.paramAsc;
if (this.paramStart != null)
postData.start = this.paramStart;
if (this.paramEnd != null)
postData.end = this.paramEnd;
if (this.paramQ != null)
postData.q = this.paramQ;
if (this.paramP != null)
postData.p = this.paramP;
const done = function (data)
{
$ ('.pagination').empty ();
if (data.page > 1)
{
($ ('.pagination')
.append ($ ('<li>', {class: 'page-item deerjika-tail'})
.append ($ ('<a>', {class: 'page-link',
href: 'javascript: void 0',
onclick: 'Script.jumpTo (1)'})
.append ($ ('<img>',
{src: './assets/page-first.png'}))
.append ($ ('<div>', {class: 'page-link-text'})
.append ('|&lt;')))));
}
else
{
($ ('.pagination')
.append ($ ('<li>', {class: 'page-item disabled deerjika-tail'})
.append ($ ('<span>', {class: 'page-link'})
.append ($ ('<img>',
{src: './assets/page-first.png'}))
.append ($ ('<div>', {class: 'page-link-text'})))));
}
for (let i = Math.max (Math.min (data.page + 10, data.max) - 20, 1);
i < data.page;
++i)
{
($ ('.pagination')
.append ($ ('<li>', {class: `page-item page-${ data.page - i }`})
.append ($ ('<a>', {class: 'page-link',
href: 'javascript: void 0',
onclick: `Script.jumpTo (${ i })`})
.append ($ ('<img>',
{src: './assets/page-body.png'}))
.append ($ ('<div>', {class: 'page-link-text'})
.append (i)))));
}
($ ('.pagination')
.append ($ ('<li>', {class: 'page-item active',
'aria-current': 'page'})
.append ($ ('<span>', {class: 'page-link'})
.append ($ ('<img>', {src: './assets/page-body.png'}))
.append ($ ('<div>', {class: 'page-link-text'})
.append (data.page)))));
for (let i = data.page + 1;
i <= Math.min (Math.max (data.page - 10, 1) + 20, data.max);
++i)
{
($ ('.pagination')
.append ($ ('<li>', {class: `page-item page-${ i - data.page }`})
.append ($ ('<a>', {class: 'page-link',
href: 'javascript: void 0',
onclick: `Script.jumpTo (${ i })`})
.append ($ ('<img>',
{src: './assets/page-body.png'}))
.append ($ ('<div>', {class: 'page-link-text'})
.append (i)))));
}
if (data.page < data.max)
{
($ ('.pagination')
.append ($ ('<li>', {class: 'page-item'})
.append ($ ('<a>',
{class: 'page-link',
href: 'javascript: void 0',
onclick: `Script.jumpTo (${ data.max })`})
.append ($ ('<img>',
{src: './assets/page-last.png'}))
.append ($ ('<div>', {class: 'page-link-text'})
.append ('&gt;|')))));
}
else
{
($ ('.pagination')
.append ($ ('<li>', {class: 'page-item disabled'})
.append ($ ('<span>', {class: 'page-link'})
.append ($ ('<img>',
{src: './assets/page-last.png'}))
.append ($ ('<div>', {class: 'page-link-text'})))));
}
$ ('#message-list').empty ();
for (let datum of data.data)
{
($ ('#message-list')
.append ($ ('<div>', {class: 'mb-4 message-block'})
.append ($ ('<div>')
.append ($ ('<span>', {
class: 'message-block-dt'})
.append (datum.dateTime)))
.append ($ ('<div>')
.append ($ ('<img>', {src: datum.chatIcon,
width: '64',
height: '64'}))
.append (datum.chatName))
.append ($ ('<div>', {style: 'color: blue'})
.append ('&gt; ')
.append ($ ('<span>',
{class: 'message-block-chat',
style: 'font-style: italic'})
.append (datum.chatMessage)))
.append ($ ('<div>')
.append ($ ('<span>',
{class: 'message-block-answer'})
.append (datum.answer)))));
}
$ ('.message-block').on ('click', function ()
{
const dt = $ (this).find ('.message-block-dt').text ();
const chat = $ (this).find ('.message-block-chat').text ();
const answer = $ (this).find ('.message-block-answer').text ();
window.open (
`./talk.php?dt=${dt}&chat=${chat}&answer=${answer}`);
});
if (data.data.length > 0)
$ ('nav').removeClass ('d-none');
else
{
$ ('nav').addClass ('d-none');
($ ('#message-list')
.text ('何も見つかりませんでしたぬ゛ぅ゛ぅ゛ぅ゛ぅ゛ん゛'));
}
self.setPagination ();
};
$.post ({url: './services/fetch_data.php',
dataType: 'json',
data: postData})
.done (done);
}
} }
+67
ファイルの表示
@@ -0,0 +1,67 @@
<?php
const LOG_PATH = '../log.txt';
header ('Content-Type: application/json; charset=UTF-8');
$log_data = [];
$page = (int) (filter_input (INPUT_POST, 'p') ?? 1);
$length = (int) (filter_input (INPUT_POST, 'max') ?? 20);
$asc = (int) (filter_input (INPUT_POST, 'asc') ?? 0) !== 0;
$keyword = trim (filter_input (INPUT_POST, 'q') ?? '');
$date_start = filter_input (INPUT_POST, 'start');
$date_end = filter_input (INPUT_POST, 'end');
$f = fopen (LOG_PATH, 'r');
if ($f !== false)
{
while (($dt = fgetcsv ($f, 0, "\t")) !== false)
{
$chat_info = json_decode ($dt[1]);
$log_data[] = ['dateTime' => $dt[0],
'chatIcon' => $chat_info -> author -> imageUrl,
'chatName' => htmlspecialchars ($chat_info -> author -> name),
'chatMessage' => htmlspecialchars ($chat_info -> message),
'answer' => htmlspecialchars ($dt[2])];
}
}
fclose ($f);
unset ($f);
if ($keyword !== '')
{
$log_data = array_filter ($log_data, fn ($row) => (
strpos (($row['chatName'] . "\n" . $row['chatMessage'] . "\n"
. $row['answer']),
$keyword)
!== false));
}
if ($date_start)
{
$log_data = array_filter ($log_data, fn ($row) => (
substr ($row['dateTime'], 0, 10) >= $date_start));
}
if ($date_end)
{
$log_data = array_filter ($log_data, fn ($row) => (
substr ($row['dateTime'], 0, 10) <= $date_end));
}
$pages_max = (int) ((count ($log_data) - 1) / $length) + 1;
if (!($asc))
$log_data = array_reverse ($log_data);
$log_data = array_slice ($log_data, ($page - 1) * $length, $length, false);
echo ('{"data": ' . json_encode ($log_data) . ', "max": ' . $pages_max
. ', "page": ' . $page . '}');
+32
ファイルの表示
@@ -0,0 +1,32 @@
/* vim:set tabstop=2 softtabstop=2 expandtab :*/
@font-face
{
font-family: 'Nikumaru';
src: url(./assets/nikumaru.otf);
}
html, body
{
overflow: hidden;
}
body
{
background-color: black;
}
#canvas
{
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: unset;
border: none
!important;
outline: none
!important;
display: block;
}
+23
ファイルの表示
@@ -0,0 +1,23 @@
<!-- vim:set tabstop=4 softtabstop=4 expandtab :-->
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="./talk.css?<?= filemtime ('./talk.css') ?>" />
<link rel="preconnect" href="./assets/nikumaru.otf" />
<title>あほ</title>
<input type="hidden" id="dt" value="<?= $dt ?>" />
<input type="hidden" id="chat" value="<?= $chat ?>" />
<input type="hidden" id="answer" value="<?= $answer ?>" />
</head>
<body>
<canvas id="canvas"></canvas>
<script src="./talk.js?<?= filemtime ('./talk.js') ?>" type="module"></script>
</body>
</html>
+136
ファイルの表示
@@ -0,0 +1,136 @@
import CommonModule from './common_module.js';
class
Talk
{
static
main ()
{
const canvas = new Canvas;
window.onresize = () => canvas.resize ();
}
}
class
Canvas
{
constructor ()
{
this.canvas = $ ('#canvas');
this.ctx = this.canvas[0].getContext ('2d');
(this.bg = new Image ()).src = './assets/bg.jpg';
this.bg.onload = () => this.resize ();
(this.nizika = new Image ()).src = './assets/nizika.png';
this.nizika.onload = () => this.resize ();
(this.talking = new Image ()).src = './assets/talking.png';
this.talking.onload = () => this.resize ();
(new FontFace ('Nikumaru', 'url(./assets/nikumaru.otf)')).load ().then (
() => this.resize ());
}
resize ()
{
this.canvas[0].width = $ (window).width ();
this.canvas[0].height = $ (window).height ();
this.redraw ();
}
redraw ()
{
this.putBG ();
this.putText (0, 0, 15, $ ('#dt').val ());
this.putImage (this.nizika, 370, 260, 1.1);
this.putImage (this.talking, 0, 0, 640 / 1024);
this.putText (75, 43.75, 20,
('> ' + ((CommonModule.lenByFull ($ ('#chat').val ()) <= 21)
? $ ('#chat').val ()
: (CommonModule.midByFull ($ ('#chat').val (), 0, 19.5)
+ '...'))),
undefined, undefined,
true);
this.putText (62.5, 93.75, 31.25,
((CommonModule.lenByFull ($ ('#answer').val ()) <= 16)
? $ ('#answer').val ()
: CommonModule.midByFull ($ ('#answer').val (), 0, 16)),
'Nikumaru', '#c00000');
if (CommonModule.lenByFull ($ ('#answer').val ()) > 16)
{
this.putText (62.5, 125, 31.25,
((CommonModule.lenByFull ($ ('#answer').val ()) <= 32)
? CommonModule.midByFull ($ ('#answer').val (), 16, 16)
: (CommonModule.midByFull ($ ('#answer').val (), 16, 14.5)
+ '...')),
'Nikumaru', '#c00000');
}
}
putBG ()
{
const [x, y, zoom] = this.convertPosition (0, 0);
const width = this.bg.height * 4 / 3;
const height = this.bg.height;
this.ctx.drawImage (this.bg,
(852 - 640) / 2, 0, width, height,
x, y, width * zoom, height * zoom);
}
putImage (image, x, y, zoom = 1)
{
let zoom2
[x, y, zoom2] = this.convertPosition (x, y);
zoom *= zoom2
this.ctx.drawImage (image,
0, 0, image.width, image.height,
x, y, image.width * zoom, image.height * zoom);
}
putText (x, y, size, text, style = 'sans-serif', colour = 'black',
italic = false)
{
let zoom;
[x, y, zoom] = this.convertPosition (x, y);
size *= zoom;
this.ctx.font = `${italic ? 'italic ' : ''}${Math.trunc (size)}px ${style}`;
this.ctx.fillStyle = colour;
this.ctx.textBaseline = 'top';
this.ctx.fillText (text, x, y);
}
convertPosition (x, y)
{
const sizeX = this.canvas.width ();
const sizeY = this.canvas.height ();
const width = this.bg.height * 4 / 3;
const height = this.bg.height;
const vertical = sizeY / sizeX > height / width;
const zoom = vertical ? (sizeX / width) : (sizeY / height);
const baseX = vertical ? 0 : ((sizeX - width * zoom) / 2);
const baseY = vertical ? ((sizeY - height * zoom) / 2) : 0;
return [baseX + x * zoom, baseY + y * zoom, zoom];
}
}
$ (() => Talk.main ());
+11
ファイルの表示
@@ -0,0 +1,11 @@
<?php
if ($_SERVER['HTTP_HOST'] === 'nizika.monster')
header ('location: //nizika.tv/talk.php');
$dt = htmlspecialchars ($_GET['dt']);
$chat = htmlspecialchars ($_GET['chat']);
$answer = htmlspecialchars ($_GET['answer']);
require_once './talk.frm.php';
+3
ファイルの表示
@@ -0,0 +1,3 @@
<?php
exec ('git pull');