The state is _everywhere_.
This commit is contained in:
parent
4c8609d7c7
commit
f182fb24bf
|
@ -1,2 +1,24 @@
|
||||||
time
|
time
|
||||||
tz
|
tz
|
||||||
|
reload
|
||||||
|
rm
|
||||||
|
boom
|
||||||
|
destroy
|
||||||
|
wipe
|
||||||
|
timer
|
||||||
|
at
|
||||||
|
slapping
|
||||||
|
slapme
|
||||||
|
autoslap
|
||||||
|
doc
|
||||||
|
noslap
|
||||||
|
temp
|
||||||
|
temperature
|
||||||
|
weather
|
||||||
|
define
|
||||||
|
crontab
|
||||||
|
group
|
||||||
|
groups
|
||||||
|
tr
|
||||||
|
char
|
||||||
|
unicode
|
||||||
|
|
|
@ -3,15 +3,18 @@
|
||||||
. /home/zgrep/offtopiabday/happybot/common.sh
|
. /home/zgrep/offtopiabday/happybot/common.sh
|
||||||
|
|
||||||
irc | while read -r n m; do
|
irc | while read -r n m; do
|
||||||
m=$(var "$m" | sed 's/[^][A-Za-z0-9\\\-{}^|_` ]//g');
|
if hreg '^happybot[:,]\s+[STst][lL]=' "$m"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
m=$(var "$m" | sed 's/[^][A-Za-z0-9\\{}^|_` -]//g');
|
||||||
var "$m";
|
var "$m";
|
||||||
if reg '^(?:[hH][aA][pP][pP][yY]|[hH][aA][tT][eE])[bB][oO][tT] (\S+) (\S+)$' "$m" && ! grep -Fxq -- "$(m 1 | tr 'A-Z' 'a-z')" happybot/act-ignore.txt; then
|
if reg '^(?:[hH][aA][pP][pP][yY]|[hH][aA][tT][eE])[bB][oO][tT] (\S+) (\S+)$' "$m" && ! grep -Fxq -- "$(m 1 | tr 'A-Z' 'a-z')" happybot/act-ignore.txt; then
|
||||||
echo "$n requested that I do '$(m 1)' to '$(m 2)'.";
|
echo "$n requested that I do '$(m 1)' to '$(m 2)'.";
|
||||||
a=$(var "$(m 1)" | tr 'A-Z' 'a-z' | sed 's/[^a-z ]//g')
|
who="$n"
|
||||||
if [ -z "$a" ]; then
|
a="$(m 1)"
|
||||||
var "$n: You're not using me properly. :(" | zwsp | say;
|
fa=$(var "$a" | tr 'A-Z' 'a-z' | sed 's/[^a-z0-9 ]//g')
|
||||||
elif [ "$a" == "zwsp" ]; then
|
if [ -z "$fa" ]; then
|
||||||
echo "Ignoring zwsp request.";
|
var "$n: That's not how I work. :(" | zwsp | say;
|
||||||
else
|
else
|
||||||
case "$(m 2)" in
|
case "$(m 2)" in
|
||||||
"happybot" | "hatebot" | "yourself" | "you" | "thyself" )
|
"happybot" | "hatebot" | "yourself" | "you" | "thyself" )
|
||||||
|
@ -30,19 +33,16 @@ irc | while read -r n m; do
|
||||||
"everybody" | "everyone" | "all")
|
"everybody" | "everyone" | "all")
|
||||||
n="$chan"
|
n="$chan"
|
||||||
;;
|
;;
|
||||||
"errybody" | "erryone")
|
|
||||||
n="erry"
|
|
||||||
;;
|
|
||||||
*)
|
*)
|
||||||
n="$(m 2)";
|
n="$(m 2)";
|
||||||
;;
|
;;
|
||||||
esac;
|
esac;
|
||||||
f="happybot/msgs/$a.sh";
|
f="happybot/msgs/$fa.sh";
|
||||||
if [ -e "$f" ]; then
|
if [ -e "$f" ]; then
|
||||||
sh happybot/msgs/$a.sh "$n" "$chan" > /tmp/tmpact.txt;
|
sh happybot/msgs/$fa.sh "$n" "$chan" "$serv" > /tmp/tmpact.txt;
|
||||||
f="/tmp/tmpact.txt";
|
f="/tmp/tmpact.txt";
|
||||||
else
|
else
|
||||||
f="happybot/msgs/$a.txt";
|
f="happybot/msgs/$fa.txt";
|
||||||
if [ ! -e "$f" ]; then
|
if [ ! -e "$f" ]; then
|
||||||
f="happybot/msgs/_.txt";
|
f="happybot/msgs/_.txt";
|
||||||
fi;
|
fi;
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env ash
|
||||||
|
|
||||||
|
. /home/zgrep/offtopiabday/happybot/common.sh
|
||||||
|
|
||||||
|
chanlist="${chanlist:-}"
|
||||||
|
pwfile="${pwfile:-}"
|
||||||
|
|
||||||
|
if [ -z "$chanlist" ]; then
|
||||||
|
echo "Need channel list."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# - Read logs.
|
||||||
|
# - Print when we get message 376.
|
||||||
|
|
||||||
|
tail -n 0 -f "$serv/out" | while read -r l; do
|
||||||
|
if [ -z "$(var "$l" | sed -n '/^\S\S* \S\S* \[376\]/p')" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -z "$pwfile" ]; then
|
||||||
|
cat "$pwfile" > '/home/zgrep/offtopiabday/'"$serv"'/in'
|
||||||
|
sleep 0.5
|
||||||
|
fi
|
||||||
|
echo '/JOIN '"$chanlist" > '/home/zgrep/offtopiabday/'"$serv"'/in'
|
||||||
|
done
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env ash
|
#!/usr/bin/env ash
|
||||||
|
|
||||||
chan="$1";
|
chan="$1";
|
||||||
serv="irc.freenode.net";
|
serv="${serv:-irc.freenode.net}";
|
||||||
cd "/home/zgrep/offtopiabday" || exit 1;
|
cd "/home/zgrep/offtopiabday" || exit 1;
|
||||||
|
|
||||||
var() { printf '%s\n' "$1"; }
|
var() { printf '%s\n' "$1"; }
|
||||||
|
@ -10,7 +10,7 @@ alias safe="sed 's%^/%//%'"
|
||||||
log="$serv/$chan/out";
|
log="$serv/$chan/out";
|
||||||
|
|
||||||
irc() {
|
irc() {
|
||||||
tail -0 -f "$serv/$chan/out" | while read -r l; do
|
tail -n 0 -f "$serv/$chan/out" | while read -r l; do
|
||||||
var "$l" | sed 's/^[^<]*<//' | sed 's/>//';
|
var "$l" | sed 's/^[^<]*<//' | sed 's/>//';
|
||||||
done;
|
done;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,18 @@ m() { var "$r" | sed -n "$1p"; }
|
||||||
|
|
||||||
zwsp=$(python3 -c 'print("\u200b",end="")');
|
zwsp=$(python3 -c 'print("\u200b",end="")');
|
||||||
zwsp() { cat - | sed 's%^\(/m \)\?%\1'"$zwsp"'%'; }
|
zwsp() { cat - | sed 's%^\(/m \)\?%\1'"$zwsp"'%'; }
|
||||||
|
x01=$(python3 -c 'print("\x01",end="")');
|
||||||
|
|
||||||
|
zirc() {
|
||||||
|
irc | while read -r n l; do
|
||||||
|
l="$(var "$l" | grep -vE "^${zwsp}|^${x01}ACTION ${zwsp}")"
|
||||||
|
if [ -z "$l" ]; then
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
var "$n $l"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
nth() {
|
nth() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
|
|
@ -0,0 +1,444 @@
|
||||||
|
// From crontab.guru.
|
||||||
|
|
||||||
|
// 10
|
||||||
|
let describe = (function (e, t, n) {
|
||||||
|
'use strict';
|
||||||
|
function u(e) {
|
||||||
|
var t = parseInt(e);
|
||||||
|
switch (20 < t ? t % 10 : t) {
|
||||||
|
case 1:
|
||||||
|
return e + 'st';
|
||||||
|
case 2:
|
||||||
|
return e + 'nd';
|
||||||
|
case 3:
|
||||||
|
return e + 'rd';
|
||||||
|
default:
|
||||||
|
return e + 'th'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function i(e, t, n, r) {
|
||||||
|
return '*' === e ? 'every ' + t : function (e, t, n, r) {
|
||||||
|
var o = e.match(/\d+|./g).map(function (e) {
|
||||||
|
var t = Number(e);
|
||||||
|
return isNaN(t) ? e : t
|
||||||
|
}),
|
||||||
|
a = o[0];
|
||||||
|
if (Number.isInteger(a)) {
|
||||||
|
if (1 === o.length) return '' + (n[a] || a);
|
||||||
|
if (3 === o.length && '/' === o[1] && Number.isInteger(o[2])) return 'every ' + u(o[2]) + ' ' + t + ' from ' + (n[a] || a) + ' through ' + (n[r] || r);
|
||||||
|
if (3 === o.length && '-' === o[1] && Number.isInteger(o[2]) && o[2] >= a) return 'every ' + t + ' from ' + (n[a] || a) + ' through ' + (n[o[2]] || o[2]);
|
||||||
|
if (5 === o.length && '-' === o[1] && Number.isInteger(o[2]) && o[2] >= a && '/' === o[3] && Number.isInteger(o[4]) && 1 <= o[4]) return 'every ' + u(o[4]) + ' ' + t + ' from ' + (n[a] || a) + ' through ' + (n[o[2]] || o[2])
|
||||||
|
} else if (3 === o.length && '/' === o[1] && Number.isInteger(o[2]) && '*' === o[0]) return 'every ' + u(o[2]) + ' ' + t;
|
||||||
|
return ''
|
||||||
|
}(e, t, n, r)
|
||||||
|
}
|
||||||
|
function h(e, t, n, r, o) {
|
||||||
|
var a = e.split(',');
|
||||||
|
return ((o ? '' : t + ' ') + function (e) {
|
||||||
|
switch (e.length) {
|
||||||
|
case 0:
|
||||||
|
return '';
|
||||||
|
case 1:
|
||||||
|
return e[0];
|
||||||
|
case 2:
|
||||||
|
return e[0] + ' and ' + e[1];
|
||||||
|
default:
|
||||||
|
return e.slice(0, e.length - 1).join(', ') + ', and ' + e[e.length - 1]
|
||||||
|
}
|
||||||
|
}(a.map(function (e) {
|
||||||
|
return i(e, t, n, r)
|
||||||
|
}))).replace('every 1st', 'every').replace(t + ' every', 'every').replace(', ' + t, ', ').replace(', and ' + t, ', and ')
|
||||||
|
}
|
||||||
|
var v = [
|
||||||
|
null,
|
||||||
|
'January',
|
||||||
|
'February',
|
||||||
|
'March',
|
||||||
|
'April',
|
||||||
|
'May',
|
||||||
|
'June',
|
||||||
|
'July',
|
||||||
|
'August',
|
||||||
|
'September',
|
||||||
|
'October',
|
||||||
|
'November',
|
||||||
|
'December'
|
||||||
|
];
|
||||||
|
var y = [
|
||||||
|
'Sunday',
|
||||||
|
'Monday',
|
||||||
|
'Tuesday',
|
||||||
|
'Wednesday',
|
||||||
|
'Thursday',
|
||||||
|
'Friday',
|
||||||
|
'Saturday',
|
||||||
|
'Sunday'
|
||||||
|
];
|
||||||
|
var b = /^0*\d\d?$/;
|
||||||
|
var g = 'After rebooting.';
|
||||||
|
return function (e) {
|
||||||
|
if ('@reboot' === e.originalParts[0]) return {
|
||||||
|
full: g,
|
||||||
|
special: g
|
||||||
|
};
|
||||||
|
var t,
|
||||||
|
n,
|
||||||
|
r,
|
||||||
|
o = e.parts,
|
||||||
|
a = '*' === (r = o[2]) ? '' : 'on ' + h(r, 'day-of-month', {
|
||||||
|
}, 31),
|
||||||
|
u = '*' === (n = o[3]) ? '' : 'in ' + h(n, 'month', v, 12, !0),
|
||||||
|
i = '*' === (t = o[4]) ? '' : 'on ' + h(t, 'day-of-week', y, 7, !0),
|
||||||
|
s = '';
|
||||||
|
a && i && (s = e.daysAnded ? 'if it\'s' : 'and');
|
||||||
|
var c,
|
||||||
|
l,
|
||||||
|
d = (c = o[0], l = o[1], b.test(c) && b.test(l) ? [
|
||||||
|
('0' + c).slice( - 2),
|
||||||
|
('0' + l).slice( - 2)
|
||||||
|
] : null);
|
||||||
|
if (d) return {
|
||||||
|
start: 'At',
|
||||||
|
minutes: d[0],
|
||||||
|
hours: d[1],
|
||||||
|
isTime: !0,
|
||||||
|
dates: a || null,
|
||||||
|
datesWeekdays: s || null,
|
||||||
|
weekdays: i || null,
|
||||||
|
months: u || null,
|
||||||
|
end: '.',
|
||||||
|
full: ('At ' + d[1] + ':' + d[0] + ' ' + a + ' ' + s + ' ' + i + ' ' + u).replace(/ +/g, ' ').trim() + '.'
|
||||||
|
};
|
||||||
|
var m,
|
||||||
|
f = h(o[0], 'minute', {
|
||||||
|
}, 59),
|
||||||
|
p = '*' === (m = o[1]) ? '' : 'past ' + h(m, 'hour', {
|
||||||
|
}, 23);
|
||||||
|
return {
|
||||||
|
start: 'At',
|
||||||
|
minutes: f || null,
|
||||||
|
hours: p || null,
|
||||||
|
dates: a || null,
|
||||||
|
datesWeekdays: s || null,
|
||||||
|
weekdays: i || null,
|
||||||
|
months: u || null,
|
||||||
|
end: '.',
|
||||||
|
full: ('At ' + f + ' ' + p + ' ' + a + ' ' + s + ' ' + i + ' ' + u).replace(/ +/g, ' ').trim() + '.'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
// 13
|
||||||
|
let normalize = (
|
||||||
|
function (e, t, n) {
|
||||||
|
'use strict';
|
||||||
|
function h(e, t) {
|
||||||
|
return e - t
|
||||||
|
}
|
||||||
|
function v(e) {
|
||||||
|
return e.reduce(function (e, t) {
|
||||||
|
return e.indexOf(t) < 0 && e.push(t),
|
||||||
|
e
|
||||||
|
}, [
|
||||||
|
])
|
||||||
|
}
|
||||||
|
function r(e) {
|
||||||
|
return e.reduce(function (e, t) {
|
||||||
|
return e.concat(Array.isArray(t) ? r(t) : t)
|
||||||
|
}, [
|
||||||
|
])
|
||||||
|
}
|
||||||
|
function o(e, t, n) {
|
||||||
|
for (var r = [
|
||||||
|
], o = e; o <= t; o += n) r.push(o);
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
var a = /(^|[,-/])\*($|[,-/])/g;
|
||||||
|
function y(e, t) {
|
||||||
|
var n = '$1' + t + '$2';
|
||||||
|
return e.replace(a, n).replace(a, n)
|
||||||
|
}
|
||||||
|
function b(e, t) {
|
||||||
|
var n = e.split(',').map(function (e) {
|
||||||
|
return function (e, t) {
|
||||||
|
var n = e ? e.match(/\d+|./g).map(function (e) {
|
||||||
|
var t = Number(e);
|
||||||
|
return isNaN(t) ? e : t
|
||||||
|
}) : [
|
||||||
|
],
|
||||||
|
r = n[0];
|
||||||
|
if (Number.isInteger(r)) {
|
||||||
|
if (1 === n.length) return {
|
||||||
|
list: [
|
||||||
|
r
|
||||||
|
]
|
||||||
|
};
|
||||||
|
if (3 === n.length && '/' === n[1] && Number.isInteger(n[2]) && 1 <= n[2]) return {
|
||||||
|
list: o(r, t, n[2]),
|
||||||
|
warnings: [
|
||||||
|
'nonstandard'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
if (3 === n.length && '-' === n[1] && Number.isInteger(n[2]) && n[2] >= r) return {
|
||||||
|
list: o(r, n[2], 1)
|
||||||
|
};
|
||||||
|
if (5 === n.length && '-' === n[1] && Number.isInteger(n[2]) && n[2] >= r && '/' === n[3] && Number.isInteger(n[4]) && 1 <= n[4]) return {
|
||||||
|
list: o(r, n[2], n[4])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
errors: [
|
||||||
|
'invalid part'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}(e, t)
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
list: v(r(n.map(function (e) {
|
||||||
|
return e.list || [
|
||||||
|
]
|
||||||
|
}))).sort(h).filter(function (e) {
|
||||||
|
return !isNaN(e)
|
||||||
|
}),
|
||||||
|
errors: v(r(n.map(function (e) {
|
||||||
|
return e.errors || [
|
||||||
|
]
|
||||||
|
}))),
|
||||||
|
warnings: v(r(n.map(function (e) {
|
||||||
|
return e.warnings || [
|
||||||
|
]
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function g(e, t, n) {
|
||||||
|
return e.length && (e[0] < t || e[e.length - 1] > n)
|
||||||
|
}
|
||||||
|
var w = /[^\d\-\/\,]/i;
|
||||||
|
return function (e) {
|
||||||
|
var t = e.parts.map(function (e) {
|
||||||
|
return e.slice(0)
|
||||||
|
}).map(function (e) {
|
||||||
|
return e.replace(/\*\/1(?!\d)/g, '*')
|
||||||
|
});
|
||||||
|
if (0 === t.length && e.originalParts.length) return {
|
||||||
|
};
|
||||||
|
var n = {
|
||||||
|
errors: [
|
||||||
|
],
|
||||||
|
warnings: [
|
||||||
|
]
|
||||||
|
};
|
||||||
|
if (void 0 !== e.daysAnded && (n.daysAnded = e.daysAnded), 5 !== t.length && n.errors.push('fields'), t[0] && t[0].length) {
|
||||||
|
var r = y(t[0], '0-59'),
|
||||||
|
o = b(r, 59);
|
||||||
|
n.minutes = o.list,
|
||||||
|
(o.errors.length || g(n.minutes, 0, 59) || w.test(r)) && (n.minutes = [
|
||||||
|
], n.errors.push('minutes')),
|
||||||
|
o.warnings.length && n.warnings.push('minutes')
|
||||||
|
} else void 0 === t[0] && n.errors.push('minutes');
|
||||||
|
if (t[1] && t[1].length) {
|
||||||
|
var a = y(t[1], '0-23'),
|
||||||
|
u = b(a, 23);
|
||||||
|
n.hours = u.list,
|
||||||
|
(u.errors.length || g(n.hours, 0, 23) || w.test(a)) && (n.hours = [
|
||||||
|
], n.errors.push('hours')),
|
||||||
|
u.warnings.length && n.warnings.push('hours')
|
||||||
|
} else void 0 === t[1] && n.errors.push('hours');
|
||||||
|
if (t[2] && t[2].length) {
|
||||||
|
var i = y(t[2], '1-31'),
|
||||||
|
s = b(i, 31);
|
||||||
|
n.dates = s.list,
|
||||||
|
(s.errors.length || g(n.dates, 1, 31) || w.test(i)) && (n.dates = [
|
||||||
|
], n.errors.push('dates')),
|
||||||
|
s.warnings.length && n.warnings.push('dates')
|
||||||
|
} else void 0 === t[2] && n.errors.push('dates');
|
||||||
|
if (t[3] && t[3].length) {
|
||||||
|
var c = y(t[3], '1-12'),
|
||||||
|
l = e.originalParts[3],
|
||||||
|
d = b(c, 12);
|
||||||
|
n.months = d.list,
|
||||||
|
(d.errors.length || g(n.months, 1, 12) || w.test(c)) && (n.months = [
|
||||||
|
], n.errors.push('months')),
|
||||||
|
(d.warnings.length || l && t[3] !== l && 3 < l.length && /\D/.test(l)) && n.warnings.push('months')
|
||||||
|
} else void 0 === t[3] && n.errors.push('months');
|
||||||
|
if (t[4] && t[4].length) {
|
||||||
|
var m = y(t[4], '0-6'),
|
||||||
|
f = e.originalParts[4],
|
||||||
|
p = b(m, 7);
|
||||||
|
n.weekdays = v(p.list.map(function (e) {
|
||||||
|
return 7 === e ? 0 : e
|
||||||
|
})).sort(h),
|
||||||
|
(p.errors.length || g(n.weekdays, 0, 6) || w.test(m)) && (n.weekdays = [
|
||||||
|
], n.errors.push('weekdays')),
|
||||||
|
(p.warnings.length || p.list.includes(7) || f && t[4] !== f && 3 < f.length && /\D/.test(f)) && n.warnings.push('weekdays')
|
||||||
|
} else void 0 === t[4] && n.errors.push('weekdays');
|
||||||
|
return n.errors.length || delete n.errors,
|
||||||
|
n.warnings.length || delete n.warnings,
|
||||||
|
n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)();
|
||||||
|
|
||||||
|
// 15
|
||||||
|
let parse = (function (e, t, n) {
|
||||||
|
'use strict';
|
||||||
|
function a(e, i) {
|
||||||
|
return Object.keys(i).reduce(function (e, t) {
|
||||||
|
return n = e,
|
||||||
|
o = i[r = t],
|
||||||
|
a = new RegExp('(^|[ ,-/])' + r + '($|[ ,-/])', 'gi'),
|
||||||
|
u = '$1' + o + '$2',
|
||||||
|
n.replace(a, u).replace(a, u);
|
||||||
|
var n,
|
||||||
|
r,
|
||||||
|
o,
|
||||||
|
a,
|
||||||
|
u
|
||||||
|
}, e)
|
||||||
|
}
|
||||||
|
var u = {
|
||||||
|
sun: '0',
|
||||||
|
mon: '1',
|
||||||
|
tue: '2',
|
||||||
|
wed: '3',
|
||||||
|
thu: '4',
|
||||||
|
fri: '5',
|
||||||
|
sat: '6'
|
||||||
|
};
|
||||||
|
var i = {
|
||||||
|
jan: '1',
|
||||||
|
feb: '2',
|
||||||
|
mar: '3',
|
||||||
|
apr: '4',
|
||||||
|
may: '5',
|
||||||
|
jun: '6',
|
||||||
|
jul: '7',
|
||||||
|
aug: '8',
|
||||||
|
sep: '9',
|
||||||
|
oct: '10',
|
||||||
|
nov: '11',
|
||||||
|
dec: '12'
|
||||||
|
};
|
||||||
|
var s = {
|
||||||
|
'@yearly': [
|
||||||
|
'0',
|
||||||
|
'0',
|
||||||
|
'1',
|
||||||
|
'1',
|
||||||
|
'*'
|
||||||
|
],
|
||||||
|
'@annually': [
|
||||||
|
'0',
|
||||||
|
'0',
|
||||||
|
'1',
|
||||||
|
'1',
|
||||||
|
'*'
|
||||||
|
],
|
||||||
|
'@monthly': [
|
||||||
|
'0',
|
||||||
|
'0',
|
||||||
|
'1',
|
||||||
|
'*',
|
||||||
|
'*'
|
||||||
|
],
|
||||||
|
'@weekly': [
|
||||||
|
'0',
|
||||||
|
'0',
|
||||||
|
'*',
|
||||||
|
'*',
|
||||||
|
'0'
|
||||||
|
],
|
||||||
|
'@daily': [
|
||||||
|
'0',
|
||||||
|
'0',
|
||||||
|
'*',
|
||||||
|
'*',
|
||||||
|
'*'
|
||||||
|
],
|
||||||
|
'@midnight': [
|
||||||
|
'0',
|
||||||
|
'0',
|
||||||
|
'*',
|
||||||
|
'*',
|
||||||
|
'*'
|
||||||
|
],
|
||||||
|
'@hourly': [
|
||||||
|
'0',
|
||||||
|
'*',
|
||||||
|
'*',
|
||||||
|
'*',
|
||||||
|
'*'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
return function (e) {
|
||||||
|
var t = e.trim().split(/\s+/).filter(function (e) {
|
||||||
|
return e
|
||||||
|
});
|
||||||
|
if (1 === t.length && '@reboot' === t[0]) return {
|
||||||
|
originalParts: t,
|
||||||
|
parts: [
|
||||||
|
]
|
||||||
|
};
|
||||||
|
var n,
|
||||||
|
r,
|
||||||
|
o = (1 === t.length ? (n = t[0], r = s[n], void 0 !== r ? r : [
|
||||||
|
n
|
||||||
|
]) : t).map(function (e, t) {
|
||||||
|
switch (t) {
|
||||||
|
case 3:
|
||||||
|
return a(e, i);
|
||||||
|
case 4:
|
||||||
|
return a(e, u);
|
||||||
|
default:
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
}); return {
|
||||||
|
originalParts: t,
|
||||||
|
parts: o,
|
||||||
|
daysAnded: !!o[2] && '*' === o[2][0] || !!o[4] && '*' === o[4][0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
let parsed, schedule;
|
||||||
|
|
||||||
|
try {
|
||||||
|
parsed = parse(process.argv[2]);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Could not parse crontab (#1).");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
schedule = normalize(parsed);
|
||||||
|
if (schedule.errors) {
|
||||||
|
if (schedule.errors.includes('fields')) {
|
||||||
|
console.log('Errors with crontab fields. Should be: minute hour day-of-month month day-of-week');
|
||||||
|
} else {
|
||||||
|
let copy = parsed.parts;
|
||||||
|
let r = [
|
||||||
|
'minutes',
|
||||||
|
'hours',
|
||||||
|
'dates',
|
||||||
|
'months',
|
||||||
|
'weekdays'
|
||||||
|
];
|
||||||
|
for (let f of schedule.errors) {
|
||||||
|
let c = r.indexOf(f);
|
||||||
|
copy[c] = '\x0304' + copy[c] + '\x03';
|
||||||
|
}
|
||||||
|
console.log('Error with crontab: ' + copy.join(' ') + ' (' + schedule.errors.join(', ') + ')')
|
||||||
|
}
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Could not parse crontab (#2).");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(describe(parsed).full);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Could not describe crontab.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env ash
|
||||||
|
|
||||||
|
. /home/zgrep/offtopiabday/happybot/common.sh
|
||||||
|
|
||||||
|
irc | while read -r n m; do
|
||||||
|
if hreg '^happybot[:,] crontab (.+)$' "$m"; then
|
||||||
|
node happybot/crontabguru.js "$(m 1)" | zwsp | say;
|
||||||
|
fi
|
||||||
|
done
|
|
@ -0,0 +1,61 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from json import loads as dejson
|
||||||
|
from itertools import zip_longest
|
||||||
|
|
||||||
|
if len(sys.argv) != 4:
|
||||||
|
print('Wrong number of arguments. Argue either more, or less.')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
_, say, defs, extra = sys.argv
|
||||||
|
|
||||||
|
say = say.strip()
|
||||||
|
if say:
|
||||||
|
say += ' '
|
||||||
|
|
||||||
|
kmap = {
|
||||||
|
'crossReference': 'x-ref',
|
||||||
|
'abbreviation': 'abbr.',
|
||||||
|
}
|
||||||
|
|
||||||
|
defs = dejson(defs)
|
||||||
|
rdefs = {}
|
||||||
|
order = []
|
||||||
|
for d in defs:
|
||||||
|
for k, v in d.items():
|
||||||
|
k = kmap.get(k, k)
|
||||||
|
if k not in order:
|
||||||
|
order.append(k)
|
||||||
|
rdefs[k] = rdefs.get(k, []) + [ v ]
|
||||||
|
|
||||||
|
for k in order:
|
||||||
|
rdefs[k] = [ v for t in zip_longest(*rdefs[k], [], fillvalue='') for v in t if v ]
|
||||||
|
|
||||||
|
defs = [ [ (k, v) for v in rdefs[k] ] for k in order ]
|
||||||
|
defs = [ v for l in zip(*defs) for v in l ]
|
||||||
|
|
||||||
|
length = 450
|
||||||
|
length -= len(say)
|
||||||
|
length -= len(extra)
|
||||||
|
|
||||||
|
def pprint(thing):
|
||||||
|
return ' '.join('\x02[' + p + ']\x0f ' + ' / '.join(ds + (['…'] if len(rdefs[p]) > len(ds) else [])) for p, ds in thing)
|
||||||
|
|
||||||
|
prevstr = ''
|
||||||
|
|
||||||
|
m = {}
|
||||||
|
thing = []
|
||||||
|
for k, v in defs:
|
||||||
|
if k in m:
|
||||||
|
thing[m[k]][1].append(v)
|
||||||
|
else:
|
||||||
|
m[k] = len(thing)
|
||||||
|
thing.append((k, [v]))
|
||||||
|
newstr = pprint(thing)
|
||||||
|
if len(newstr) <= length:
|
||||||
|
prevstr = newstr
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
print(say + prevstr + extra)
|
|
@ -0,0 +1,41 @@
|
||||||
|
#!/usr/bin/env ash
|
||||||
|
|
||||||
|
. /home/zgrep/offtopiabday/happybot/common.sh
|
||||||
|
|
||||||
|
irc | while read -r n m; do
|
||||||
|
if hreg '^happybot[:,] define( -w)?( \S+)? (\S+)$' "$m"; then
|
||||||
|
lang="$(m 2)"
|
||||||
|
word="$(m 3)"
|
||||||
|
wikt="$(m 1)"
|
||||||
|
elif reg '^#define( -w)?( \S+)? (\S+)$' "$m"; then
|
||||||
|
lang="$(m 2)"
|
||||||
|
word="$(m 3)"
|
||||||
|
wikt="$(m 1)"
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
fi
|
||||||
|
if [ -z "$lang" ]; then
|
||||||
|
lang="en"
|
||||||
|
fi
|
||||||
|
if [ -z "$wikt" ]; then
|
||||||
|
result="$(curl -s -g -G 'https://api.dictionaryapi.dev/api/v2/entries/'"$lang"'/'"$word")"
|
||||||
|
else
|
||||||
|
result="{}"
|
||||||
|
fi
|
||||||
|
if [ "$(var "$result" | jq -r 'type')" == "object" ]; then
|
||||||
|
result="$(python3 wiktionary/wiktionary.py "$lang" "$word")"
|
||||||
|
var "$result" | if ! grep -q '^\['; then
|
||||||
|
var "$result" | zwsp | say;
|
||||||
|
else
|
||||||
|
phonetics="$(var "$result" | jq -r '.[0]|unique|join(" ")')"
|
||||||
|
definitions="$(var "$result" | jq -r '.[1]')"
|
||||||
|
extra="$(var "$result" | jq -r '.[2]')"
|
||||||
|
python3 happybot/def-limit.py "$phonetics" "$definitions" "$extra" | zwsp | say
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
phonetics="$(var "$result" | jq -r 'map(.phonetics | map(.text)) | flatten | unique | join(" ")')"
|
||||||
|
definitions="$(var "$result" | jq -r 'map(.meanings | map( {(.partOfSpeech): (.definitions|map(.definition))} )) | flatten')"
|
||||||
|
extra=""
|
||||||
|
python3 happybot/def-limit.py "$phonetics" "$definitions" "$extra" | zwsp | say
|
||||||
|
fi
|
||||||
|
done
|
|
@ -0,0 +1,118 @@
|
||||||
|
#!/usr/bin/env ash
|
||||||
|
|
||||||
|
. /home/zgrep/offtopiabday/happybot/common.sh
|
||||||
|
|
||||||
|
d="happybot/dowork/people"
|
||||||
|
delay="300"
|
||||||
|
pause="7200"
|
||||||
|
|
||||||
|
irc | while read -r n m; do
|
||||||
|
n="$(var "$n" | tr -d './')"
|
||||||
|
if hreg '^happybot[:,] (?:noslap|(?:autoslap|slap(?:ping|me)) (?:pause|delay|wait|0?\.5|1/2|½))(?: ([0-9]+))?' "$m"; then
|
||||||
|
pse="$(m 1)"
|
||||||
|
if [ -z "$pse" ]; then
|
||||||
|
pse="$pause"
|
||||||
|
fi
|
||||||
|
if [ -e "$d/$n.delay" ]; then
|
||||||
|
dly="$(cat "$d/$n.delay")"
|
||||||
|
else
|
||||||
|
dly="$delay"
|
||||||
|
fi
|
||||||
|
rpause="$(echo "$pse - $dly" | bc)"
|
||||||
|
echo "$(dateadd -f '%s' 'now' "${rpause}s")" > "$d/$n.slap";
|
||||||
|
echo "${zwsp}Automatic slapping for $n paused until about ${pse}s from now." | say
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif hreg '^happybot[:,] (autoslap|slap(ping|me)) (public|loud)(ly)?' "$m"; then
|
||||||
|
grep -Fvxe "$n" "${d}_private.txt" > "${d}_private.2"
|
||||||
|
mv "${d}_private.2" "${d}_private.txt"
|
||||||
|
echo "${zwsp}I will automatically slap $n in public." | say;
|
||||||
|
continue
|
||||||
|
elif hreg '^happybot[:,] (autoslap|slap(ping|me)) (priv(msg|ate)?|secret(ive)?|quiet)(ly)?' "$m"; then
|
||||||
|
echo "$n" >> "${d}_private.txt"
|
||||||
|
sort -u "${d}_private.txt" > "${d}_private.2"
|
||||||
|
mv "${d}_private.2" "${d}_private.txt"
|
||||||
|
echo "${zwsp}I will automatically slap $n privately." | say;
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif hreg '^happybot[:,] (autoslap|slap(ping|me)) (stop|off|disable|no|0)' "$m"; then
|
||||||
|
grep -Fvxe "$n" "$d.txt" > "$d.2"
|
||||||
|
mv "$d.2" "$d.txt"
|
||||||
|
if [ -e "$d/$n.slap" ]; then
|
||||||
|
rm "$d/$n.slap";
|
||||||
|
fi
|
||||||
|
if [ -e "$d/$n.delay" ]; then
|
||||||
|
rm "$d/$n.delay";
|
||||||
|
fi
|
||||||
|
echo "${zwsp}I will no longer automatically slap $n." | say
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif hreg '^happybot[:,] (?:autoslap|slap(?:ping|me)) (?:start|on|enable|yes|1|set)(?: ([0-9]+))?' "$m"; then
|
||||||
|
dly="$(m 1)"
|
||||||
|
if [ ! -z "$dly" ]; then
|
||||||
|
echo "$dly" > "$d/$n.delay";
|
||||||
|
else
|
||||||
|
dly="$delay";
|
||||||
|
fi
|
||||||
|
echo "$n" >> "$d.txt"
|
||||||
|
sort -u "$d.txt" > "$d.2"
|
||||||
|
mv "$d.2" "$d.txt"
|
||||||
|
echo "${zwsp}I will slap $n every time they speak, at most once every ${dly}s." | say
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif hreg '^happybot[:,] (?:autoslap|slap(?:ping|me)) status(?: (\S+))?' "$m"; then
|
||||||
|
newn="$(m 1)"
|
||||||
|
if [ ! -z "$newn" ]; then
|
||||||
|
n="$newn"
|
||||||
|
fi
|
||||||
|
if grep -Fxqe "$n" "${d}_private.txt"; then
|
||||||
|
slaptype="private";
|
||||||
|
else
|
||||||
|
slaptype="public";
|
||||||
|
fi
|
||||||
|
if grep -Fxqe "$n" "$d.txt"; then
|
||||||
|
delta="$(datediff -i '%s' -f '%S' "$(cat "$d/$n.slap")" 'now')"
|
||||||
|
if [ -e "$d/$n.delay" ]; then
|
||||||
|
dly="$(cat "$d/$n.delay")"
|
||||||
|
else
|
||||||
|
dly="$delay"
|
||||||
|
fi
|
||||||
|
if [ "$delta" -le "$dly" ]; then
|
||||||
|
delta="$(echo "$dly - $delta" | bc)"
|
||||||
|
pstat="Not slapping for another ${delta}s."
|
||||||
|
else
|
||||||
|
pstat="Currently primed to slap."
|
||||||
|
fi
|
||||||
|
echo "${zwsp}I'm supposed to ${slaptype}ly slap ${n} at most once every ${dly}s. ${pstat}" | say;
|
||||||
|
else
|
||||||
|
echo "${zwsp}No automatic ${slaptype} slapping for ${n} yet." | say;
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif [ -s "$d.txt" ]; then
|
||||||
|
if grep -Fxqe "$n" "$d.txt"; then
|
||||||
|
if [ -e "$d/$n.slap" ]; then
|
||||||
|
delta="$(datediff -i '%s' -f '%S' "$(cat "$d/$n.slap")" 'now')"
|
||||||
|
if [ -e "$d/$n.delay" ]; then
|
||||||
|
dly="$(cat "$d/$n.delay")"
|
||||||
|
else
|
||||||
|
dly="$delay"
|
||||||
|
fi
|
||||||
|
if [ "$delta" -le "$dly" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "$(date +%s)" > "$d/$n.slap"
|
||||||
|
if [ -e "$d/$n.txt" ]; then
|
||||||
|
obj="$(rand "$d/$n.txt")"
|
||||||
|
else
|
||||||
|
obj="$(rand "${d}_generic.txt")"
|
||||||
|
fi
|
||||||
|
if grep -Fxqe "$n" "${d}_private.txt"; then
|
||||||
|
echo "/PRIVMSG ${n} :${x01}ACTION ${zwsp}slaps you with $obj.${x01}" | say;
|
||||||
|
else
|
||||||
|
echo "/m ${zwsp}slaps $n with $obj." | say;
|
||||||
|
fi
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
done;
|
|
@ -0,0 +1,24 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import requests as rq
|
||||||
|
from lxml import html
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
if len(argv) != 2:
|
||||||
|
print('Not enough arguments. Bug zgrep.')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
q = argv[1]
|
||||||
|
|
||||||
|
r = rq.get('http://ichi.moe/cl/qr/', params={'q': q})
|
||||||
|
|
||||||
|
if r.status_code != 200:
|
||||||
|
print('Non-200 status code. Bug zgrep.')
|
||||||
|
exit()
|
||||||
|
|
||||||
|
# tree
|
||||||
|
t = html.fromstring(r.content)
|
||||||
|
|
||||||
|
ichi = ''.join(t.xpath('//span[@class="ds-text"]//text()'))
|
||||||
|
|
||||||
|
print(ichi)
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env ash
|
||||||
|
|
||||||
|
. /home/zgrep/offtopiabday/happybot/common.sh
|
||||||
|
|
||||||
|
irc | while read -r n m; do
|
||||||
|
if reg '^(happy|hate)bot[:,] ichi (.*)' "$m"; then
|
||||||
|
python3 happybot/ichi.py "$(m 2)" | say;
|
||||||
|
fi;
|
||||||
|
done;
|
|
@ -0,0 +1,48 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
. /home/zgrep/offtopiabday/happybot/common.sh
|
||||||
|
|
||||||
|
segment() {
|
||||||
|
sed 's/[a-zA-Z][a-zA-Z]*:\/\/\S*\|./&\n/g' | sed -n '/./p'
|
||||||
|
}
|
||||||
|
|
||||||
|
oldtopic="$(
|
||||||
|
tac "$serv/$chan/out" \
|
||||||
|
| awk '{if($3" "$5$6$7=="-!- changedtopicto"){print;exit}}' \
|
||||||
|
| sed 's/^[^"]*"//;s/"$//'
|
||||||
|
)"
|
||||||
|
|
||||||
|
tail -n 0 -f "$serv/$chan/out" | gawk '{if($3" "$5$6$7=="-!- changedtopicto"){gsub(/^[^"]*"/,"");gsub(/"$/,"");print;fflush("/dev/stdout")}}' | while read -r t; do
|
||||||
|
if [[ "$t" != "$oldtopic" ]]; then
|
||||||
|
diff="(diff) "
|
||||||
|
mode="_"
|
||||||
|
diff="$(diff -a -d -U 1024 <(var "$oldtopic" | segment) <(var "$t" | segment) \
|
||||||
|
| tail -n+4 | sed 's/^ /_/;s/^./& _/;s/$/_/' \
|
||||||
|
| while read -r d l; do
|
||||||
|
l="$(var "$l" | sed 's/^_//;s/_$//')"
|
||||||
|
p=""
|
||||||
|
if [[ "$mode" != "$d" ]]; then
|
||||||
|
if [[ "$d" == "-" ]]; then
|
||||||
|
if [[ "$mode" == "+" ]]; then
|
||||||
|
p="$(echo -ne "\x0305,99")"
|
||||||
|
else
|
||||||
|
p="$(echo -ne "\x1f\x0305,99")"
|
||||||
|
fi
|
||||||
|
elif [[ "$d" == "+" ]]; then
|
||||||
|
if [[ "$mode" == "-" ]]; then
|
||||||
|
p="$(echo -ne "\x0303,99")"
|
||||||
|
else
|
||||||
|
p="$(echo -ne "\x1f\x0303,99")"
|
||||||
|
fi
|
||||||
|
elif [[ "$d" == "_" ]]; then
|
||||||
|
p="$(echo -ne "\x0f")"
|
||||||
|
fi
|
||||||
|
mode="$d"
|
||||||
|
fi
|
||||||
|
diff="$diff$p$l"
|
||||||
|
var "$diff"
|
||||||
|
done | tail -n1)"
|
||||||
|
var "$diff" | zwsp | say
|
||||||
|
oldtopic="$t"
|
||||||
|
fi
|
||||||
|
done
|
105
ii/ii.c
105
ii/ii.c
|
@ -18,12 +18,23 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
#ifndef PIPE_BUF /* For OS that doesn't includes PIPE_BUF in limits.h, FreeBSD? */
|
#ifndef PIPE_BUF /* For OS that doesn't includes PIPE_BUF in limits.h, FreeBSD? */
|
||||||
#define PIPE_BUF _POSIX_PIPE_BUF
|
#define PIPE_BUF _POSIX_PIPE_BUF
|
||||||
#endif
|
#endif
|
||||||
#define PING_TIMEOUT 300
|
#define PING_TIMEOUT 300
|
||||||
#define SERVER_PORT 6667
|
#define SERVER_PORT 6667
|
||||||
|
#define SSL_SERVER_PORT 6697
|
||||||
|
#define WRITE(con, mes, len) (use_ssl ? SSL_write(irc->sslHandle, mes, len) : write(con->irc, mes, len))
|
||||||
|
#define READ(fd, buf, size) (from_server && use_ssl ? SSL_read(irc->sslHandle, buf, size) : read(fd, buf, size))
|
||||||
|
typedef struct {
|
||||||
|
int irc;
|
||||||
|
SSL *sslHandle;
|
||||||
|
SSL_CTX *sslContext;
|
||||||
|
} conn;
|
||||||
enum { TOK_NICKSRV = 0, TOK_USER, TOK_CMD, TOK_CHAN, TOK_ARG, TOK_TEXT, TOK_LAST };
|
enum { TOK_NICKSRV = 0, TOK_USER, TOK_CMD, TOK_CHAN, TOK_ARG, TOK_TEXT, TOK_LAST };
|
||||||
|
|
||||||
typedef struct Channel Channel;
|
typedef struct Channel Channel;
|
||||||
|
@ -33,7 +44,8 @@ struct Channel {
|
||||||
Channel *next;
|
Channel *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int irc;
|
conn *irc;
|
||||||
|
static int use_ssl;
|
||||||
static time_t last_response;
|
static time_t last_response;
|
||||||
static Channel *channels = NULL;
|
static Channel *channels = NULL;
|
||||||
static char *host = "irc.freenode.net";
|
static char *host = "irc.freenode.net";
|
||||||
|
@ -46,7 +58,7 @@ static void usage() {
|
||||||
fputs("ii - irc it - " VERSION "\n"
|
fputs("ii - irc it - " VERSION "\n"
|
||||||
"(C)opyright MMV-MMVI Anselm R. Garbe\n"
|
"(C)opyright MMV-MMVI Anselm R. Garbe\n"
|
||||||
"(C)opyright MMV-MMXI Nico Golde\n"
|
"(C)opyright MMV-MMXI Nico Golde\n"
|
||||||
"usage: ii [-i <irc dir>] [-s <host>] [-p <port>]\n"
|
"usage: ii [-i <irc dir>] [-s <host>] [-p <port>] [-e ssl]\n"
|
||||||
" [-n <nick>] [-k <password>] [-f <fullname>]\n", stderr);
|
" [-n <nick>] [-k <password>] [-f <fullname>]\n", stderr);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -149,11 +161,12 @@ static void login(char *key, char *fullname) {
|
||||||
nick, nick, host, fullname ? fullname : nick);
|
nick, nick, host, fullname ? fullname : nick);
|
||||||
else snprintf(message, PIPE_BUF, "NICK %s\r\nUSER %s localhost %s :%s\r\n",
|
else snprintf(message, PIPE_BUF, "NICK %s\r\nUSER %s localhost %s :%s\r\n",
|
||||||
nick, nick, host, fullname ? fullname : nick);
|
nick, nick, host, fullname ? fullname : nick);
|
||||||
write(irc, message, strlen(message)); /* login */
|
WRITE(irc, message, strlen(message)); /* login */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tcpopen(unsigned short port) {
|
conn *tcpopen(unsigned short port) {
|
||||||
int fd;
|
int fd;
|
||||||
|
conn *c;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
struct hostent *hp = gethostbyname(host);
|
struct hostent *hp = gethostbyname(host);
|
||||||
|
|
||||||
|
@ -173,7 +186,22 @@ static int tcpopen(unsigned short port) {
|
||||||
perror("ii: cannot connect to host");
|
perror("ii: cannot connect to host");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
return fd;
|
c = malloc(sizeof(conn));
|
||||||
|
c->irc = fd;
|
||||||
|
if(use_ssl) {
|
||||||
|
c->sslHandle = NULL;
|
||||||
|
c->sslContext = NULL;
|
||||||
|
SSL_load_error_strings();
|
||||||
|
SSL_library_init();
|
||||||
|
c->sslContext = SSL_CTX_new(SSLv23_client_method());
|
||||||
|
if(c->sslContext == NULL)
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
c->sslHandle = SSL_new(c->sslContext);
|
||||||
|
if(!SSL_set_fd(c->sslHandle, c->irc)
|
||||||
|
|| (SSL_connect(c->sslHandle) != 1))
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
}
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t tokenize(char **result, size_t reslen, char *str, char delim) {
|
static size_t tokenize(char **result, size_t reslen, char *str, char delim) {
|
||||||
|
@ -220,7 +248,7 @@ static void proc_channels_privmsg(char *channel, char *buf) {
|
||||||
snprintf(message, PIPE_BUF, "<%s> %s", nick, buf);
|
snprintf(message, PIPE_BUF, "<%s> %s", nick, buf);
|
||||||
print_out(channel, message);
|
print_out(channel, message);
|
||||||
snprintf(message, PIPE_BUF, "PRIVMSG %s :%s\r\n", channel, buf);
|
snprintf(message, PIPE_BUF, "PRIVMSG %s :%s\r\n", channel, buf);
|
||||||
write(irc, message, strlen(message));
|
WRITE(irc, message, strlen(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void proc_channels_input(Channel *c, char *buf) {
|
static void proc_channels_input(Channel *c, char *buf) {
|
||||||
|
@ -275,7 +303,7 @@ static void proc_channels_input(Channel *c, char *buf) {
|
||||||
else
|
else
|
||||||
snprintf(message, PIPE_BUF,
|
snprintf(message, PIPE_BUF,
|
||||||
"PART %s :byeeeee\r\n", c->name);
|
"PART %s :byeeeee\r\n", c->name);
|
||||||
write(irc, message, strlen(message));
|
WRITE(irc, message, strlen(message));
|
||||||
close(c->fd);
|
close(c->fd);
|
||||||
/*create_filepath(infile, sizeof(infile), c->name, "in");
|
/*create_filepath(infile, sizeof(infile), c->name, "in");
|
||||||
unlink(infile); */
|
unlink(infile); */
|
||||||
|
@ -311,7 +339,7 @@ static void proc_channels_input(Channel *c, char *buf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message[0] != '\0')
|
if (message[0] != '\0')
|
||||||
write(irc, message, strlen(message));
|
WRITE(irc, message, strlen(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void proc_server_cmd(char *buf) {
|
static void proc_server_cmd(char *buf) {
|
||||||
|
@ -359,67 +387,71 @@ static void proc_server_cmd(char *buf) {
|
||||||
|
|
||||||
tokenize(&argv[TOK_CMD], TOK_LAST - TOK_CMD, cmd, ' ');
|
tokenize(&argv[TOK_CMD], TOK_LAST - TOK_CMD, cmd, ' ');
|
||||||
|
|
||||||
if(!argv[TOK_CMD] || !strncmp("PONG", argv[TOK_CMD], 5)) {
|
if(!argv[TOK_CMD]) {
|
||||||
return;
|
return;
|
||||||
|
} else if(!strncmp("PONG", argv[TOK_CMD], 5)) {
|
||||||
|
snprintf(message, PIPE_BUF, "-!- pong %s", argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
||||||
} else if(!strncmp("PING", argv[TOK_CMD], 5)) {
|
} else if(!strncmp("PING", argv[TOK_CMD], 5)) {
|
||||||
snprintf(message, PIPE_BUF, "PONG %s\r\n", argv[TOK_TEXT]);
|
snprintf(message, PIPE_BUF, "PONG %s\r\n", argv[TOK_TEXT]);
|
||||||
write(irc, message, strlen(message));
|
WRITE(irc, message, strlen(message));
|
||||||
return;
|
return;
|
||||||
} else if(!argv[TOK_NICKSRV] || !argv[TOK_USER]) { /* server command */
|
} else if(!argv[TOK_NICKSRV] || !argv[TOK_USER]) { /* server command */
|
||||||
snprintf(message, PIPE_BUF, "%s%s", argv[TOK_ARG] ? argv[TOK_ARG] : "", argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
snprintf(message, PIPE_BUF, "[%s] %s%s", argv[TOK_CMD], argv[TOK_ARG] ? argv[TOK_ARG] : "", argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
||||||
print_out(0, message);
|
print_out(0, message);
|
||||||
return;
|
return;
|
||||||
} else if(!strncmp("ERROR", argv[TOK_CMD], 6))
|
} else if(!strncmp("ERROR", argv[TOK_CMD], 6)) {
|
||||||
snprintf(message, PIPE_BUF, "-!- error %s", argv[TOK_TEXT] ? argv[TOK_TEXT] : "unknown");
|
snprintf(message, PIPE_BUF, "-!- error %s", argv[TOK_TEXT] ? argv[TOK_TEXT] : "unknown");
|
||||||
else if(!strncmp("JOIN", argv[TOK_CMD], 5) && (argv[TOK_CHAN] || argv[TOK_TEXT])) {
|
} else if(!strncmp("JOIN", argv[TOK_CMD], 5) && (argv[TOK_CHAN] || argv[TOK_TEXT])) {
|
||||||
if (argv[TOK_TEXT] != NULL)
|
if (argv[TOK_TEXT] != NULL)
|
||||||
argv[TOK_CHAN] = argv[TOK_TEXT];
|
argv[TOK_CHAN] = argv[TOK_TEXT];
|
||||||
snprintf(message, PIPE_BUF, "-!- %s(%s) has joined %s", argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]);
|
snprintf(message, PIPE_BUF, "-!- %s(%s) has joined %s", argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]);
|
||||||
} else if(!strncmp("PART", argv[TOK_CMD], 5) && argv[TOK_CHAN]) {
|
} else if(!strncmp("PART", argv[TOK_CMD], 5) && argv[TOK_CHAN]) {
|
||||||
snprintf(message, PIPE_BUF, "-!- %s(%s) has left %s", argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]);
|
snprintf(message, PIPE_BUF, "-!- %s(%s) has left %s", argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_CHAN]);
|
||||||
} else if(!strncmp("MODE", argv[TOK_CMD], 5))
|
} else if(!strncmp("MODE", argv[TOK_CMD], 5)) {
|
||||||
snprintf(message, PIPE_BUF, "-!- %s changed mode/%s -> %s %s", argv[TOK_NICKSRV], argv[TOK_CMD + 1] ? argv[TOK_CMD + 1] : "" , argv[TOK_CMD + 2]? argv[TOK_CMD + 2] : "", argv[TOK_CMD + 3] ? argv[TOK_CMD + 3] : "");
|
snprintf(message, PIPE_BUF, "-!- %s changed mode/%s -> %s %s", argv[TOK_NICKSRV], argv[TOK_CMD + 1] ? argv[TOK_CMD + 1] : "" , argv[TOK_CMD + 2]? argv[TOK_CMD + 2] : "", argv[TOK_CMD + 3] ? argv[TOK_CMD + 3] : "");
|
||||||
else if(!strncmp("QUIT", argv[TOK_CMD], 5))
|
} else if(!strncmp("QUIT", argv[TOK_CMD], 5)) {
|
||||||
snprintf(message, PIPE_BUF, "-!- %s(%s) has quit \"%s\"", argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
snprintf(message, PIPE_BUF, "-!- %s(%s) has quit \"%s\"", argv[TOK_NICKSRV], argv[TOK_USER], argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
||||||
else if(!strncmp("NICK", argv[TOK_CMD], 5) && argv[TOK_TEXT] && !strcmp(_nick, argv[TOK_TEXT])) {
|
} else if(!strncmp("NICK", argv[TOK_CMD], 5) && argv[TOK_TEXT] && !strcmp(_nick, argv[TOK_TEXT])) {
|
||||||
snprintf(nick, sizeof(nick), "%s", _nick);
|
snprintf(nick, sizeof(nick), "%s", _nick);
|
||||||
snprintf(message, PIPE_BUF, "-!- changed nick to \"%s\"", nick);
|
snprintf(message, PIPE_BUF, "-!- changed nick to \"%s\"", nick);
|
||||||
print_out(NULL, message);
|
print_out(NULL, message);
|
||||||
} else if(!strncmp("NICK", argv[TOK_CMD], 5) && argv[TOK_TEXT])
|
} else if(!strncmp("NICK", argv[TOK_CMD], 5) && argv[TOK_TEXT]) {
|
||||||
snprintf(message, PIPE_BUF, "-!- %s changed nick to %s", argv[TOK_NICKSRV], argv[TOK_TEXT]);
|
snprintf(message, PIPE_BUF, "-!- %s changed nick to %s", argv[TOK_NICKSRV], argv[TOK_TEXT]);
|
||||||
else if(!strncmp("TOPIC", argv[TOK_CMD], 6))
|
} else if(!strncmp("TOPIC", argv[TOK_CMD], 6)) {
|
||||||
snprintf(message, PIPE_BUF, "-!- %s changed topic to \"%s\"", argv[TOK_NICKSRV], argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
snprintf(message, PIPE_BUF, "-!- %s changed topic to \"%s\"", argv[TOK_NICKSRV], argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
||||||
else if(!strncmp("KICK", argv[TOK_CMD], 5) && argv[TOK_ARG])
|
} else if(!strncmp("KICK", argv[TOK_CMD], 5) && argv[TOK_ARG]) {
|
||||||
snprintf(message, PIPE_BUF, "-!- %s kicked %s (\"%s\")", argv[TOK_NICKSRV], argv[TOK_ARG], argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
snprintf(message, PIPE_BUF, "-!- %s kicked %s (\"%s\")", argv[TOK_NICKSRV], argv[TOK_ARG], argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
||||||
else if(!strncmp("NOTICE", argv[TOK_CMD], 7))
|
} else if(!strncmp("NOTICE", argv[TOK_CMD], 7)) {
|
||||||
snprintf(message, PIPE_BUF, "-!- \"%s\")", argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
snprintf(message, PIPE_BUF, "[%s] %s", argv[TOK_NICKSRV], argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
||||||
else if(!strncmp("PRIVMSG", argv[TOK_CMD], 8))
|
} else if(!strncmp("PRIVMSG", argv[TOK_CMD], 8)) {
|
||||||
snprintf(message, PIPE_BUF, "<%s> %s", argv[TOK_NICKSRV], argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
snprintf(message, PIPE_BUF, "<%s> %s", argv[TOK_NICKSRV], argv[TOK_TEXT] ? argv[TOK_TEXT] : "");
|
||||||
else
|
} else {
|
||||||
return; /* can't read this message */
|
return; /* can't read this message */
|
||||||
|
}
|
||||||
|
|
||||||
if(!argv[TOK_CHAN] || !strncmp(argv[TOK_CHAN], nick, strlen(nick)))
|
if(!argv[TOK_CHAN] || !strncmp(argv[TOK_CHAN], nick, strlen(nick))) {
|
||||||
print_out(argv[TOK_NICKSRV], message);
|
print_out(argv[TOK_NICKSRV], message);
|
||||||
else
|
} else {
|
||||||
print_out(argv[TOK_CHAN], message);
|
print_out(argv[TOK_CHAN], message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_line(int fd, size_t res_len, char *buf) {
|
static int read_line(int fd, size_t res_len, char *buf, int from_server) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
char c = 0;
|
char c = 0;
|
||||||
do {
|
do {
|
||||||
if(read(fd, &c, sizeof(char)) != sizeof(char))
|
if(READ(fd, &c, sizeof(char)) != sizeof(char)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
buf[i++] = c;
|
buf[i++] = c;
|
||||||
}
|
} while (c != '\n' && i < res_len);
|
||||||
while(c != '\n' && i < res_len);
|
|
||||||
buf[i - 1] = 0; /* eliminates '\n' */
|
buf[i - 1] = 0; /* eliminates '\n' */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_channels_input(Channel *c) {
|
static void handle_channels_input(Channel *c) {
|
||||||
static char buf[PIPE_BUF];
|
static char buf[PIPE_BUF];
|
||||||
if(read_line(c->fd, PIPE_BUF, buf) == -1) {
|
if(read_line(c->fd, PIPE_BUF, buf, 0) == -1) {
|
||||||
close(c->fd);
|
close(c->fd);
|
||||||
int fd = open_channel(c->name);
|
int fd = open_channel(c->name);
|
||||||
if(fd != -1)
|
if(fd != -1)
|
||||||
|
@ -433,7 +465,7 @@ static void handle_channels_input(Channel *c) {
|
||||||
|
|
||||||
static void handle_server_output() {
|
static void handle_server_output() {
|
||||||
static char buf[PIPE_BUF];
|
static char buf[PIPE_BUF];
|
||||||
if(read_line(irc, PIPE_BUF, buf) == -1) {
|
if(read_line(irc->irc, PIPE_BUF, buf, 1) == -1) {
|
||||||
perror("ii: remote host closed connection");
|
perror("ii: remote host closed connection");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -450,8 +482,8 @@ static void run() {
|
||||||
snprintf(ping_msg, sizeof(ping_msg), "PING %s\r\n", host);
|
snprintf(ping_msg, sizeof(ping_msg), "PING %s\r\n", host);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
FD_ZERO(&rd);
|
FD_ZERO(&rd);
|
||||||
maxfd = irc;
|
maxfd = irc->irc;
|
||||||
FD_SET(irc, &rd);
|
FD_SET(irc->irc, &rd);
|
||||||
for(c = channels; c; c = c->next) {
|
for(c = channels; c; c = c->next) {
|
||||||
if(maxfd < c->fd)
|
if(maxfd < c->fd)
|
||||||
maxfd = c->fd;
|
maxfd = c->fd;
|
||||||
|
@ -471,10 +503,10 @@ static void run() {
|
||||||
print_out(NULL, "-!- ii shutting down: ping timeout");
|
print_out(NULL, "-!- ii shutting down: ping timeout");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
write(irc, ping_msg, strlen(ping_msg));
|
WRITE(irc, ping_msg, strlen(ping_msg));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(FD_ISSET(irc, &rd)) {
|
if(FD_ISSET(irc->irc, &rd)) {
|
||||||
handle_server_output();
|
handle_server_output();
|
||||||
last_response = time(NULL);
|
last_response = time(NULL);
|
||||||
}
|
}
|
||||||
|
@ -508,10 +540,13 @@ int main(int argc, char *argv[]) {
|
||||||
case 'p': port = strtol(argv[++i], NULL, 10); break;
|
case 'p': port = strtol(argv[++i], NULL, 10); break;
|
||||||
case 'n': snprintf(nick,sizeof(nick),"%s", argv[++i]); break;
|
case 'n': snprintf(nick,sizeof(nick),"%s", argv[++i]); break;
|
||||||
case 'k': key = getenv(argv[++i]); break;
|
case 'k': key = getenv(argv[++i]); break;
|
||||||
|
case 'e': use_ssl = 1; ++i; break;
|
||||||
case 'f': fullname = argv[++i]; break;
|
case 'f': fullname = argv[++i]; break;
|
||||||
default: usage(); break;
|
default: usage(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(use_ssl)
|
||||||
|
port = port == SERVER_PORT ? SSL_SERVER_PORT : port;
|
||||||
irc = tcpopen(port);
|
irc = tcpopen(port);
|
||||||
if(!snprintf(path, sizeof(path), "%s/%s", prefix, host)) {
|
if(!snprintf(path, sizeof(path), "%s/%s", prefix, host)) {
|
||||||
fputs("ii: path to irc directory too long\n", stderr);
|
fputs("ii: path to irc directory too long\n", stderr);
|
||||||
|
|
30
launch
30
launch
|
@ -1,6 +1,26 @@
|
||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
nick="happybot"
|
initn="1"
|
||||||
if [ -e '/home/zgrep/offtopiabday/hateweekfile' ]; then
|
maxn="3600"
|
||||||
nick="hatebot";
|
|
||||||
fi;
|
olddate="$(date +%s)"
|
||||||
ii/ii -i ~/offtopiabday -s irc.freenode.net -p 6667 -n "$nick" -f 'Happy birthday! By which I mean existential crisis.'
|
n="$initn"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
nick="happybot"
|
||||||
|
if [ -e '/home/zgrep/offtopiabday/hateweekfile' ]; then
|
||||||
|
nick="hatebot";
|
||||||
|
fi;
|
||||||
|
ii/ii -i ~/offtopiabday -e ssl -s irc.libera.chat -p 6697 -n "$nick" -f 'Happy birthday! By which I mean existential crisis.'
|
||||||
|
|
||||||
|
echo "[$(date)] Oh no, ii died."
|
||||||
|
if [ "$(date +%s)" -lt "$(($olddate + $n + 60))" ]; then
|
||||||
|
n="$((n * 7 / 2))"
|
||||||
|
if [ "$n" -gt "$maxn" ]; then
|
||||||
|
n="$maxn"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
n="$initn"
|
||||||
|
fi
|
||||||
|
olddate="$(date +%s)"
|
||||||
|
sleep "$n"
|
||||||
|
done
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
initn="1"
|
||||||
|
maxn="3600"
|
||||||
|
|
||||||
|
olddate="$(date +%s)"
|
||||||
|
n="$initn"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
ii/ii -i ~/offtopiabday -s irc.sortix.org -e ssl -p 6697 -n "happybot" -f 'Happy birthday! By which I mean existential crisis.'
|
||||||
|
echo "[$(date)] Oh no, ii died."
|
||||||
|
if [ "$(date +%s)" -lt "$(($olddate + $n + 60))" ]; then
|
||||||
|
n="$((n * 7 / 2))"
|
||||||
|
if [ "$n" -gt "$maxn" ]; then
|
||||||
|
n="$maxn"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
n="$initn"
|
||||||
|
fi
|
||||||
|
olddate="$(date +%s)"
|
||||||
|
sleep "$n"
|
||||||
|
done
|
Loading…
Reference in New Issue