<commit_before>--[[
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version
 2 of the License, or (at your option) any later version.
]]
--------------------------------------------------
-- MZ3 Script : twitter
--
-- $Id$
--------------------------------------------------
mz3.logger_debug('twitter.lua start');
module("twitter", package.seeall)

ID_REPORT_URL_BASE = 36100 -37000;	-- URLJ

----------------------------------------
-- T[rX̓o^(^up)
----------------------------------------
mz3.regist_service('Twitter', true);

----------------------------------------
-- ANZXʂ̓o^
----------------------------------------
--[[
type = mz3.get_access_type_by_key('TWITTER_FRIENDS_TIMELINE');
mz3_access_type_info.set_body_integrated_line_pattern(type, 1, '<small>%2 \t(%3)</small>');
mz3_access_type_info.set_body_integrated_line_pattern(type, 2, '%1');
mz3_access_type_info.set_body_integrated_line_pattern(type, 1, '%1');
mz3_access_type_info.set_body_integrated_line_pattern(type, 2, '<small>%2 \t(%3)</small>');
]]

-- POSTpANZXʓo^
type = MZ3AccessTypeInfo:create();
type:set_info_type('post');									-- JeS
type:set_service_type('Twitter');							-- T[rX
type:set_serialize_key('TWITTER_FAVOURINGS_CREATE');		-- VACYL[
type:set_short_title('Cɓo^');						-- ȈՃ^Cg
type:set_request_method('POST');							-- NGXg\bh
type:set_request_encoding('utf8');							-- GR[fBO

type = MZ3AccessTypeInfo:create();
type:set_info_type('post');									-- JeS
type:set_service_type('Twitter');							-- T[rX
type:set_serialize_key('TWITTER_FAVOURINGS_DESTROY');		-- VACYL[
type:set_short_title('Cɓ폜');						-- ȈՃ^Cg
type:set_request_method('POST');							-- NGXg\bh
type:set_request_encoding('utf8');							-- GR[fBO

type = MZ3AccessTypeInfo:create();
type:set_info_type('post');									-- JeS
type:set_service_type('Twitter');							-- T[rX
type:set_serialize_key('TWITTER_FRIENDSHIPS_CREATE');		-- VACYL[
type:set_short_title('tH[o^');						-- ȈՃ^Cg
type:set_request_method('POST');							-- NGXg\bh
type:set_request_encoding('utf8');							-- GR[fBO

type = MZ3AccessTypeInfo:create();
type:set_info_type('post');									-- JeS
type:set_service_type('Twitter');							-- T[rX
type:set_serialize_key('TWITTER_FRIENDSHIPS_DESTROY');		-- VACYL[
type:set_short_title('tH[');						-- ȈՃ^Cg
type:set_request_method('POST');							-- NGXg\bh
type:set_request_encoding('utf8');							-- GR[fBO


--------------------------------------------------
-- [list] ^CCpp[T
--
-- http://twitter.com/statuses/friends_timeline.xml
--
-- :
--   parent: yC̑IIuWFNg(MZ3Data*)
--   body:   yC̃IuWFNgQ(MZ3DataList*)
--   html:   HTMLf[^(CHtmlArray*)
--------------------------------------------------
function twitter_friends_timeline_parser(parent, body, html)
	mz3.logger_debug("twitter_friends_timeline_parser start");
	
	-- wrapperNX
	parent = MZ3Data:create(parent);
	body = MZ3DataList:create(body);
	html = MZ3HTMLArray:create(html);

	-- SȂ
	body:clear();
	
	-- dh~p id ꗗ𐶐B
	id_set = {};
	n = body:get_count();
	for i=0, n-1 do
		id = mz3_data.get_integer(body:get_data(i), 'id');
--		mz3.logger_debug(id);
		id_set[ id ] = true;
	end

	local t1 = mz3.get_tick_count();
	
	-- ꎞXg
	new_list = MZ3DataList:create();
	
	-- sɕĂ̂1sɌ
	line = '';
	local line_count = html:get_count();
	status = '';
	for i=0, line_count-1 do
		line = html:get_at(i);
		
		if line_has_strings(line, '<status>') then
			status = line;
		elseif line_has_strings(line, '</status>') then
			status = status .. line;
			
			-- id : status/id
			s = status:match('<id>(.-)</id>');
			
			-- IDΒǉȂB
			if id_set[ id ] == nil then
				-- data 
				data = MZ3Data:create();
				
				data:set_integer('id', s);
				
				type = mz3.get_access_type_by_key('TWITTER_USER');
				data:set_access_type(type);
				
				-- text : status/text
				text = status:match('<text>(.-)</text>');
				text = mz3.decode_html_entity(text);
				data:add_text_array('body', text);
				
				-- source : status/source
				s = status:match('<source>(.-)</source>');
				s = mz3.decode_html_entity(s);
				data:set_text('source', s);
				
				-- name : status/user/screen_name
				user = status:match('<user>.-</user>');
				s = user:match('<screen_name>(.-)</screen_name>');
				s = mz3.decode_html_entity(s);
				data:set_text('name', s);
				
				-- author : status/user/name
				s = user:match('<name>(.-)</name>');
				s = mz3.decode_html_entity(s);
				data:set_text('author', s);

				-- description : status/user/description
				-- title ɓ̂͋̍EEE
				s = user:match('<description>(.-)</description>');
				s = mz3.decode_html_entity(s);
				data:set_text('title', s);

				-- owner-id : status/user/id
				data:set_integer('owner_id', user:match('<id>(.-)</id>'));

				-- URL : status/user/url
				url = user:match('<url>(.-)</url>');
				data:set_text('url', url);
				data:set_text('browse_uri', url);

				-- Image : status/user/profile_image_url
				profile_image_url = user:match('<profile_image_url>(.-)</profile_image_url>');
				profile_image_url = mz3.decode_html_entity(profile_image_url);
--				mz3.logger_debug(profile_image_url);

				-- t@Ĉ݂URLGR[h
--				int idx = strImage.ReverseFind( '/' );
--				if (idx >= 0) {
--					CString strFileName = strImage.Mid( idx +1 );
--					strFileName = URLEncoder::encode_utf8( strFileName );
--					strImage = strImage.Left(idx + 1);
--					strImage += strFileName;
--				}
				data:add_text_array('image', profile_image_url);

--				<location>East Tokyo United</location>
				data:set_text('location', mz3.decode_html_entity(user:match('<location>(.-)</location>')));
--				<followers_count>555</followers_count>
				data:set_integer('followers_count', user:match('<followers_count>(.-)</followers_count>'));
--				<friends_count>596</friends_count>
				data:set_integer('friends_count', user:match('<friends_count>(.-)</friends_count>'));
--				<favourites_count>361</favourites_count>
				data:set_integer('favourites_count', user:match('<favourites_count>(.-)</favourites_count>'));
--				<statuses_count>7889</statuses_count>
				data:set_integer('statuses_count', user:match('<statuses_count>(.-)</statuses_count>'));

				-- updated : status/created_at
				s = status:match('<created_at>(.-)</created_at>');
				data:parse_date_line(s);
				
				-- URL 𒊏oANɂ
				for url in text:gmatch("h?ttps?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+") do
					data:add_link_list(url, url);
					mz3.logger_debug(url);
				end

				-- ꎞXgɒǉ
				new_list:add(data.data);
				
				-- data 폜
				data:delete();

			end

			--  status 擾
			status = '';
		elseif status ~= '' then	-- status ł <status> Ȃ̂œǂݔ΂
			status = status .. line;
		end
	end
	
	-- f[^o͂ɔf
	body:merge(new_list);
	--TwitterParserBase::MergeNewList(out_, new_list);

	new_list:delete();
	
	-- V parent(JeS m_mixi) ɐݒ肷
	parent:set_integer('new_count', new_count);
	
	local t2 = mz3.get_tick_count();
	mz3.logger_debug("twitter_friends_timeline_parser end; elapsed : " .. (t2-t1) .. "[msec]");
end
mz3.set_parser("TWITTER_FRIENDS_TIMELINE", "twitter.twitter_friends_timeline_parser");


----------------------------------------
-- j[ړo^(ÓIɗpӂ邱)
----------------------------------------
menu_items = {}
menu_items.read                  = mz3_menu.regist_menu("twitter.on_read_menu_item");
menu_items.retweet               = mz3_menu.regist_menu("twitter.on_retweet_menu_item");

--  @xxx o҂TL(5l܂)
menu_items.show_follower_tl = {}
menu_items.show_follower_tl[1]   = mz3_menu.regist_menu("twitter.on_show_follower_tl_1");
menu_items.show_follower_tl[2]   = mz3_menu.regist_menu("twitter.on_show_follower_tl_2");
menu_items.show_follower_tl[3]   = mz3_menu.regist_menu("twitter.on_show_follower_tl_3");
menu_items.show_follower_tl[4]   = mz3_menu.regist_menu("twitter.on_show_follower_tl_4");
menu_items.show_follower_tl[5]   = mz3_menu.regist_menu("twitter.on_show_follower_tl_5");
follower_names = {}

menu_items.update                = mz3_menu.regist_menu("twitter.on_twitter_update");
menu_items.reply                 = mz3_menu.regist_menu("twitter.on_twitter_reply");
menu_items.new_dm                = mz3_menu.regist_menu("twitter.on_twitter_new_dm");
menu_items.create_favourings     = mz3_menu.regist_menu("twitter.on_twitter_create_favourings");
menu_items.destroy_favourings    = mz3_menu.regist_menu("twitter.on_twitter_destroy_favourings");
menu_items.create_friendships    = mz3_menu.regist_menu("twitter.on_twitter_create_friendships");
menu_items.destroy_friendships   = mz3_menu.regist_menu("twitter.on_twitter_destroy_friendships");
menu_items.show_friend_timeline  = mz3_menu.regist_menu("twitter.on_show_friend_timeline");
menu_items.open_home             = mz3_menu.regist_menu("twitter.on_open_home");
menu_items.open_friend_favorites = mz3_menu.regist_menu("twitter.on_open_friend_favorites");
menu_items.open_friend_favorites_by_browser = mz3_menu.regist_menu("twitter.on_open_friend_favorites_by_browser");
menu_items.open_friend_site      = mz3_menu.regist_menu("twitter.on_open_friend_site");



----------------------------------------
-- T[rXp֐
----------------------------------------

--- Xe[^XR[h
function get_http_status_error_status(http_status)

	if http_status==200 or http_status==304 then
		-- 200 OK: 
		-- 304 Not Modified: V͂Ȃ
		return nil;
	elseif http_status==400 then		-- Bad Request:
		return "API ̎s񐔐Ɉ|AȂǂ̗RŃNGXgp";
	elseif http_status==401 then		-- Not Authorized:
		return "F؎s";
	elseif http_status==403 then		-- Forbidden:
		return "ȂAPI s悤Ƃ";
	elseif http_status==404 then		-- Not Found:
		return "݂Ȃ API s悤ƂA݂Ȃ[UŎw肵 API s悤Ƃ";
	elseif http_status==500 then		-- Internal Server Error:
		return "Twitter ŉ炩̖肪Ă܂";
	elseif http_status==502 then		-- Bad Gateway:
		return "Twitter ̃T[o~܂Ă܂ie܂j";
	elseif http_status==503 then		-- Service Unavailable:
		return "Twitter ̃T[oׂ̕āANGXgق؂ȂԂɂȂĂ܂";
	end

	return nil;
end


----------------------------------------
-- Cxgnh
----------------------------------------

-- uԂ₭vj[pnh
function on_twitter_update(serialize_key, event_name, data)
	-- [hύX
	mz3_main_view.set_post_mode(MAIN_VIEW_POST_MODE_TWITTER_UPDATE);

	-- [hύXf({^̕ύX)
	mz3_main_view.update_control_status();

	-- tH[JXړ
	mz3_main_view.set_focus('edit');
end

-- uԐMvj[pnh
function on_twitter_reply(serialize_key, event_name, data)
	-- [hύX
	mz3_main_view.set_post_mode(MAIN_VIEW_POST_MODE_TWITTER_UPDATE);

	-- [hύXf({^̕ύX)
	mz3_main_view.update_control_status();

	-- ͗̈Ƀ[ŨXN[ǉ
	text = mz3_main_view.get_edit_text();
	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	name = body:get_text('name');
	-- łɊ܂܂ĂΒǉȂ
	if text:find("@" .. name, 1, true)~=nil then
		return;
	end
	text = text .. "@" .. name .. " ";
	
	mz3_main_view.set_edit_text(text);

	-- tH[JXړ
	mz3_main_view.set_focus('edit');

	-- ֈړ
	VK_END = 0x23;
	mz3.keybd_event(VK_END, "keydown");
	mz3.keybd_event(VK_END, "keyup");
end

-- ubZ[WMvj[pnh
function on_twitter_new_dm(serialize_key, event_name, data)
	-- [hύX
	mz3_main_view.set_post_mode(MAIN_VIEW_POST_MODE_TWITTER_DM);

	-- [hύXf({^̕ύX)
	mz3_main_view.update_control_status();

	-- tH[JXړ
	mz3_main_view.set_focus('edit');
end

-- uCɓo^vj[pnh
function on_twitter_create_favourings(serialize_key, event_name, data)
	-- URL 
	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	id = body:get_integer('id');
	url = "http://twitter.com/favourings/create/" .. id .. ".xml";

	-- ʐMJn
	key = "TWITTER_FAVOURINGS_CREATE";
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

-- uCɓ폜vj[pnh
function on_twitter_destroy_favourings(serialize_key, event_name, data)
	-- URL 
	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	id = body:get_integer('id');
	url = "http://twitter.com/favourings/destroy/" .. id .. ".xml";

	-- ʐMJn
	key = "TWITTER_FAVOURINGS_DESTROY";
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

-- utH[vj[pnh
function on_twitter_create_friendships(serialize_key, event_name, data)

	-- mF
	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	name = body:get_text('name');
	if mz3.confirm(name .. " tH[܂B낵łH", nil, "yes_no") ~= 'yes' then
		-- ~
		return;
	end

	-- URL 
	url = "http://twitter.com/friendships/create/" .. name .. ".xml";

	-- ʐMJn
	key = "TWITTER_FRIENDSHIPS_CREATE";
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

-- utH[߂vj[pnh
function on_twitter_destroy_friendships(serialize_key, event_name, data)

	-- mF
	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	name = body:get_text('name');
	if mz3.confirm(name .. " ̃tH[܂B낵łH", nil, "yes_no") ~= 'yes' then
		-- ~
		return;
	end

	-- URL 
	url = "http://twitter.com/friendships/destroy/" .. name .. ".xml";

	-- ʐMJn
	key = "TWITTER_FRIENDSHIPS_DESTROY";
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

--- u@xxx ̃^CCvj[pnh
function on_show_friend_timeline(serialize_key, event_name, data)
	body = mz3_main_view.get_selected_body_item();
	body = MZ3Data:create(body);
	name = body:get_text('name');
	
	-- JeSǉ
	title = "@" .. name .. "̃^CC";
	url = "http://twitter.com/statuses/user_timeline/" .. name .. ".xml";
	key = "TWITTER_FRIENDS_TIMELINE";
	mz3_main_view.append_category(title, url, key);
	
	-- ǉJeS̎擾Jn
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

--- u@xxx ̃^CCv(tH[)j[pnh
function on_show_follower_tl_1(serialize_key, event_name, data)	show_follower_tl(1) end
function on_show_follower_tl_2(serialize_key, event_name, data)	show_follower_tl(2) end
function on_show_follower_tl_3(serialize_key, event_name, data)	show_follower_tl(3) end
function on_show_follower_tl_4(serialize_key, event_name, data)	show_follower_tl(4) end
function on_show_follower_tl_5(serialize_key, event_name, data)	show_follower_tl(5) end
function show_follower_tl(num)
	--  num Ԗڂ @xxx [U TL \
	name = follower_names[num];
	
	-- JeSǉ
	title = "@" .. name .. "̃^CC";
	url = "http://twitter.com/statuses/user_timeline/" .. name .. ".xml";
	key = "TWITTER_FRIENDS_TIMELINE";
	mz3_main_view.append_category(title, url, key);
	
	-- ǉJeS̎擾Jn
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

--- uReTweetvj[pnh
function on_retweet_menu_item(serialize_key, event_name, data)
	-- [hύX
	mz3_main_view.set_post_mode(MAIN_VIEW_POST_MODE_TWITTER_UPDATE);

	-- [hύXf({^̕ύX)
	mz3_main_view.update_control_status();

	-- GfBbgRg[ɕݒ
	data = mz3_main_view.get_selected_body_item();
	data = MZ3Data:create(data);
	text = "RT @" .. data:get_text('name') .. ": " .. data:get_text_array_joined_text('body');
	text = text:gsub("\r\n", "");
	mz3_main_view.set_edit_text(text);

	-- tH[JXړ
	mz3_main_view.set_focus('edit');
end

--- uz[vj[pnh
function on_open_home(serialize_key, event_name, data)

	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	
	mz3.open_url_by_browser_with_confirm("http://twitter.com/" .. body:get_text('name'));
end

--- uFB̂Cɓvj[pnh
function on_open_friend_favorites_by_browser(serialize_key, event_name, data)

	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	
	mz3.open_url_by_browser_with_confirm("http://twitter.com/" .. body:get_text('name') .. "/favorites");
end

--- uFB̃TCgvj[pnh
function on_open_friend_site(serialize_key, event_name, data)

	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	
	mz3.open_url_by_browser_with_confirm(body:get_text('url'));
end

--- uFB̂Cɓvj[pnh
function on_open_friend_favorites(serialize_key, event_name, data)

	body = mz3_main_view.get_selected_body_item();
	body = MZ3Data:create(body);
	name = body:get_text('name');
	
	-- JeSǉ
	title = "@" .. name .. "̂Cɓ";
	url = "http://twitter.com/favorites/" .. name .. ".xml";
	key = "TWITTER_FAVORITES";
	mz3_main_view.append_category(title, url, key);
	
	-- ǉJeS̎擾Jn
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

--- {fBXg̃_uNbN(܂Enter)̃Cxgnh
function on_body_list_click(serialize_key, event_name, data)
	if serialize_key=="TWITTER_USER" then
		-- S\
		return on_read_menu_item(serialize_key, event_name, data);
	end
	
	-- W̏𑱍s
	return false;
end

--- S\j[܂̓_uNbNCxg
function on_read_menu_item(serialize_key, event_name, data)
	mz3.logger_debug('on_read_menu_item : (' .. serialize_key .. ', ' .. event_name .. ')');
	data = MZ3Data:create(data);
--	mz3.logger_debug(data:get_text('name'));
	
	-- {1sɕϊĕ\
	item = data:get_text_array_joined_text('body');
	item = item:gsub("\r\n", "");
	
	item = item .. "\r\n";
	item = item .. "----\r\n";
	item = item .. "name : " .. data:get_text('name') .. " / " .. data:get_text('author') .. "\r\n";
	item = item .. "description : " .. data:get_text('title') .. "\r\n";
	item = item .. data:get_date() .. "\r\n";
--	item = item .. "id : " .. data:get_integer('id') .. "\r\n";
--	item = item .. "owner-id : " .. data:get_integer('owner_id') .. "\r\n";

	if data:get_text('location') ~= '' then
		item = item .. "location : " .. data:get_text('location') .. "\r\n";
	end
	
	if data:get_integer('friends_count') ~= -1 then
		item = item .. "followings : " .. data:get_integer('friends_count')
		            .. ", "
		            .. "followers : " .. data:get_integer('followers_count')
		            .. ", "
		            .. "fav : " .. data:get_integer('favourites_count')
		            .. ", "
		            .. " : " .. data:get_integer('statuses_count')
		            .. "\r\n";
	end
	
	-- \[X
	source = data:get_text('source');
--	item = item .. "source : " .. source .. "\r\n";
	s_url, s_name = source:match("href=\"(.*)\".*>(.*)<");
	if s_url ~= nil then
		item = item .. "source : " .. s_name .. " (" .. s_url .. ")\r\n";
	else
		item = item .. "source : " .. source .. "\r\n";
	end

	mz3.alert(item, data:get_text('name'));

	return true;
end

--- POST Cxg
--
-- @param event_name    'post_end'
-- @param serialize_key ڂ̃VACYL[
-- @param http_status   HTTP Status Code (200, 404, etc...)
-- @param wnd           wnd
--
function on_post_end(event_name, serialize_key, http_status)

	service_type = mz3.get_service_type(serialize_key);
	if service_type~="Twitter" then
		return false;
	end

	-- Twittere

	-- Xe[^XR[h`FbN
	msg = get_http_status_error_status(http_status);
	if msg ~= nil then
		-- G[AȂ̂Œf邽߂ true Ԃ
		mz3.logger_error(msg);
		mz3_main_view.set_info_text(msg);
		return true;
	end

	-- NGXg̎ʂɉăbZ[W\
	if serialize_key == "TWITTER_NEW_DM" then
		mz3_main_view.set_info_text("bZ[WMI");
	elseif serialize_key == "TWITTER_FAVOURINGS_CREATE" then
		mz3_main_view.set_info_text("ӂڂI");
	elseif serialize_key == "TWITTER_FAVOURINGS_DESTROY" then
		mz3_main_view.set_info_text("ӂڂ̂߂I");
	elseif serialize_key == "TWITTER_FRIENDSHIPS_CREATE" then
		mz3_main_view.set_info_text("tH[I");
	elseif serialize_key == "TWITTER_FRIENDSHIPS_DESTROY" then
		mz3_main_view.set_info_text("tH[߂I");
	else 
		-- TWITTER_UPDATE
		mz3_main_view.set_info_text("Xe[^XMI");
	end

	-- Wassr ւ̓e(NX|Xg)
--[[
	if serialize_key == "TWITTER_UPDATE" then

		text = mz3_main_view.get_edit_text();
		msg = "Wassr ɂe܂H\r\n";
		msg = msg .. "----\r\n";
		msg = msg .. text .. "\r\n";
		msg = msg .. "----\r\n";
		
		if mz3.confirm(msg, nil, "yes_no") == "yes" then
		
			-- URL 
			url = "http://api.wassr.jp/statuses/update.json";
			post = mz3_post_data.create();
			mz3_post_data.append_post_body(post, "status=");
			mz3_post_data.append_post_body(post, mz3.url_encode(text, 'utf8'));
			mz3_post_data.append_post_body(post, "&source=");
			mz3_post_data.append_post_body(post, mz3.get_app_name());
			
			-- ʐMJn
			access_type = mz3.get_access_type_by_key("WASSR_UPDATE");
			referer = '';
			user_agent = nil;
			mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
			return true;
		end
	end
]]

	-- ͒l
	mz3_main_view.set_edit_text("");
	
	return true;
end

--- GET Cxg
--
-- @param event_name    'get_end'
-- @param serialize_key ڂ̃VACYL[
-- @param http_status   HTTP Status Code (200, 404, etc...)
-- @param wnd           wnd
--
function on_get_end(event_name, serialize_key, http_status)

	service_type = mz3.get_service_type(serialize_key);
	if service_type~="Twitter" then
		return false;
	end

	-- Xe[^XR[h`FbN̂ݍs
	msg = get_http_status_error_status(http_status);
	if msg ~= nil then
		-- G[AȂ̂Œf邽߂ true Ԃ
		mz3.logger_error(msg);
		mz3_main_view.set_info_text(msg);
		mz3.alert("T[oG[(" .. http_status .. ") : " .. msg);
		return true;
	end
	-- G[ȂȂ̂ős(㑱̉͏p)

	return false;
end

--- {fBXg̃|bvAbvj[\
--
-- @param event_name    'popup_body_menu'
-- @param serialize_key {fBACẽVACYL[
-- @param body          body
-- @param wnd           wnd
--
function on_popup_body_menu(event_name, serialize_key, body, wnd)
	if serialize_key~="TWITTER_USER" then
		return false;
	end

	-- CX^X
	body = MZ3Data:create(body);
	
	-- j[
	menu = MZ3Menu:create_popup_menu();
	submenu = MZ3Menu:create_popup_menu();
	
	menu:append_menu("string", "ŐV̈ꗗ擾", IDM_CATEGORY_OPEN);
	menu:append_menu("string", "Sǂ...", menu_items.read);

	menu:append_menu("separator");

	menu:append_menu("string", "Ԃ₭", menu_items.update);

	name = body:get_text('name');

	menu:append_menu("string", "@" .. name .. " ɕԐM", menu_items.reply);
	menu:append_menu("string", "@" .. name .. " ɃbZ[WM", menu_items.new_dm);

	menu:append_menu("separator");

	menu:append_menu("string", "ReTweet...", menu_items.retweet);
	
	-- JeSutimelinev̂݁ACɓo^\
	category_access_type = mz3_main_view.get_selected_category_access_type();
	category_key = mz3.get_serialize_key_by_access_type(category_access_type);
	if category_key == "TWITTER_FRIENDS_TIMELINE" then
		menu:append_menu("string", "Cɓo^iӂڂj", menu_items.create_favourings);
	end
	
	-- JeSuCɓv̂݁ACɓ폜\
	if category_key == "TWITTER_FAVORITES" then
		menu:append_menu("string", "Cɓ폜", menu_items.destroy_favourings);
	end

	menu:append_menu("separator");

	menu:append_menu("string", "@" .. name .. " ̃^CC", menu_items.show_friend_timeline);
	
	--  @XXX 𒊏oAj[
	body_text = body:get_text_array_joined_text('body');
	i = 1;
	for f_name in body_text:gmatch("@([0-9a-zA-Z_]+)") do
		mz3.logger_debug(f_name);
		-- Lua ϐɖOۑĂ
		follower_names[i] = f_name;
		menu:append_menu("string", "@" .. f_name .. " ̃^CC", menu_items.show_follower_tl[i]);
		-- ő5l܂ŃT|[g
		i = i+1;
		if i>5 then
			break;
		end
	end

--	menu:append_menu("separator");
	
	submenu:append_menu("string", "@" .. name .. " tH[", menu_items.create_friendships);
	submenu:append_menu("string", "@" .. name .. " ̃tH[߂", menu_items.destroy_friendships);
	submenu:append_menu("string", "@" .. name .. " ̃z[uEUŊJ", menu_items.open_home);
	submenu:append_menu("string", "@" .. name .. " ̂CɓuEUŊJ", menu_items.open_friend_favorites_by_browser);
	submenu:append_menu("string", "@" .. name .. " ̂Cɓ", menu_items.open_friend_favorites);
	menu:append_submenu("̑", submenu);

	-- URL łȂ΁uTCgvǉ
	url = body:get_text('url');
	if url~=nil and url:len()>0 then
		submenu:append_menu("string", "@" .. name .. " ̃TCguEUŊJ", menu_items.open_friend_site);
	end

	-- Nǉ
	n = body:get_link_list_size();
	if n > 0 then
		menu:append_menu("separator");
		for i=0, n-1 do
			id = ID_REPORT_URL_BASE+(i+1);
			menu:append_menu("string", "link : " .. body:get_link_list_text(i), id);
		end
	end

	-- |bvAbv
	menu:popup(wnd);
	
	-- j[\[X폜
	menu:delete();
	submenu:delete();
	
	return true;
end

--- ftHg̃O[vXgCxgnh
--
-- @param serialize_key VACYL[(nil)
-- @param event_name    'creating_default_group'
-- @param group         MZ3GroupData
--
function on_creating_default_group(serialize_key, event_name, group)

	-- T|[gT[rXʂ̎擾(Xy[X؂)
	services = mz3_group_data.get_services(group);
	if services:find(' Twitter', 1, true) ~= nil then

		-- Twitter^uǉ
		local tab = MZ3GroupItem:create("Twitter");
		tab:append_category("^CC", "TWITTER_FRIENDS_TIMELINE", "http://twitter.com/statuses/friends_timeline.xml");
		tab:append_category("ԐMꗗ", "TWITTER_FRIENDS_TIMELINE", "http://twitter.com/statuses/replies.xml");
		tab:append_category("Cɓ", "TWITTER_FAVORITES", "http://twitter.com/favorites.xml");
		tab:append_category("MbZ[W", "TWITTER_DIRECT_MESSAGES", "http://twitter.com/direct_messages.xml");
		tab:append_category("MbZ[W", "TWITTER_DIRECT_MESSAGES", "http://twitter.com/direct_messages/sent.xml");
		mz3_group_data.append_tab(group, tab.item);
		tab:delete();
	end
end

----------------------------------------
-- Cxgnh̓o^
----------------------------------------

-- {fBXg̃_uNbN(܂Enter)Cxgnho^
mz3.add_event_listener("dblclk_body_list", "twitter.on_body_list_click");
mz3.add_event_listener("enter_body_list",  "twitter.on_body_list_click");

-- {fBXg̃|bvAbvj[\Cxgnho^
mz3.add_event_listener("popup_body_menu",  "twitter.on_popup_body_menu");

-- POSTCxgnho^
mz3.add_event_listener("post_end", "twitter.on_post_end");
mz3.add_event_listener("get_end",  "twitter.on_get_end");

-- ftHg̃O[vXg
mz3.add_event_listener("creating_default_group", "twitter.on_creating_default_group", false);

mz3.logger_debug('twitter.lua end');
<commit_msg>重複チェック等に失敗しているのを修正。<commit_after>--[[
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version
 2 of the License, or (at your option) any later version.
]]
--------------------------------------------------
-- MZ3 Script : twitter
--
-- $Id$
--------------------------------------------------
mz3.logger_debug('twitter.lua start');
module("twitter", package.seeall)

ID_REPORT_URL_BASE = 36100 -37000;	-- URLJ

----------------------------------------
-- T[rX̓o^(^up)
----------------------------------------
mz3.regist_service('Twitter', true);

----------------------------------------
-- ANZXʂ̓o^
----------------------------------------
--[[
type = mz3.get_access_type_by_key('TWITTER_FRIENDS_TIMELINE');
mz3_access_type_info.set_body_integrated_line_pattern(type, 1, '<small>%2 \t(%3)</small>');
mz3_access_type_info.set_body_integrated_line_pattern(type, 2, '%1');
mz3_access_type_info.set_body_integrated_line_pattern(type, 1, '%1');
mz3_access_type_info.set_body_integrated_line_pattern(type, 2, '<small>%2 \t(%3)</small>');
]]

-- POSTpANZXʓo^
type = MZ3AccessTypeInfo:create();
type:set_info_type('post');									-- JeS
type:set_service_type('Twitter');							-- T[rX
type:set_serialize_key('TWITTER_FAVOURINGS_CREATE');		-- VACYL[
type:set_short_title('Cɓo^');						-- ȈՃ^Cg
type:set_request_method('POST');							-- NGXg\bh
type:set_request_encoding('utf8');							-- GR[fBO

type = MZ3AccessTypeInfo:create();
type:set_info_type('post');									-- JeS
type:set_service_type('Twitter');							-- T[rX
type:set_serialize_key('TWITTER_FAVOURINGS_DESTROY');		-- VACYL[
type:set_short_title('Cɓ폜');						-- ȈՃ^Cg
type:set_request_method('POST');							-- NGXg\bh
type:set_request_encoding('utf8');							-- GR[fBO

type = MZ3AccessTypeInfo:create();
type:set_info_type('post');									-- JeS
type:set_service_type('Twitter');							-- T[rX
type:set_serialize_key('TWITTER_FRIENDSHIPS_CREATE');		-- VACYL[
type:set_short_title('tH[o^');						-- ȈՃ^Cg
type:set_request_method('POST');							-- NGXg\bh
type:set_request_encoding('utf8');							-- GR[fBO

type = MZ3AccessTypeInfo:create();
type:set_info_type('post');									-- JeS
type:set_service_type('Twitter');							-- T[rX
type:set_serialize_key('TWITTER_FRIENDSHIPS_DESTROY');		-- VACYL[
type:set_short_title('tH[');						-- ȈՃ^Cg
type:set_request_method('POST');							-- NGXg\bh
type:set_request_encoding('utf8');							-- GR[fBO


--------------------------------------------------
-- [list] ^CCpp[T
--
-- http://twitter.com/statuses/friends_timeline.xml
--
-- :
--   parent: yC̑IIuWFNg(MZ3Data*)
--   body:   yC̃IuWFNgQ(MZ3DataList*)
--   html:   HTMLf[^(CHtmlArray*)
--------------------------------------------------
function twitter_friends_timeline_parser(parent, body, html)
	mz3.logger_debug("twitter_friends_timeline_parser start");
	
	-- wrapperNX
	parent = MZ3Data:create(parent);
	body = MZ3DataList:create(body);
	html = MZ3HTMLArray:create(html);

	-- SȂ
--	body:clear();
	
	-- dh~p id ꗗ𐶐B
	id_set = {};
	n = body:get_count();
	for i=0, n-1 do
		id = mz3_data.get_integer(body:get_data(i), 'id');
--		mz3.logger_debug(id);
		id_set[ id ] = true;
	end

	local t1 = mz3.get_tick_count();
	
	-- ꎞXg
	new_list = MZ3DataList:create();
	
	-- sɕĂ̂1sɌ
	line = '';
	local line_count = html:get_count();
	status = '';
	for i=0, line_count-1 do
		line = html:get_at(i);
		
		if line_has_strings(line, '<status>') then
			status = line;
		elseif line_has_strings(line, '</status>') then
			status = status .. line;
			
			-- id : status/id
			id = status:match('<id>(.-)</id>');
			
			-- IDΒǉȂB
			if id_set[ id ] == nil then
				-- data 
				data = MZ3Data:create();
				
				data:set_integer('id', id);
				
				type = mz3.get_access_type_by_key('TWITTER_USER');
				data:set_access_type(type);
				
				-- text : status/text
				text = status:match('<text>(.-)</text>');
				text = mz3.decode_html_entity(text);
				data:add_text_array('body', text);
				
				-- source : status/source
				s = status:match('<source>(.-)</source>');
				s = mz3.decode_html_entity(s);
				data:set_text('source', s);
				
				-- name : status/user/screen_name
				user = status:match('<user>.-</user>');
				s = user:match('<screen_name>(.-)</screen_name>');
				s = mz3.decode_html_entity(s);
				data:set_text('name', s);
				
				-- author : status/user/name
				s = user:match('<name>(.-)</name>');
				s = mz3.decode_html_entity(s);
				data:set_text('author', s);

				-- description : status/user/description
				-- title ɓ̂͋̍EEE
				s = user:match('<description>(.-)</description>');
				s = mz3.decode_html_entity(s);
				data:set_text('title', s);

				-- owner-id : status/user/id
				data:set_integer('owner_id', user:match('<id>(.-)</id>'));

				-- URL : status/user/url
				url = user:match('<url>(.-)</url>');
				data:set_text('url', url);
				data:set_text('browse_uri', url);

				-- Image : status/user/profile_image_url
				profile_image_url = user:match('<profile_image_url>(.-)</profile_image_url>');
				profile_image_url = mz3.decode_html_entity(profile_image_url);
--				mz3.logger_debug(profile_image_url);

				-- t@Ĉ݂URLGR[h
--				int idx = strImage.ReverseFind( '/' );
--				if (idx >= 0) {
--					CString strFileName = strImage.Mid( idx +1 );
--					strFileName = URLEncoder::encode_utf8( strFileName );
--					strImage = strImage.Left(idx + 1);
--					strImage += strFileName;
--				}
				data:add_text_array('image', profile_image_url);

--				<location>East Tokyo United</location>
				data:set_text('location', mz3.decode_html_entity(user:match('<location>(.-)</location>')));
--				<followers_count>555</followers_count>
				data:set_integer('followers_count', user:match('<followers_count>(.-)</followers_count>'));
--				<friends_count>596</friends_count>
				data:set_integer('friends_count', user:match('<friends_count>(.-)</friends_count>'));
--				<favourites_count>361</favourites_count>
				data:set_integer('favourites_count', user:match('<favourites_count>(.-)</favourites_count>'));
--				<statuses_count>7889</statuses_count>
				data:set_integer('statuses_count', user:match('<statuses_count>(.-)</statuses_count>'));

				-- updated : status/created_at
				s = status:match('<created_at>(.-)</created_at>');
				data:parse_date_line(s);
				
				-- URL 𒊏oANɂ
				for url in text:gmatch("h?ttps?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+") do
					data:add_link_list(url, url);
--					mz3.logger_debug(url);
				end

				-- ꎞXgɒǉ
				new_list:add(data.data);
				
				-- data 폜
				data:delete();

			end

			--  status 擾
			status = '';
		elseif status ~= '' then	-- status ł <status> Ȃ̂œǂݔ΂
			status = status .. line;
		end
	end
	
	-- f[^o͂ɔf
	body:merge(new_list);
	--TwitterParserBase::MergeNewList(out_, new_list);

	new_list:delete();
	
	-- V parent(JeS m_mixi) ɐݒ肷
	parent:set_integer('new_count', new_count);
	
	local t2 = mz3.get_tick_count();
	mz3.logger_debug("twitter_friends_timeline_parser end; elapsed : " .. (t2-t1) .. "[msec]");
end
mz3.set_parser("TWITTER_FRIENDS_TIMELINE", "twitter.twitter_friends_timeline_parser");


----------------------------------------
-- j[ړo^(ÓIɗpӂ邱)
----------------------------------------
menu_items = {}
menu_items.read                  = mz3_menu.regist_menu("twitter.on_read_menu_item");
menu_items.retweet               = mz3_menu.regist_menu("twitter.on_retweet_menu_item");

--  @xxx o҂TL(5l܂)
menu_items.show_follower_tl = {}
menu_items.show_follower_tl[1]   = mz3_menu.regist_menu("twitter.on_show_follower_tl_1");
menu_items.show_follower_tl[2]   = mz3_menu.regist_menu("twitter.on_show_follower_tl_2");
menu_items.show_follower_tl[3]   = mz3_menu.regist_menu("twitter.on_show_follower_tl_3");
menu_items.show_follower_tl[4]   = mz3_menu.regist_menu("twitter.on_show_follower_tl_4");
menu_items.show_follower_tl[5]   = mz3_menu.regist_menu("twitter.on_show_follower_tl_5");
follower_names = {}

menu_items.update                = mz3_menu.regist_menu("twitter.on_twitter_update");
menu_items.reply                 = mz3_menu.regist_menu("twitter.on_twitter_reply");
menu_items.new_dm                = mz3_menu.regist_menu("twitter.on_twitter_new_dm");
menu_items.create_favourings     = mz3_menu.regist_menu("twitter.on_twitter_create_favourings");
menu_items.destroy_favourings    = mz3_menu.regist_menu("twitter.on_twitter_destroy_favourings");
menu_items.create_friendships    = mz3_menu.regist_menu("twitter.on_twitter_create_friendships");
menu_items.destroy_friendships   = mz3_menu.regist_menu("twitter.on_twitter_destroy_friendships");
menu_items.show_friend_timeline  = mz3_menu.regist_menu("twitter.on_show_friend_timeline");
menu_items.open_home             = mz3_menu.regist_menu("twitter.on_open_home");
menu_items.open_friend_favorites = mz3_menu.regist_menu("twitter.on_open_friend_favorites");
menu_items.open_friend_favorites_by_browser = mz3_menu.regist_menu("twitter.on_open_friend_favorites_by_browser");
menu_items.open_friend_site      = mz3_menu.regist_menu("twitter.on_open_friend_site");



----------------------------------------
-- T[rXp֐
----------------------------------------

--- Xe[^XR[h
function get_http_status_error_status(http_status)

	if http_status==200 or http_status==304 then
		-- 200 OK: 
		-- 304 Not Modified: V͂Ȃ
		return nil;
	elseif http_status==400 then		-- Bad Request:
		return "API ̎s񐔐Ɉ|AȂǂ̗RŃNGXgp";
	elseif http_status==401 then		-- Not Authorized:
		return "F؎s";
	elseif http_status==403 then		-- Forbidden:
		return "ȂAPI s悤Ƃ";
	elseif http_status==404 then		-- Not Found:
		return "݂Ȃ API s悤ƂA݂Ȃ[UŎw肵 API s悤Ƃ";
	elseif http_status==500 then		-- Internal Server Error:
		return "Twitter ŉ炩̖肪Ă܂";
	elseif http_status==502 then		-- Bad Gateway:
		return "Twitter ̃T[o~܂Ă܂ie܂j";
	elseif http_status==503 then		-- Service Unavailable:
		return "Twitter ̃T[oׂ̕āANGXgق؂ȂԂɂȂĂ܂";
	end

	return nil;
end


----------------------------------------
-- Cxgnh
----------------------------------------

-- uԂ₭vj[pnh
function on_twitter_update(serialize_key, event_name, data)
	-- [hύX
	mz3_main_view.set_post_mode(MAIN_VIEW_POST_MODE_TWITTER_UPDATE);

	-- [hύXf({^̕ύX)
	mz3_main_view.update_control_status();

	-- tH[JXړ
	mz3_main_view.set_focus('edit');
end

-- uԐMvj[pnh
function on_twitter_reply(serialize_key, event_name, data)
	-- [hύX
	mz3_main_view.set_post_mode(MAIN_VIEW_POST_MODE_TWITTER_UPDATE);

	-- [hύXf({^̕ύX)
	mz3_main_view.update_control_status();

	-- ͗̈Ƀ[ŨXN[ǉ
	text = mz3_main_view.get_edit_text();
	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	name = body:get_text('name');
	-- łɊ܂܂ĂΒǉȂ
	if text:find("@" .. name, 1, true)~=nil then
		return;
	end
	text = text .. "@" .. name .. " ";
	
	mz3_main_view.set_edit_text(text);

	-- tH[JXړ
	mz3_main_view.set_focus('edit');

	-- ֈړ
	VK_END = 0x23;
	mz3.keybd_event(VK_END, "keydown");
	mz3.keybd_event(VK_END, "keyup");
end

-- ubZ[WMvj[pnh
function on_twitter_new_dm(serialize_key, event_name, data)
	-- [hύX
	mz3_main_view.set_post_mode(MAIN_VIEW_POST_MODE_TWITTER_DM);

	-- [hύXf({^̕ύX)
	mz3_main_view.update_control_status();

	-- tH[JXړ
	mz3_main_view.set_focus('edit');
end

-- uCɓo^vj[pnh
function on_twitter_create_favourings(serialize_key, event_name, data)
	-- URL 
	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	id = body:get_integer('id');
	url = "http://twitter.com/favourings/create/" .. id .. ".xml";

	-- ʐMJn
	key = "TWITTER_FAVOURINGS_CREATE";
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

-- uCɓ폜vj[pnh
function on_twitter_destroy_favourings(serialize_key, event_name, data)
	-- URL 
	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	id = body:get_integer('id');
	url = "http://twitter.com/favourings/destroy/" .. id .. ".xml";

	-- ʐMJn
	key = "TWITTER_FAVOURINGS_DESTROY";
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

-- utH[vj[pnh
function on_twitter_create_friendships(serialize_key, event_name, data)

	-- mF
	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	name = body:get_text('name');
	if mz3.confirm(name .. " tH[܂B낵łH", nil, "yes_no") ~= 'yes' then
		-- ~
		return;
	end

	-- URL 
	url = "http://twitter.com/friendships/create/" .. name .. ".xml";

	-- ʐMJn
	key = "TWITTER_FRIENDSHIPS_CREATE";
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

-- utH[߂vj[pnh
function on_twitter_destroy_friendships(serialize_key, event_name, data)

	-- mF
	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	name = body:get_text('name');
	if mz3.confirm(name .. " ̃tH[܂B낵łH", nil, "yes_no") ~= 'yes' then
		-- ~
		return;
	end

	-- URL 
	url = "http://twitter.com/friendships/destroy/" .. name .. ".xml";

	-- ʐMJn
	key = "TWITTER_FRIENDSHIPS_DESTROY";
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

--- u@xxx ̃^CCvj[pnh
function on_show_friend_timeline(serialize_key, event_name, data)
	body = mz3_main_view.get_selected_body_item();
	body = MZ3Data:create(body);
	name = body:get_text('name');
	
	-- JeSǉ
	title = "@" .. name .. "̃^CC";
	url = "http://twitter.com/statuses/user_timeline/" .. name .. ".xml";
	key = "TWITTER_FRIENDS_TIMELINE";
	mz3_main_view.append_category(title, url, key);
	
	-- ǉJeS̎擾Jn
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

--- u@xxx ̃^CCv(tH[)j[pnh
function on_show_follower_tl_1(serialize_key, event_name, data)	show_follower_tl(1) end
function on_show_follower_tl_2(serialize_key, event_name, data)	show_follower_tl(2) end
function on_show_follower_tl_3(serialize_key, event_name, data)	show_follower_tl(3) end
function on_show_follower_tl_4(serialize_key, event_name, data)	show_follower_tl(4) end
function on_show_follower_tl_5(serialize_key, event_name, data)	show_follower_tl(5) end
function show_follower_tl(num)
	--  num Ԗڂ @xxx [U TL \
	name = follower_names[num];
	
	-- JeSǉ
	title = "@" .. name .. "̃^CC";
	url = "http://twitter.com/statuses/user_timeline/" .. name .. ".xml";
	key = "TWITTER_FRIENDS_TIMELINE";
	mz3_main_view.append_category(title, url, key);
	
	-- ǉJeS̎擾Jn
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

--- uReTweetvj[pnh
function on_retweet_menu_item(serialize_key, event_name, data)
	-- [hύX
	mz3_main_view.set_post_mode(MAIN_VIEW_POST_MODE_TWITTER_UPDATE);

	-- [hύXf({^̕ύX)
	mz3_main_view.update_control_status();

	-- GfBbgRg[ɕݒ
	data = mz3_main_view.get_selected_body_item();
	data = MZ3Data:create(data);
	text = "RT @" .. data:get_text('name') .. ": " .. data:get_text_array_joined_text('body');
	text = text:gsub("\r\n", "");
	mz3_main_view.set_edit_text(text);

	-- tH[JXړ
	mz3_main_view.set_focus('edit');
end

--- uz[vj[pnh
function on_open_home(serialize_key, event_name, data)

	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	
	mz3.open_url_by_browser_with_confirm("http://twitter.com/" .. body:get_text('name'));
end

--- uFB̂Cɓvj[pnh
function on_open_friend_favorites_by_browser(serialize_key, event_name, data)

	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	
	mz3.open_url_by_browser_with_confirm("http://twitter.com/" .. body:get_text('name') .. "/favorites");
end

--- uFB̃TCgvj[pnh
function on_open_friend_site(serialize_key, event_name, data)

	body = MZ3Data:create(mz3_main_view.get_selected_body_item());
	
	mz3.open_url_by_browser_with_confirm(body:get_text('url'));
end

--- uFB̂Cɓvj[pnh
function on_open_friend_favorites(serialize_key, event_name, data)

	body = mz3_main_view.get_selected_body_item();
	body = MZ3Data:create(body);
	name = body:get_text('name');
	
	-- JeSǉ
	title = "@" .. name .. "̂Cɓ";
	url = "http://twitter.com/favorites/" .. name .. ".xml";
	key = "TWITTER_FAVORITES";
	mz3_main_view.append_category(title, url, key);
	
	-- ǉJeS̎擾Jn
	access_type = mz3.get_access_type_by_key(key);
	referer = '';
	user_agent = nil;
	post = nil;
	mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
end

--- {fBXg̃_uNbN(܂Enter)̃Cxgnh
function on_body_list_click(serialize_key, event_name, data)
	if serialize_key=="TWITTER_USER" then
		-- S\
		return on_read_menu_item(serialize_key, event_name, data);
	end
	
	-- W̏𑱍s
	return false;
end

--- S\j[܂̓_uNbNCxg
function on_read_menu_item(serialize_key, event_name, data)
	mz3.logger_debug('on_read_menu_item : (' .. serialize_key .. ', ' .. event_name .. ')');
	data = MZ3Data:create(data);
--	mz3.logger_debug(data:get_text('name'));
	
	-- {1sɕϊĕ\
	item = data:get_text_array_joined_text('body');
	item = item:gsub("\r\n", "");
	
	item = item .. "\r\n";
	item = item .. "----\r\n";
	item = item .. "name : " .. data:get_text('name') .. " / " .. data:get_text('author') .. "\r\n";
	item = item .. "description : " .. data:get_text('title') .. "\r\n";
	item = item .. data:get_date() .. "\r\n";
--	item = item .. "id : " .. data:get_integer('id') .. "\r\n";
--	item = item .. "owner-id : " .. data:get_integer('owner_id') .. "\r\n";

	if data:get_text('location') ~= '' then
		item = item .. "location : " .. data:get_text('location') .. "\r\n";
	end
	
	if data:get_integer('friends_count') ~= -1 then
		item = item .. "followings : " .. data:get_integer('friends_count')
		            .. ", "
		            .. "followers : " .. data:get_integer('followers_count')
		            .. ", "
		            .. "fav : " .. data:get_integer('favourites_count')
		            .. ", "
		            .. " : " .. data:get_integer('statuses_count')
		            .. "\r\n";
	end
	
	-- \[X
	source = data:get_text('source');
--	item = item .. "source : " .. source .. "\r\n";
	s_url, s_name = source:match("href=\"(.*)\".*>(.*)<");
	if s_url ~= nil then
		item = item .. "source : " .. s_name .. " (" .. s_url .. ")\r\n";
	else
		item = item .. "source : " .. source .. "\r\n";
	end

	mz3.alert(item, data:get_text('name'));

	return true;
end

--- POST Cxg
--
-- @param event_name    'post_end'
-- @param serialize_key ڂ̃VACYL[
-- @param http_status   HTTP Status Code (200, 404, etc...)
-- @param wnd           wnd
--
function on_post_end(event_name, serialize_key, http_status)

	service_type = mz3.get_service_type(serialize_key);
	if service_type~="Twitter" then
		return false;
	end

	-- Twittere

	-- Xe[^XR[h`FbN
	msg = get_http_status_error_status(http_status);
	if msg ~= nil then
		-- G[AȂ̂Œf邽߂ true Ԃ
		mz3.logger_error(msg);
		mz3_main_view.set_info_text(msg);
		return true;
	end

	-- NGXg̎ʂɉăbZ[W\
	if serialize_key == "TWITTER_NEW_DM" then
		mz3_main_view.set_info_text("bZ[WMI");
	elseif serialize_key == "TWITTER_FAVOURINGS_CREATE" then
		mz3_main_view.set_info_text("ӂڂI");
	elseif serialize_key == "TWITTER_FAVOURINGS_DESTROY" then
		mz3_main_view.set_info_text("ӂڂ̂߂I");
	elseif serialize_key == "TWITTER_FRIENDSHIPS_CREATE" then
		mz3_main_view.set_info_text("tH[I");
	elseif serialize_key == "TWITTER_FRIENDSHIPS_DESTROY" then
		mz3_main_view.set_info_text("tH[߂I");
	else 
		-- TWITTER_UPDATE
		mz3_main_view.set_info_text("Xe[^XMI");
	end

	-- Wassr ւ̓e(NX|Xg)
--[[
	if serialize_key == "TWITTER_UPDATE" then

		text = mz3_main_view.get_edit_text();
		msg = "Wassr ɂe܂H\r\n";
		msg = msg .. "----\r\n";
		msg = msg .. text .. "\r\n";
		msg = msg .. "----\r\n";
		
		if mz3.confirm(msg, nil, "yes_no") == "yes" then
		
			-- URL 
			url = "http://api.wassr.jp/statuses/update.json";
			post = mz3_post_data.create();
			mz3_post_data.append_post_body(post, "status=");
			mz3_post_data.append_post_body(post, mz3.url_encode(text, 'utf8'));
			mz3_post_data.append_post_body(post, "&source=");
			mz3_post_data.append_post_body(post, mz3.get_app_name());
			
			-- ʐMJn
			access_type = mz3.get_access_type_by_key("WASSR_UPDATE");
			referer = '';
			user_agent = nil;
			mz3.open_url(mz3_main_view.get_wnd(), access_type, url, referer, "text", user_agent, post);
			return true;
		end
	end
]]

	-- ͒l
	mz3_main_view.set_edit_text("");
	
	return true;
end

--- GET Cxg
--
-- @param event_name    'get_end'
-- @param serialize_key ڂ̃VACYL[
-- @param http_status   HTTP Status Code (200, 404, etc...)
-- @param wnd           wnd
--
function on_get_end(event_name, serialize_key, http_status)

	service_type = mz3.get_service_type(serialize_key);
	if service_type~="Twitter" then
		return false;
	end

	-- Xe[^XR[h`FbN̂ݍs
	msg = get_http_status_error_status(http_status);
	if msg ~= nil then
		-- G[AȂ̂Œf邽߂ true Ԃ
		mz3.logger_error(msg);
		mz3_main_view.set_info_text(msg);
		mz3.alert("T[oG[(" .. http_status .. ") : " .. msg);
		return true;
	end
	-- G[ȂȂ̂ős(㑱̉͏p)

	return false;
end

--- {fBXg̃|bvAbvj[\
--
-- @param event_name    'popup_body_menu'
-- @param serialize_key {fBACẽVACYL[
-- @param body          body
-- @param wnd           wnd
--
function on_popup_body_menu(event_name, serialize_key, body, wnd)
	if serialize_key~="TWITTER_USER" then
		return false;
	end

	-- CX^X
	body = MZ3Data:create(body);
	
	-- j[
	menu = MZ3Menu:create_popup_menu();
	submenu = MZ3Menu:create_popup_menu();
	
	menu:append_menu("string", "ŐV̈ꗗ擾", IDM_CATEGORY_OPEN);
	menu:append_menu("string", "Sǂ...", menu_items.read);

	menu:append_menu("separator");

	menu:append_menu("string", "Ԃ₭", menu_items.update);

	name = body:get_text('name');

	menu:append_menu("string", "@" .. name .. " ɕԐM", menu_items.reply);
	menu:append_menu("string", "@" .. name .. " ɃbZ[WM", menu_items.new_dm);

	menu:append_menu("separator");

	menu:append_menu("string", "ReTweet...", menu_items.retweet);
	
	-- JeSutimelinev̂݁ACɓo^\
	category_access_type = mz3_main_view.get_selected_category_access_type();
	category_key = mz3.get_serialize_key_by_access_type(category_access_type);
	if category_key == "TWITTER_FRIENDS_TIMELINE" then
		menu:append_menu("string", "Cɓo^iӂڂj", menu_items.create_favourings);
	end
	
	-- JeSuCɓv̂݁ACɓ폜\
	if category_key == "TWITTER_FAVORITES" then
		menu:append_menu("string", "Cɓ폜", menu_items.destroy_favourings);
	end

	menu:append_menu("separator");

	menu:append_menu("string", "@" .. name .. " ̃^CC", menu_items.show_friend_timeline);
	
	--  @XXX 𒊏oAj[
	body_text = body:get_text_array_joined_text('body');
	i = 1;
	for f_name in body_text:gmatch("@([0-9a-zA-Z_]+)") do
		mz3.logger_debug(f_name);
		-- Lua ϐɖOۑĂ
		follower_names[i] = f_name;
		menu:append_menu("string", "@" .. f_name .. " ̃^CC", menu_items.show_follower_tl[i]);
		-- ő5l܂ŃT|[g
		i = i+1;
		if i>5 then
			break;
		end
	end

--	menu:append_menu("separator");
	
	submenu:append_menu("string", "@" .. name .. " tH[", menu_items.create_friendships);
	submenu:append_menu("string", "@" .. name .. " ̃tH[߂", menu_items.destroy_friendships);
	submenu:append_menu("string", "@" .. name .. " ̃z[uEUŊJ", menu_items.open_home);
	submenu:append_menu("string", "@" .. name .. " ̂CɓuEUŊJ", menu_items.open_friend_favorites_by_browser);
	submenu:append_menu("string", "@" .. name .. " ̂Cɓ", menu_items.open_friend_favorites);
	menu:append_submenu("̑", submenu);

	-- URL łȂ΁uTCgvǉ
	url = body:get_text('url');
	if url~=nil and url:len()>0 then
		submenu:append_menu("string", "@" .. name .. " ̃TCguEUŊJ", menu_items.open_friend_site);
	end

	-- Nǉ
	n = body:get_link_list_size();
	if n > 0 then
		menu:append_menu("separator");
		for i=0, n-1 do
			id = ID_REPORT_URL_BASE+(i+1);
			menu:append_menu("string", "link : " .. body:get_link_list_text(i), id);
		end
	end

	-- |bvAbv
	menu:popup(wnd);
	
	-- j[\[X폜
	menu:delete();
	submenu:delete();
	
	return true;
end

--- ftHg̃O[vXgCxgnh
--
-- @param serialize_key VACYL[(nil)
-- @param event_name    'creating_default_group'
-- @param group         MZ3GroupData
--
function on_creating_default_group(serialize_key, event_name, group)

	-- T|[gT[rXʂ̎擾(Xy[X؂)
	services = mz3_group_data.get_services(group);
	if services:find(' Twitter', 1, true) ~= nil then

		-- Twitter^uǉ
		local tab = MZ3GroupItem:create("Twitter");
		tab:append_category("^CC", "TWITTER_FRIENDS_TIMELINE", "http://twitter.com/statuses/friends_timeline.xml");
		tab:append_category("ԐMꗗ", "TWITTER_FRIENDS_TIMELINE", "http://twitter.com/statuses/replies.xml");
		tab:append_category("Cɓ", "TWITTER_FAVORITES", "http://twitter.com/favorites.xml");
		tab:append_category("MbZ[W", "TWITTER_DIRECT_MESSAGES", "http://twitter.com/direct_messages.xml");
		tab:append_category("MbZ[W", "TWITTER_DIRECT_MESSAGES", "http://twitter.com/direct_messages/sent.xml");
		mz3_group_data.append_tab(group, tab.item);
		tab:delete();
	end
end

----------------------------------------
-- Cxgnh̓o^
----------------------------------------

-- {fBXg̃_uNbN(܂Enter)Cxgnho^
mz3.add_event_listener("dblclk_body_list", "twitter.on_body_list_click");
mz3.add_event_listener("enter_body_list",  "twitter.on_body_list_click");

-- {fBXg̃|bvAbvj[\Cxgnho^
mz3.add_event_listener("popup_body_menu",  "twitter.on_popup_body_menu");

-- POSTCxgnho^
mz3.add_event_listener("post_end", "twitter.on_post_end");
mz3.add_event_listener("get_end",  "twitter.on_get_end");

-- ftHg̃O[vXg
mz3.add_event_listener("creating_default_group", "twitter.on_creating_default_group", false);

mz3.logger_debug('twitter.lua end');

{'fraction_non_alphanumeric': 0.18521513464720926, 'fraction_numerical': 0.011809839025124115, 'mean_word_length': 3.230132845437913, 'pattern_counts': {'":': 2, '<': 103, '<?xml version=': 0, '>': 111, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 26}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1525046', 'n_tokens_mistral': 23819, 'n_tokens_neox': 21779, 'n_words': 2966}