$ git clone https://tcclient.ion.nu/tc_client.git
commit 3b7097016d8ebf06f896852d071e8306b127bbae
Author: Alicia <...>
Date: Tue Apr 7 06:49:01 2015 +0200
Version 0.17
diff --git a/ChangeLog b/ChangeLog
index dd44c65..81e809c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+0.17:
+irchack: translate tc_client's "No such nick" to IRC's 401 (No such nick/channel)
+modbot: mark manually started videos as playing.
+modbot: fixed a memory error in list_del()
+Added a configure script to better handle platform differences (primarily that some systems need to link to libiconv, for others it is provided by libc)
+crossbuild.sh: build libiconv if necessary.
+modbot: added more responses to !approve to make it less confusing.
+modbot: pass -- to youtube-dl before the ID to avoid issues when IDs start with -
0.16:
Get and print the channel topic (contributed by Jade)
irchack: fork and keep accepting connections.
diff --git a/Makefile b/Makefile
index 1a130b8..2e357fe 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,9 @@
-VERSION=0.16
+VERSION=0.17
CFLAGS=-g3 -Wall $(shell curl-config --cflags)
LIBS=-g3 $(shell curl-config --libs)
+ifneq ($(wildcard config.mk),)
+ include config.mk
+endif
tc_client: client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o colors.o endian.o
$(CC) $(LDFLAGS) $^ $(LIBS) -o $@
@@ -11,4 +14,4 @@ clean:
rm -f client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o colors.o endian.o tc_client irchack modbot
tarball:
- tar -cJf tc_client-$(VERSION).tar.xz --transform='s|^|tc_client-$(VERSION)/|' Makefile client.c amfparser.c rtmp.c numlist.c amfwriter.c idlist.c colors.c endian.c amfparser.h rtmp.h numlist.h amfwriter.h idlist.h colors.h endian.h LICENSE README ChangeLog crossbuild.sh irchack.c modbot.c
+ tar -cJf tc_client-$(VERSION).tar.xz --transform='s|^|tc_client-$(VERSION)/|' Makefile client.c amfparser.c rtmp.c numlist.c amfwriter.c idlist.c colors.c endian.c amfparser.h rtmp.h numlist.h amfwriter.h idlist.h colors.h endian.h LICENSE README ChangeLog crossbuild.sh irchack.c modbot.c configure
diff --git a/client.c b/client.c
index bd724fb..a8a25a5 100644
--- a/client.c
+++ b/client.c
@@ -339,8 +339,15 @@ int main(int argc, char** argv)
{
pfd[0].revents=0;
unsigned char buf[2048];
- unsigned int len=read(0, buf, 2047);
- if(len<1){break;}
+ unsigned int len=0;
+ int r;
+ while(len<2047)
+ {
+ if((r=read(0, &buf[len], 1))!=1 || buf[len]=='\r' || buf[len]=='\n'){break;}
+ ++len;
+ }
+ if(r<1){break;}
+ if(len<1){continue;}
while(len>0 && (buf[len-1]=='\n'||buf[len-1]=='\r')){--len;}
if(!len){continue;} // Don't send empty lines
buf[len]=0;
@@ -404,7 +411,8 @@ int main(int argc, char** argv)
privfield=idlist_get((char*)&buf[5]);
if(privfield<0)
{
- printf("No such nick\n");
+ buf[5+privlen]=0;
+ printf("No such nick: %s\n", &buf[5]);
fflush(stdout);
continue;
}
diff --git a/configure b/configure
index 6d37dbf..d45512a 100755
--- a/configure
+++ b/configure
@@ -38,144 +38,4 @@ else
fi
rm -f iconvtest iconvtest.c
-printf 'Checking for gtk+-3.0... '
-libs="`pkg-config --libs gtk+-3.0 2> /dev/null`"
-if [ "x$libs" != "x" ]; then
- echo "GTK_LIBS=${libs}" >> config.mk
- echo "GTK_CFLAGS=`pkg-config --cflags gtk+-3.0`" >> config.mk
- echo yes
-else
- echo no
- printf 'Checking for gtk+-2.0... '
- libs="`pkg-config --libs gtk+-2.0 2> /dev/null`"
- if [ "x$libs" != "x" ]; then
- echo "GTK_LIBS=${libs}" >> config.mk
- echo "GTK_CFLAGS=`pkg-config --cflags gtk+-2.0`" >> config.mk
- echo yes
- else
- echo no
- fi
-fi
-
-printf 'Checking for libavcodec... '
-libs="`pkg-config --libs libavcodec 2> /dev/null`"
-if [ "x$libs" != "x" ]; then
- echo "AVCODEC_LIBS=${libs}" >> config.mk
- echo "AVCODEC_CFLAGS=`pkg-config --cflags libavcodec`" >> config.mk
- echo yes
-else
- echo no
-fi
-
-printf 'Checking for libswscale... '
-libs="`pkg-config --libs libswscale 2> /dev/null`"
-if [ "x$libs" != "x" ]; then
- echo "SWSCALE_LIBS=${libs}" >> config.mk
- echo "SWSCALE_CFLAGS=`pkg-config --cflags libswscale`" >> config.mk
- echo yes
-else
- echo no
-fi
-
-printf 'Checking for libavutil... '
-libs="`pkg-config --libs libavutil 2> /dev/null`"
-if [ "x$libs" != "x" ]; then
- echo "AVUTIL_LIBS=${libs}" >> config.mk
- echo "AVUTIL_CFLAGS=`pkg-config --cflags libavutil`" >> config.mk
- echo yes
-else
- echo no
-fi
-
-# TODO: Figure out how to mix sound sources so that this doesn't sound horrible with more than one person on mic, having it disabled by default until then
-if [ "x${ENABLE_MIC}" != "x" ]; then
-printf 'Checking for libavresample... '
-libs="`pkg-config --libs libavresample 2> /dev/null`"
-if [ "x$libs" != "x" ]; then
- echo "AVRESAMPLE_LIBS=${libs}" >> config.mk
- echo "AVRESAMPLE_CFLAGS=`pkg-config --cflags libavresample`" >> config.mk
- echo yes
-else
- echo no
- printf 'Checking for libswresample... '
- libs="`pkg-config --libs libswresample 2> /dev/null`"
- if [ "x$libs" != "x" ]; then
- echo "SWRESAMPLE_LIBS=${libs}" >> config.mk
- echo "SWRESAMPLE_CFLAGS=`pkg-config --cflags libswresample`" >> config.mk
- echo yes
- else
- echo no
- fi
-fi
-
-printf 'Checking for libao... '
-libs="`pkg-config --libs ao 2> /dev/null`"
-if [ "x$libs" != "x" ]; then
- echo "AO_LIBS=${libs}" >> config.mk
- echo "AO_CFLAGS=`pkg-config --cflags ao`" >> config.mk
- echo yes
-else
- echo no
-fi
-fi
-
-printf 'Checking for ncurses... '
-libs="`ncursesw5-config --libs 2> /dev/null || ncurses5-config --libs 2> /dev/null`"
-if [ "x$libs" != "x" ]; then
- echo "CURSES_LIBS=${libs}" >> config.mk
- echo "CURSES_CFLAGS=`ncursesw5-config --cflags 2> /dev/null || ncurses5-config --cflags 2> /dev/null`" >> config.mk
- echo yes
-else
- echo no
-fi
-
-printf 'Checking for readline... '
-echo '#include <stdio.h>' > readlinetest.c
-echo '#include <readline/readline.h>' >> readlinetest.c
-echo 'int main(){rl_initialize();return 0;}' >> readlinetest.c
-if "$CC" readlinetest.c -lreadline ${libs} -o readlinetest > /dev/null 2> /dev/null; then
- echo "READLINE_LIBS=-lreadline" >> config.mk
- echo yes
-else
- echo no
-fi
-rm -f readlinetest.c readlinetest
-
-printf 'Checking for libv4l2... '
-libs="`pkg-config --libs libv4l2 2> /dev/null`"
-if [ "x$libs" != "x" ]; then
- echo "LIBV4L2_LIBS=${libs}" >> config.mk
- echo "LIBV4L2_CFLAGS=`pkg-config --cflags libv4l2`" >> config.mk
- echo yes
-else
- echo no
-fi
-
-# TODO: handle crosscompiling better
-printf 'Checking if endianness macros work... '
-echo '#include <stdio.h>' > endiantest.c
-echo 'int main(){' >> endiantest.c
-echo '#if defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__)' >> endiantest.c
-echo ' if(__ORDER_LITTLE_ENDIAN__==__ORDER_BIG_ENDIAN__){return 1;}' >> endiantest.c
-echo ' if(__BYTE_ORDER__!=__ORDER_LITTLE_ENDIAN__ && __BYTE_ORDER__!=__ORDER_BIG_ENDIAN__){return 1;}' >> endiantest.c
-echo ' return 0;' >> endiantest.c
-echo '#else' >> endiantest.c
-echo ' return 1;' >> endiantest.c
-echo '#endif' >> endiantest.c
-echo '}' >> endiantest.c
-"$CC" endiantest.c -o endiantest > /dev/null 2> /dev/null
-if ./endiantest 2> /dev/null; then
- echo yes
-else
- echo no
- printf 'Checking endianness and writing our own macros... '
- echo '#include <stdio.h>' > endiantest.c
- echo 'int main(){int num=1;char* x=(char*)#if(x[0]){printf("CFLAGS+=-D__ORDER_LITTLE_ENDIAN__=1 -D__ORDER_BIG_ENDIAN__=2 -D__BYTE_ORDER__=1");}else{printf("CFLAGS+=-D__ORDER_LITTLE_ENDIAN__=1 -D__ORDER_BIG_ENDIAN__=2 -D__BYTE_ORDER__=2");}return 0;}' >> endiantest.c
- "$CC" endiantest.c -o endiantest > /dev/null 2> /dev/null
- ./endiantest >> config.mk
- echo >> config.mk
- echo done
-fi
-rm -f endiantest.c endiantest
-
echo Done
diff --git a/crossbuild.sh b/crossbuild.sh
index 13c3d48..481b401 100755
--- a/crossbuild.sh
+++ b/crossbuild.sh
@@ -5,6 +5,7 @@ if [ "$host" = "" ]; then
if [ "$host" = "" ]; then host='i386-pc-linux-gnu'; fi
echo "No target host specified (argv[1]), defaulting to ${host}"
fi
+./configure --host="$host"
here="`pwd`"
if [ ! -e curlprefix ]; then
wget -c http://curl.haxx.se/download/curl-7.40.0.tar.bz2
@@ -17,14 +18,19 @@ if [ ! -e curlprefix ]; then
make install
cd "$here"
fi
-export PATH="${here}/curlprefix/bin:${PATH}"
-# Select a crosscompiler (if we can find one)
-if which "${host}-gcc" > /dev/null 2> /dev/null && [ "`which "${host}-gcc" 2> /dev/null`" != "" ]; then
- export CC="${host}-gcc"
-elif which "${host}-clang" > /dev/null 2> /dev/null && [ "`which "${host}-clang" 2> /dev/null`" != "" ]; then
- export CC="${host}-clang"
-elif which "${host}-cc" > /dev/null 2> /dev/null && [ "`which "${host}-cc" 2> /dev/null`" != "" ]; then
- export CC="${host}-cc"
+if grep -q 'LIBS+=-liconv' config.mk && [ ! -e iconvprefix ]; then
+ wget -c http://ftp.gnu.org/gnu/libiconv/libiconv-1.14.tar.gz
+ tar -xzf libiconv-1.14.tar.gz
+ cd libiconv-1.14
+ mkdir -p build
+ cd build
+ ../configure --prefix="${here}/iconvprefix" --host="`echo "$host" | sed -e 's/android/gnu/'`" --enable-static --disable-shared CC="${host}-gcc" # libiconv does not handle android well, so we pretend it's GNU and specify the compiler
+ make
+ make install
+ cd "$here"
fi
+export PATH="${here}/curlprefix/bin:${PATH}"
+echo "CFLAGS+=-I${here}/iconvprefix/include" >> config.mk
+echo "LDFLAGS+=-L${here}/iconvprefix/lib" >> config.mk
make
make utils
diff --git a/irchack.c b/irchack.c
index 26a67b9..dca0f14 100644
--- a/irchack.c
+++ b/irchack.c
@@ -277,6 +277,11 @@ printf("Got from tc_client: '%s'\n", buf);
dprintf(sock, ":%s!user@host NICK :guest-%s\n", nick, &buf[10]);
continue;
}
+ if(!strncmp(buf, "No such nick: ", 14))
+ {
+ dprintf(sock, ":irchack 401 %s %s :No such nick/channel\n", nick, &buf[14]);
+ continue;
+ }
char* space=strchr(buf, ' ');
if(space && !strcmp(space, " is a moderator."))
{
diff --git a/modbot.c b/modbot.c
index d375590..36d5ddf 100644
--- a/modbot.c
+++ b/modbot.c
@@ -47,7 +47,7 @@ void list_del(struct list* list, const char* item)
{
free(list->items[i]);
--list->itemcount;
- memmove(&list->items[i], &list->items[i+1], sizeof(char*)*list->itemcount);
+ memmove(&list->items[i], &list->items[i+1], sizeof(char*)*(list->itemcount-i));
}
}
}
@@ -165,9 +165,8 @@ unsigned int getduration(const char* vid)
{
close(out[0]);
dup2(out[1], 1);
- close(2); // Ignore youtube-dl errors/warnings
write(1, ":", 1);
- execlp("youtube-dl", "youtube-dl", "--get-duration", vid, (char*)0);
+ execlp("youtube-dl", "youtube-dl", "--get-duration", "--", vid, (char*)0);
perror("execlp(youtube-dl)");
_exit(1);
}
@@ -175,7 +174,7 @@ unsigned int getduration(const char* vid)
close(out[1]);
char timebuf[128];
int len=read(out[0], timebuf, 127);
- if(len<1){return 60;} // If using youtube-dl fails, assume all videos are 1 minute long
+ if(len<2){printf("Failed to get video duration using youtube-dl, assuming 60s\n"); return 60;} // If using youtube-dl fails, assume all videos are 1 minute long
timebuf[len]=0;
close(out[0]);
// youtube-dl prints it out in hh:mm:ss format, convert it to plain seconds
@@ -317,6 +316,7 @@ int main(int argc, char** argv)
if((pos=list_getpos(&queue, vid))>-1)
{
say(pm, "That video is already in queue (number %i)\n", pos);
+ continue;
}
if(list_contains(&mods, nick))
{
@@ -399,24 +399,28 @@ int main(int argc, char** argv)
{
if(playing)
{
+ if(list_contains(&goodvids, playing) && !list_contains(&badvids, playing)){say(pm, "'%s' is already approved, use !approve <ID> to approve another video\n", playing); continue;}
list_add(&goodvids, playing);
list_del(&badvids, playing);
list_save(&goodvids, "goodvids.txt");
list_save(&badvids, "badvids.txt");
}else if(queue.itemcount>0){
+ if(list_contains(&goodvids, queue.items[0]) && !list_contains(&badvids, queue.items[0])){say(pm, "'%s' is already approved, use !approve <ID> to approve another video\n", queue.items[0]); continue;}
list_add(&goodvids, queue.items[0]);
list_del(&badvids, queue.items[0]);
list_save(&goodvids, "goodvids.txt");
list_save(&badvids, "badvids.txt");
playnext(0);
- }else{write(tc_client, "Approve what? please specify a video\n", 37);}
+ }else{say(pm, "Approve what? please specify a video\n");}
}
else if(!strncmp(msg, "!approve ", 9))
{
char* vid=getyoutube(&msg[9]);
if(!vid[0]){vid=playing; if(!vid){continue;}}
list_add(&goodvids, vid);
+ list_del(&badvids, vid);
list_save(&goodvids, "goodvids.txt");
+ list_save(&badvids, "badvids.txt");
if(!playing && queue.itemcount>0 && !strcmp(vid, queue.items[0])){playnext(0);} // Next in queue just got approved, so play it
}
else if(!strcmp(msg, "!badvid") || !strncmp(msg, "!badvid ", 8))
@@ -439,6 +443,8 @@ int main(int argc, char** argv)
list_del(&queue, vid);
list_add(&goodvids, vid);
list_save(&goodvids, "goodvids.txt");
+ free(playing);
+ playing=strdup(vid);
alarm(getduration(vid));
}
else if(!strcmp(msg, "/mbc youTube")){playnext(0);} // TODO: handle /mbsk (seek) too?