Skip to content

Instantly share code, notes, and snippets.

@skoji
Last active January 2, 2018 12:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skoji/2e79d9f2d9a4a4dbaa7d17495234a791 to your computer and use it in GitHub Desktop.
Save skoji/2e79d9f2d9a4a4dbaa7d17495234a791 to your computer and use it in GitHub Desktop.
userlocalのMastodonリアルタイム検索に頼ってhashtag検索結果をHTMLにする
require 'open-uri'
require 'json'
require 'nokogiri'
require 'uri'
raise 'should specify keyword' if ARGV.size < 1
keyword = ARGV[0]
title = keyword
title = ARGV[1] if ARGV.size >= 2
uri = 'http://realtime.userlocal.jp/toots/index?q=' + URI.encode('#' + keyword)
charset = nil
html = open uri do |f|
charset = f.charset
f.read
end
doc = Nokogiri::HTML.parse(html, nil, charset)
domains = doc.css('.user_name').map do |n|
URI.split(n.css('a')[0].attribute('href'))[2]
end
toots = []
domains.uniq.each do |d|
toots += JSON.parse open("https://#{d}/api/v1/timelines/tag/#{URI.encode(keyword)}").read
end
toots.sort_by! do |t|
DateTime.parse t['created_at']
end.uniq! do |t|
t['url']
end
puts <<EOF
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<title>#{title}</title>
<link rel='stylesheet' href='mastodon-toots.css' />
</head>
<body>
<h1>#{title}</h1>
EOF
toots.each do |t|
domain = URI.split(t["url"])[2]
user_link = "https://#{domain}/@#{t['account']['username']}"
puts "<section class='toot'>\n"
puts "<div class='toot-head'>\n"
puts "<span class='avatar'><img width='48' height='48' class='avatar' src='#{t["account"]["avatar"]}' /></span>"
puts "<a class='display-name' href='#{user_link}'>"
puts "#{t['account']['display_name']}"
puts "</a>"
puts "<a class='account-name' href='#{user_link}'>"
puts "@#{t['account']['username']}@#{domain}"
puts "</a>"
puts "</div>\n"
puts "<div class='toot-body'>\n"
puts t['content']
puts "</div>\n"
puts "<div class='toot-foot'>"
puts "<a href='#{t['url']}'>"
puts DateTime.parse(t['created_at']).strftime('%Y年%m月%d日 %H:%M')
puts "</a></div>\n"
puts "</section>\n"
end
puts '</body></html>'
@font-face {
font-family: "Yu Gothic";
src: local("Yu Gothic Medium");
font-weight: 100;
}
@font-face {
font-family: "Yu Gothic";
src: local("Yu Gothic Medium");
font-weight: 200;
}
@font-face {
font-family: "Yu Gothic";
src: local("Yu Gothic Medium");
font-weight: 300;
}
@font-face {
font-family: "Yu Gothic";
src: local("Yu Gothic Medium");
font-weight: 400;
}
@font-face {
font-family: "Yu Gothic";
src: local("Yu Gothic Bold");
font-weight: bold;
}
body {
line-height: 1.8;
font-family: "Yu Gothic", YuGothic, sans-serif;
font-size: 12pt;
color: #020202;
background-color: #f0f0f0;
}
a {
text-decoration: none;
color: #0000ff;
}
a:visited {
color: #0000ff;
}
a:hover {
text-decoration: underline;
}
h1 {
font-size: 16pt;
max-width: 400px;
text-align: center;
margin: 0.5em auto;
}
.toot {
background-color: #fefefe;
max-width: 400px;
margin: 0.5em auto;
padding: 0.5em;
border: 1px solid #888888;
border-radius: 0.5em;
}
.toot-head {
display: grid;
white-space: nowrap;
grid-template-columns: 60px 1fr;
grid-template-rows: 24px 24px;
}
.toot-head a {
color: #000000;
}
.toot-head a:visited {
color: #000000;
}
.toot-head > .display-name {
grid-column: 2;
grid-row: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.toot-head > .account-name {
grid-column: 2;
grid-row: 2;
font-size: 10pt;
color: #808080;
}
.invisible {
display: none;
}
.ellipsis::after {
content: "...";
}
.toot-foot {
font-size: 10pt;
color: #808080;
}
.toot-foot a {
color: #808080;
}
.toot-foot a:visited {
color: #808080;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment