2008/02/14


なんだかtwitterではハート祭りが繰り広げられている様で...
twitter-heart
どうやら「<3」でハートマークが付くようです。
今日はバレンタインデーって事で、こんなもん作ってみました。
WWW::Mechanize::AutoPagerでfriends全員をハッシュ一覧化し、Net::Twitterで全員にこのハートを送るperlスクリプトを作ってみました。
宜しければどうぞ!
って私はやりませんが...
※ちなみに本気でやるなら、ちゃんとsleep入れて下さいね。

#!/usr/bin/perl

use warnings;
use strict;
use WWW::Mechanize;
use WWW::Mechanize::AutoPager;
use Web::Scraper;
use Net::Twitter;

my $username = 'username';
my $password = 'password';

my $twitter_friends = scraper {
    process 'tr.vcard',
        'friends[]' => scraper {
            process 'td strong a', name => 'TEXT';
        };
    result 'friends';
};

my $u = 'http://twitter.com/friends/';

my $mech = WWW::Mechanize->new(timeout => 10);
$mech->add_header('Accept-Encoding', 'identity');
$mech->get('http://twitter.com/login');
$mech->submit_form(
    form_number => 2,
    fields    => {
        username_or_email  => $username,
        password           => $password,
    },
    button    => 'commit',
);

$mech->autopager->load_siteinfo();
my $friends;
while($u) {
    my $res = $twitter_friends->scrape( $mech->get($u)->content );
    eval { push @$friends, @{$res}; };
    last if ( $@ or !defined($mech->next_link) );
    $u = $mech->next_link;
}

my $twit = Net::Twitter->new( username => $username, password => $password );
foreach my $friend (@$friends) {
    my $name = $friend->{name};
    $result = $twit->update("\@$name <3");
}
って俺、男だ。
Posted at by



2008/02/13


ShareOnTumblr
「CShellExt::QueryContextMenu」でやれば出来なく無いけどコストがデカイし別のシェルエクステンション混ぜると落ちたりするんですよね。
Gyazowin tumblr for Windowsにファイルのアップロード機能を追加して名前をGyamblr for Windowsに変更 « ZeroMemory
Windowsのコンテキストメニューのコピーとかにcopy to tumblrみたいなのを追加できないかなと思ったんだけど、標準のやつはともかくアプリケーションの右クリックはアプリケーション管轄で制御されていてWindowsシロウト同然の自分には外からいじれなそうだったのであきらめました。
本当は「CShellExt::QueryContextMenu」でやるのがいいんだろうけど、今回はコマンドラインユーザでも使える様にコマンド形式で「送る」に登録する方法にした。

続きを読む...

Posted at by



2008/02/08


まぁ、id:tokuhirom氏が作ったwassr-todo.plがあるんですが...
(いいんです。C言語が書きたいんです!)

でっかく記事いっぱいにコードだけ...


ちなみに、json-cというライブラリとcURLを使っています。
昨日のパッチを使えばVC6でもビルド出来ます。
よろしければどうぞ。

最新ソースはCodeReposのコノ辺におきました。

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <curl/curl.h>
#include <json.h>

#define APP_NAME                   "wassr_todo"

#ifdef _WIN32
# ifndef snprintf
#  define snprintf _snprintf
# endif
#endif

#define TODO_MODIFY_URL "http://api.wassr.jp/todo/"
#define TODO_JSON_EXT ".json"

static char* response_cond = NULL;  /* response condition */
static char* response_mime = NULL;  /* response content-type. ex: "text/html" */
static char* response_data = NULL;  /* response data from server. */
static size_t response_size = 0;    /* response size of data */

static void initialize_http_response() {
    response_cond = NULL;
    response_mime = NULL;
    response_data = NULL;
    response_size = 0;
}

static void terminate_http_response() {
    if (response_cond) free(response_cond);
    if (response_mime) free(response_mime);
    if (response_data) free(response_data);
    response_cond = NULL;
    response_mime = NULL;
    response_data = NULL;
    response_size = 0;
}

static size_t handle_returned_data(char* ptr, size_t size, size_t nmemb, void* stream) {
    if (!response_data)
        response_data = (char*)malloc(size*nmemb);
    else
        response_data = (char*)realloc(response_data, response_size+size*nmemb);
    if (response_data) {
        memcpy(response_data+response_size, ptr, size*nmemb);
        response_size += size*nmemb;
    }
    return size*nmemb;
}

static size_t handle_returned_header(void* ptr, size_t size, size_t nmemb, void* stream) {
    char* header = NULL;

    header = (char*)malloc(size*nmemb + 1);
    memcpy(header, ptr, size*nmemb);
    header[size*nmemb] = 0;
    if (strncmp(header, "Content-Type: ", 14) == 0) {
        char* stop = header + 14;
        stop = strpbrk(header + 14, "\r\n;");
        if (stop) *stop = 0;
        if (response_mime) free(response_mime);
        response_mime = strdup(header + 14);
    }
    if (strncmp(header, "Last-Modified: ", 15) == 0) {
        char* stop = strpbrk(header, "\r\n;");
        if (stop) *stop = 0;
        if (response_cond) free(response_cond);
        response_cond = strdup(header);
    }
    if (strncmp(header, "ETag: ", 6) == 0) {
        char* stop = strpbrk(header, "\r\n;");
        if (stop) *stop = 0;
        if (response_cond) free(response_cond);
        response_cond = strdup(header);
    }
    free(header);
    return size*nmemb;
}

char* get_http_data(char* url, char* user, char* pass) {
    CURLcode res;
    CURL* curl;
    char* ret = NULL;
    int status = 0;
    char auth[512];

    initialize_http_response();

    memset(auth, 0, sizeof(auth));
    snprintf(auth, sizeof(auth)-1, "%s:%s", user, pass);

    curl = curl_easy_init();
    if (!curl) return NULL;
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_USERPWD, auth);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handle_returned_data);
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, handle_returned_header);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, APP_NAME);
    res = curl_easy_perform(curl);
    res = res == CURLE_OK ? curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &status) : res;
    curl_easy_cleanup(curl);
    if (res == CURLE_OK && status == 200) {
        ret = (char*)malloc(response_size+1);
        memset(ret, 0, response_size+1);
        memcpy(ret, (char*)response_data, response_size);
    }

    terminate_http_response();

    return ret;
}

char* post_http_data(char* url, char* user, char* pass, char* data) {
    CURLcode res;
    CURL* curl;
    char* ret = NULL;
    int status = 0;
    char auth[512];

    initialize_http_response();

    memset(auth, 0, sizeof(auth));
    snprintf(auth, sizeof(auth)-1, "%s:%s", user, pass);

    curl = curl_easy_init();
    if (!curl) return NULL;
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_USERPWD, auth);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handle_returned_data);
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, handle_returned_header);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, APP_NAME);
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void*)data);
    res = curl_easy_perform(curl);
    res = res == CURLE_OK ? curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &status) : res;
    curl_easy_cleanup(curl);
    if (res == CURLE_OK && status == 200) {
        ret = (char*)malloc(response_size+1);
        memset(ret, 0, response_size+1);
        memcpy(ret, (char*)response_data, response_size);
    }

    terminate_http_response();

    return ret;
}

char* string_to_utf8_alloc(const char* str) {
    if (!str) return NULL;
#ifdef WIN32
    UINT codePage;
    size_t in_len = strlen(str);
    codePage = GetACP();
    size_t wcssize = MultiByteToWideChar(codePage, 0, str, in_len,  NULL, 0);
    wchar_t* pszStrWC = (wchar_t*)malloc(sizeof(wchar_t)*(wcssize + 1));
    wcssize = MultiByteToWideChar(codePage, 0, str, in_len, pszStrWC, wcssize + 1);
    pszStrWC[wcssize] = '\0';

    codePage = CP_UTF8;
    size_t mbssize = WideCharToMultiByte(codePage, 0, pszStrWC, -1, NULL, 0, NULL, NULL);
    char* pszStrMB = (char*)malloc(mbssize + 1);
    mbssize = WideCharToMultiByte(codePage, 0, pszStrWC, -1, pszStrMB, mbssize, NULL, NULL);
    pszStrMB[mbssize] = '\0';

    free(pszStrWC);

    return pszStrMB;
#else
    return strdup(str);
#endif
}

char* utf8_to_string_alloc(const char* str) {
    if (!str) return NULL;
#ifdef WIN32
    UINT codePage = CP_UTF8;
    const char* ptr = str;
    if (str[0] == (char)0xef && str[1] == (char)0xbb && str[2] == (char)0xbf)
        ptr += 3;
    size_t wcssize = MultiByteToWideChar(codePage, 0, ptr, -1,  NULL, 0);
    wchar_t* pszStrWC = (wchar_t*)malloc(sizeof(wchar_t)*(wcssize + 1));
    wcssize = MultiByteToWideChar(codePage, 0, ptr, -1, pszStrWC, wcssize + 1);
    pszStrWC[wcssize] = '\0';

    codePage = GetACP();
    size_t mbssize = WideCharToMultiByte(codePage, 0, pszStrWC,-1, NULL, 0, NULL, NULL);
    char* pszStrMB = (char*)malloc(mbssize + 1);
    mbssize = WideCharToMultiByte(codePage, 0, pszStrWC, -1, pszStrMB, mbssize, NULL, NULL);
    pszStrMB[mbssize] = '\0';

    free(pszStrWC);

    return pszStrMB;
#else
    return strdup(str);
#endif
}

static char* url_encode_alloc(const char* str) {
    static const int force_encode_all = TRUE;
    const char* hex = "0123456789abcdef";

    char* buf = NULL;
    unsigned char* pbuf = NULL;
    int len = 0;

    if (!str) return NULL;
    len = strlen(str)*3;
    buf = (char*)malloc(len+1);
    memset(buf, 0, len+1);
    pbuf = (unsigned char*)buf;
    while(*str) {
        unsigned char c = (unsigned char)*str;
        if (c == ' ')
            *pbuf++ = '+';
        else if (c & 0x80 || force_encode_all) {
            *pbuf++ = '%';
            *pbuf++ = hex[c >> 4];
            *pbuf++ = hex[c & 0x0f];
        } else
            *pbuf++ = c;
        str++;
    }
    return buf;
}

char* add_todo(char* user, char* pass, char* body) {
    int size;
    char* body_utf8;
    char* body_data;
    char* post;
    char* data;

    body_utf8 = string_to_utf8_alloc(body);
    if (!body_utf8) return NULL;
    body_data = url_encode_alloc(body_utf8);
    free(body_utf8);
    size = 5 + strlen(body_data);
    post = (char*)malloc(size + 1);
    memset(post, 0, size + 1);
    strcpy(post, "body=");
    strcat(post, body_data);
    free(body_data);

    data = post_http_data("http://api.wassr.jp/todo/add.json", user, pass, post);
    free(post);
    return data;
}

char* modify_todo(char* user, char* pass, char* command, char* todo_rid) {
    int size;
    char* url;
    char* post;
    char* data;

    size = 9 + strlen(todo_rid);
    post = (char*)malloc(size + 1);
    memset(post, 0, size + 1);
    strcpy(post, "todo_rid=");
    strcat(post, todo_rid);

    size = strlen(TODO_MODIFY_URL) + strlen(command) + strlen(TODO_JSON_EXT);
    url = (char*)malloc(size + 1);
    memset(url, 0, size + 1);
    strcpy(url, TODO_MODIFY_URL);
    strcat(url, command);
    strcat(url, TODO_JSON_EXT);

    data = post_http_data(url, user, pass, post);
    free(post);
    free(url);
    return data;
}

char* list_todo(char* user, char* pass, int done_fg) {
    char* data;

    if (done_fg)
        data = get_http_data("http://api.wassr.jp/todo/list.json?done_fg=1", user, pass);
    else
        data = get_http_data("http://api.wassr.jp/todo/list.json?done_fg=0", user, pass);
    if (!data) {
        perror("Unknown server response(server down or invalid authenticate?)");
        return NULL;
    }
    return data;
}

int main(int argc, char* argv[]) {
    FILE* fp = NULL;
    char* home = NULL;
    char* user = NULL;
    char* pass = NULL;
    char conf[_MAX_PATH];
    char buff[BUFSIZ];
    char* data = NULL;
    struct json_object* obj = NULL;
    struct json_object* res = NULL;
    int i;

    home = getenv("HOME");
    if (!home) home = getenv("USERPROFILE");
    snprintf(conf, sizeof(conf), "%s/.wassr-todo", home);
    fp = fopen(conf, "rt");
    if (!fp) {
        perror("404 ~/.wassr-todo NOT FOUND");
        goto error;
    }
    while(fgets(buff, sizeof(buff), fp)) {
        char *ptr = strpbrk(buff, "\r\n");
        if (*ptr) *ptr = 0;
        if (!strncmp(buff, "username: ", 10))
            user = strdup(buff + 10);
        if (!strncmp(buff, "password: ", 10))
            pass = strdup(buff + 10);
    }
    fclose(fp);

    if (argc == 1)
        data = list_todo(user, pass, FALSE);
    else {
        if (argc == 2 && !strcmp(argv[1], "list"))
            data = list_todo(user, pass, FALSE);
        else
        if (argc == 2 && !strcmp(argv[1], "listdone"))
            data = list_todo(user, pass, TRUE);
        else
        if (argc == 3 && !strcmp(argv[1], "add"))
            data = add_todo(user, pass, argv[2]);
        else
        if (argc == 3 && (
                !strcmp(argv[1], "delete") ||
                !strcmp(argv[1], "start") ||
                !strcmp(argv[1], "stop") ||
                !strcmp(argv[1], "done")))
            data = modify_todo(user, pass, argv[1], argv[2]);
        else {
            puts("usage: wassr_todo [command] [argument]");
            puts("\t* command");
            puts("\t\tlist\t\tlist todo.");
            puts("\t\tlistdone\tlist todo which is done.");
            puts("\t\tadd [body]\tpost new todo to wassr.");
            puts("\t\tdelete [rid]\tdelete the todo.");
            puts("\t\tstart [rid]\tstart the todo.");
            puts("\t\tstop [rid]\tstop the todo.");
            puts("\t\tdone [rid]\tdone the todo.");
            goto error;
        }
    }

    if (!data) {
        perror("Unknown server response(server down or invalid authenticate?)");
        goto error;
    }
    obj = json_tokener_parse(data);
    free(data);

    if (is_error(obj)) {
        perror("Unknown server response(not json?)");
        goto error;
    }

    if (json_object_is_type(obj, json_type_object)) {
        res = json_object_object_get(obj, "error");
        if (!is_error(res)) {
            char* _res = utf8_to_string_alloc(json_object_get_string(res));
            if (_res) {
                printf("error: %s\n", _res);
                free(_res);
                goto error;
            }
        }
        res = json_object_object_get(obj, "message");
        if (!is_error(res)) {
            char* _res = utf8_to_string_alloc(json_object_get_string(res));
            if (_res) {
                printf("message: %s\n", _res);
                free(_res);
            }
        }
    }

    if (json_object_is_type(obj, json_type_array)) {
        for(i = 0; i < json_object_array_length(obj); i++) {
            struct json_object *item = json_object_array_get_idx(obj, i);
            struct json_object* todo_rid = json_object_object_get(item, "todo_rid");
            struct json_object* body = json_object_object_get(item, "body");
            if (!is_error(todo_rid) && !is_error(body)) {
                char* _todo_rid = utf8_to_string_alloc(json_object_get_string(todo_rid));
                char* _body = utf8_to_string_alloc(json_object_get_string(body));
                printf("TODO-%03d [%s] %s\n", i+1, _todo_rid, _body);
                free(_todo_rid);
                free(_body);
            }
        }
    } else
    if (json_object_is_type(obj, json_type_object)) {
        struct json_object* todo_rid = json_object_object_get(obj, "todo_rid");
        if (!is_error(todo_rid)) {
            char* _todo_rid = utf8_to_string_alloc(json_object_get_string(todo_rid));
            if (_todo_rid) {
                printf("%s\n", _todo_rid);
                free(_todo_rid);
            }
        }
    }
    return 0;

error:
    if (user) free(user);
    if (pass) free(pass);
    return -1;
}
Posted at by