Rewrite to static site
With a complete reorganisation of the directory structure and most of the content converted to pandoc-flavoured markdown. Some TODO's left before this can go live: - Main page - Atom feeds - Bug tracker
This commit is contained in:
parent
5c85a7d32f
commit
6242b2ee9c
291 changed files with 4346 additions and 6141 deletions
|
|
@ -1,326 +0,0 @@
|
|||
/* vinfo - A small commandline visual novel info display thingy
|
||||
|
||||
Last modified: 2009-11-16
|
||||
|
||||
This is just a simple example program using the public VNDB API,
|
||||
this program is neither useful nor actively maintained. Feel free
|
||||
to extend it to suit your needs.
|
||||
|
||||
Requirements:
|
||||
- A POSIX-compatible system
|
||||
- GNU getopt()
|
||||
- json-c (http://oss.metaparadigm.com/json-c/)
|
||||
|
||||
Compile:
|
||||
gcc vinfo.c `pkg-config --cflags --libs json` -o vinfo
|
||||
|
||||
Usage:
|
||||
vinfo -u <username> -p <password> <vnid>
|
||||
|
||||
TODO:
|
||||
- Giving password on the commandline is a really bad idea,
|
||||
need to fix an alternative method.
|
||||
- Display more info on VN info output (links/description)
|
||||
- Make host/port configurable
|
||||
- VN searching
|
||||
- More error checking on the received JSON data
|
||||
- Producers/releases?
|
||||
|
||||
|
||||
Copyright (c) 2009 Yoran Heling
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#define PROGRAM "vinfo"
|
||||
#define VERSION 0.1
|
||||
|
||||
#define SERVER "81.204.242.156" /* beta, you may want to change this to whatever api.vndb.org resolves to */
|
||||
#define PORT 19534
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <json.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
#define WS "\011\012\015\040"
|
||||
#define DIE(str) { perror(str); exit(1); }
|
||||
|
||||
|
||||
char *user, *pass;
|
||||
int sock;
|
||||
|
||||
|
||||
/* sends command and returns reply */
|
||||
char *docmd(char *cmd) {
|
||||
char *res, *fmt;
|
||||
unsigned int start, end, read = 0, size = 1024;
|
||||
int r;
|
||||
json_object *json;
|
||||
|
||||
if(send(sock, cmd, strlen(cmd), 0) < 0)
|
||||
DIE("send");
|
||||
|
||||
/* receive data */
|
||||
res = malloc(size);
|
||||
while(memchr(res, 4, read) == NULL) {
|
||||
if(read > 102400) {
|
||||
printf("ERROR: Too long reply.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(size-read < 500) {
|
||||
size *= 2;
|
||||
res = realloc(res, size);
|
||||
}
|
||||
if((r = recv(sock, res+read, size-read, 0)) < 0)
|
||||
DIE("recv");
|
||||
read += r;
|
||||
}
|
||||
|
||||
/* remove leading and trailing whitespace */
|
||||
end = ((char *)memchr(res, 4, read))-res;
|
||||
res[end--] = 0;
|
||||
while(strspn(res+end, WS))
|
||||
end--;
|
||||
start = strspn(res, WS);
|
||||
|
||||
if(start == 0)
|
||||
fmt = res;
|
||||
else {
|
||||
fmt = malloc(end-start+1);
|
||||
strcpy(fmt, res+start);
|
||||
free(res);
|
||||
}
|
||||
|
||||
/* check for error response */
|
||||
if(!strncmp(fmt, "error", strlen("error"))) {
|
||||
res = fmt+strlen("error");
|
||||
res += strspn(res, WS);
|
||||
json = json_tokener_parse(res);
|
||||
if(json != NULL && json_object_is_type(json, json_type_object)) {
|
||||
printf("ERROR(%s): %s\n",
|
||||
json_object_get_string(json_object_object_get(json, "id")),
|
||||
json_object_get_string(json_object_object_get(json, "msg")));
|
||||
json_object_put(json);
|
||||
} else {
|
||||
printf("Received something strange...\n> %s\n", fmt);
|
||||
}
|
||||
free(fmt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
|
||||
/* opens the TCP socket and logs in */
|
||||
void login() {
|
||||
struct sockaddr_in addr;
|
||||
json_object *arg;
|
||||
const char *json;
|
||||
char *cmd, *res;
|
||||
|
||||
/* connect */
|
||||
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
DIE("socket");
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(PORT);
|
||||
inet_aton(SERVER, &addr.sin_addr);
|
||||
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
DIE("connect");
|
||||
|
||||
/* construct login command */
|
||||
arg = json_object_new_object();
|
||||
json_object_object_add(arg, "protocol", json_object_new_int(1));
|
||||
json_object_object_add(arg, "client", json_object_new_string(PROGRAM));
|
||||
json_object_object_add(arg, "clientver", json_object_new_double(VERSION));
|
||||
json_object_object_add(arg, "username", json_object_new_string(user));
|
||||
json_object_object_add(arg, "password", json_object_new_string(pass));
|
||||
json = json_object_to_json_string(arg);
|
||||
cmd = malloc(strlen(json) + 10);
|
||||
sprintf(cmd, "login %s\04", json);
|
||||
json_object_put(arg);
|
||||
|
||||
/* login */
|
||||
res = docmd(cmd);
|
||||
free(cmd);
|
||||
if(strncmp("ok", res, 2)) {
|
||||
printf("ERROR: Received something strange.\n> %s\n", res);
|
||||
free(res);
|
||||
exit(1);
|
||||
}
|
||||
free(res);
|
||||
}
|
||||
|
||||
|
||||
void vninfo(int vid) {
|
||||
char cmd[50], *res, *tmp, *tmp2;
|
||||
const char *str;
|
||||
int i, n;
|
||||
json_object *json, *vn, *itm;
|
||||
|
||||
login();
|
||||
sprintf(cmd, "get vn basic,details (id=%d)\04", vid);
|
||||
res = docmd(cmd);
|
||||
if(strncmp("results", res, 7)) {
|
||||
printf("ERROR: Received something strange.\n> %s\n", res);
|
||||
exit(1);
|
||||
}
|
||||
tmp = res+7;
|
||||
tmp += strspn(tmp, WS);
|
||||
if((json = json_tokener_parse(tmp)) == NULL || !json_object_is_type(json, json_type_object)) {
|
||||
printf("ERROR: Received something strange.\n> %s\n", res);
|
||||
exit(1);
|
||||
}
|
||||
/*printf("\n%s\n\n", tmp);*/
|
||||
|
||||
/* note: may want to put in some checks on whether the data indeed confirms to what we expect */
|
||||
if(json_object_get_int(json_object_object_get(json, "num")) < 1) {
|
||||
printf("No VN with that ID.\n");
|
||||
exit(1);
|
||||
}
|
||||
vn = json_object_array_get_idx(json_object_object_get(json, "items"), 0);
|
||||
|
||||
/* header + titles */
|
||||
printf("------------------------------ v%-5d ----------------------------\n", vid);
|
||||
printf(" Title : %s\n", json_object_get_string(json_object_object_get(vn, "title")));
|
||||
if((str = json_object_get_string(json_object_object_get(vn, "original"))) != NULL)
|
||||
printf(" Official : %s\n", str);
|
||||
|
||||
/* aliases (string processing in C, meh) */
|
||||
str = json_object_get_string(json_object_object_get(vn, "aliases"));
|
||||
if(str != NULL) {
|
||||
printf(" Aliases : ");
|
||||
tmp = strdup(str);
|
||||
tmp2 = tmp;
|
||||
i = -1;
|
||||
do {
|
||||
i++;
|
||||
if(!tmp[i] || tmp[i] == ',' || tmp[i] == '\n') {
|
||||
if(tmp2 != tmp)
|
||||
printf(" ");
|
||||
tmp2 += strspn(tmp2, ", \n");
|
||||
n = tmp[i];
|
||||
tmp[i] = 0;
|
||||
printf("%s\n", tmp2);
|
||||
if(n) {
|
||||
i++;
|
||||
tmp2 = tmp+i;
|
||||
}
|
||||
}
|
||||
} while(tmp[i]);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
/* release date */
|
||||
str = json_object_get_string(json_object_object_get(vn, "released"));
|
||||
printf(" First release : %-10s\n", str != NULL ? str : "-");
|
||||
|
||||
/* length */
|
||||
itm = json_object_object_get(vn, "length");
|
||||
if(json_object_is_type(itm, json_type_int)) {
|
||||
printf(" Length : ");
|
||||
switch(json_object_get_int(itm)) {
|
||||
case 1: printf("Very short\n"); break;
|
||||
case 2: printf("Short\n"); break;
|
||||
case 3: printf("Medium\n"); break;
|
||||
case 4: printf("Long\n"); break;
|
||||
case 5: printf("Very long\n"); break;
|
||||
}
|
||||
}
|
||||
|
||||
/* languages */
|
||||
itm = json_object_object_get(vn, "languages");
|
||||
if(json_object_array_length(itm) > 0) {
|
||||
printf(" Available in : ");
|
||||
for(i=0; i<json_object_array_length(itm); i++) {
|
||||
if(i)
|
||||
printf(", ");
|
||||
printf("%s", json_object_get_string(json_object_array_get_idx(itm, i)));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* platforms */
|
||||
itm = json_object_object_get(vn, "platforms");
|
||||
if(json_object_array_length(itm) > 0) {
|
||||
printf(" ...for : ");
|
||||
for(i=0; i<json_object_array_length(itm); i++) {
|
||||
if(i)
|
||||
printf(", ");
|
||||
printf("%s", json_object_get_string(json_object_array_get_idx(itm, i)));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
json_object_put(json);
|
||||
free(res);
|
||||
}
|
||||
|
||||
|
||||
void usage() {
|
||||
printf("%s -u username -p password query\n", PROGRAM);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *query;
|
||||
int r;
|
||||
|
||||
user = pass = query = NULL;
|
||||
|
||||
while((r = getopt(argc, argv, "-u:p:")) >= 0) {
|
||||
switch(r) {
|
||||
case 'u':
|
||||
user = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
pass = optarg;
|
||||
break;
|
||||
case '\1':
|
||||
query = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if(!pass || !user || !query)
|
||||
usage();
|
||||
|
||||
if(sscanf(query, "%d", &r) == 1 && r > 0) {
|
||||
vninfo(r);
|
||||
} else {
|
||||
printf("Sorry, searching is not supported yet\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue