自分の変化

このコミットが含まれているのは:
テクニカル諏訪子 2021-08-10 07:17:39 +09:00
コミット a87e94b981
20個のファイルの変更98行の追加31行の削除

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 2.8 MiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 20 KiB

ファイルの表示

@ -17,12 +17,16 @@ CONFIG = Config.from_yaml(File.open("config/config.example.yml"))
describe "Helper" do
describe "#produce_channel_videos_url" do
it "correctly produces url for requesting page `x` of a channel's videos" do
#produce_channel_videos_url(ucid: "UCXuqSBlHAE6Xw-yeJA0Tunw").should eq("/browse_ajax?continuation=4qmFsgI8EhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaIEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0V4&gl=JP&hl=ja")
produce_channel_videos_url(ucid: "UCXuqSBlHAE6Xw-yeJA0Tunw").should eq("/browse_ajax?continuation=4qmFsgI8EhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaIEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0V4&gl=US&hl=en")
#produce_channel_videos_url(ucid: "UCXuqSBlHAE6Xw-yeJA0Tunw", sort_by: "popular").should eq("/browse_ajax?continuation=4qmFsgJAEhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaJEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0V4R0FFPQ%3D%3D&gl=JP&hl=ja")
produce_channel_videos_url(ucid: "UCXuqSBlHAE6Xw-yeJA0Tunw", sort_by: "popular").should eq("/browse_ajax?continuation=4qmFsgJAEhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaJEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0V4R0FFPQ%3D%3D&gl=US&hl=en")
#produce_channel_videos_url(ucid: "UCXuqSBlHAE6Xw-yeJA0Tunw", page: 20).should eq("/browse_ajax?continuation=4qmFsgJAEhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaJEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0l5TUE9PQ%3D%3D&gl=JP&hl=ja")
produce_channel_videos_url(ucid: "UCXuqSBlHAE6Xw-yeJA0Tunw", page: 20).should eq("/browse_ajax?continuation=4qmFsgJAEhhVQ1h1cVNCbEhBRTZYdy15ZUpBMFR1bncaJEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0l5TUE9PQ%3D%3D&gl=US&hl=en")
#produce_channel_videos_url(ucid: "UC-9-kyTW8ZkZNDHQJ6FgpwQ", page: 20, sort_by: "popular").should eq("/browse_ajax?continuation=4qmFsgJAEhhVQy05LWt5VFc4WmtaTkRIUUo2Rmdwd1EaJEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0l5TUJnQg%3D%3D&gl=JP&hl=ja")
produce_channel_videos_url(ucid: "UC-9-kyTW8ZkZNDHQJ6FgpwQ", page: 20, sort_by: "popular").should eq("/browse_ajax?continuation=4qmFsgJAEhhVQy05LWt5VFc4WmtaTkRIUUo2Rmdwd1EaJEVnWjJhV1JsYjNNd0FqZ0JZQUZxQUxnQkFDQUFlZ0l5TUJnQg%3D%3D&gl=US&hl=en")
end
end
@ -37,6 +41,7 @@ describe "Helper" do
describe "#produce_channel_playlists_url" do
it "correctly produces a /browse_ajax URL with the given UCID and cursor" do
produce_channel_playlists_url("UCCj956IF62FbT7Gouszaj9w", "AIOkY9EQpi_gyn1_QrFuZ1reN81_MMmI1YmlBblw8j7JHItEFG5h7qcJTNd4W9x5Quk_CVZ028gW").should eq("/browse_ajax?continuation=4qmFsgLNARIYVUNDajk1NklGNjJGYlQ3R291c3phajl3GrABRWdsd2JHRjViR2x6ZEhNd0FqZ0JZQUZxQUxnQkFIcG1VVlZzVUdFeGF6VlNWa1ozWVZZNWJtVlhOSGhZTVVaNVVtNVdZVTFZU214VWFtZDRXREF4VG1KVmEzaFhWekZ6VVcxS2MyUjZhSEZPTUhCSlUxaFNSbEpyWXpGaFJHUjRXVEJ3VlZSdFVUQldlbXcwVGxaR01XRXhPVVJXYkc5M1RXcG9ibFozSUFFWUF3PT0%3D&gl=JP&hl=ja")
produce_channel_playlists_url("UCCj956IF62FbT7Gouszaj9w", "AIOkY9EQpi_gyn1_QrFuZ1reN81_MMmI1YmlBblw8j7JHItEFG5h7qcJTNd4W9x5Quk_CVZ028gW").should eq("/browse_ajax?continuation=4qmFsgLNARIYVUNDajk1NklGNjJGYlQ3R291c3phajl3GrABRWdsd2JHRjViR2x6ZEhNd0FqZ0JZQUZxQUxnQkFIcG1VVlZzVUdFeGF6VlNWa1ozWVZZNWJtVlhOSGhZTVVaNVVtNVdZVTFZU214VWFtZDRXREF4VG1KVmEzaFhWekZ6VVcxS2MyUjZhSEZPTUhCSlUxaFNSbEpyWXpGaFJHUjRXVEJ3VlZSdFVUQldlbXcwVGxaR01XRXhPVVJXYkc5M1RXcG9ibFozSUFFWUF3PT0%3D&gl=US&hl=en")
end
end

ファイルの表示

@ -813,7 +813,8 @@ post "/data_control" do |env|
if match = channel["url"].as_s.match(/\/channel\/(?<channel>UC[a-zA-Z0-9_-]{22})/)
next match["channel"]
elsif match = channel["url"].as_s.match(/\/user\/(?<user>.+)/)
response = YT_POOL.client &.get("/user/#{match["user"]}?disable_polymer=1&hl=en&gl=US")
response = YT_POOL.client &.get("/user/#{match["user"]}?disable_polymer=1&hl=ja&gl=JP")
#response = YT_POOL.client &.get("/user/#{match["user"]}?disable_polymer=1&hl=en&gl=US")
html = XML.parse_html(response.body)
ucid = html.xpath_node(%q(//link[@rel="canonical"])).try &.["href"].split("/")[-1]
next ucid if ucid
@ -1210,7 +1211,8 @@ get "/feed/trending" do |env|
trending_type ||= "Default"
region = env.params.query["region"]?
region ||= "US"
region ||= "JP"
#region ||= "US"
begin
trending, plid = fetch_trending(trending_type, region, locale)
@ -1347,7 +1349,8 @@ get "/feed/channel/:ucid" do |env|
XML.build(indent: " ", encoding: "UTF-8") do |xml|
xml.element("feed", "xmlns:yt": "http://www.youtube.com/xml/schemas/2015",
"xmlns:media": "http://search.yahoo.com/mrss/", xmlns: "http://www.w3.org/2005/Atom",
"xml:lang": "en-US") do
"xml:lang": "ja-JP") do
#"xml:lang": "en-US") do
xml.element("link", rel: "self", href: "#{HOST_URL}#{env.request.resource}")
xml.element("id") { xml.text "yt:channel:#{channel.ucid}" }
xml.element("yt:channelId") { xml.text channel.ucid }
@ -1399,7 +1402,8 @@ get "/feed/private" do |env|
XML.build(indent: " ", encoding: "UTF-8") do |xml|
xml.element("feed", "xmlns:yt": "http://www.youtube.com/xml/schemas/2015",
"xmlns:media": "http://search.yahoo.com/mrss/", xmlns: "http://www.w3.org/2005/Atom",
"xml:lang": "en-US") do
"xml:lang": "ja-JP") do
#"xml:lang": "en-US") do
xml.element("link", "type": "text/html", rel: "alternate", href: "#{HOST_URL}/feed/subscriptions")
xml.element("link", "type": "application/atom+xml", rel: "self",
href: "#{HOST_URL}#{env.request.resource}")
@ -1429,7 +1433,8 @@ get "/feed/playlist/:plid" do |env|
next XML.build(indent: " ", encoding: "UTF-8") do |xml|
xml.element("feed", "xmlns:yt": "http://www.youtube.com/xml/schemas/2015",
"xmlns:media": "http://search.yahoo.com/mrss/", xmlns: "http://www.w3.org/2005/Atom",
"xml:lang": "en-US") do
"xml:lang": "ja-JP") do
#"xml:lang": "en-US") do
xml.element("link", rel: "self", href: "#{HOST_URL}#{env.request.resource}")
xml.element("id") { xml.text "iv:playlist:#{plid}" }
xml.element("iv:playlistId") { xml.text plid }

ファイルの表示

@ -29,8 +29,10 @@ struct AboutRelatedChannel
end
def get_about_info(ucid, locale)
#result = YT_POOL.client &.get("/channel/#{ucid}/about?gl=JP&hl=ja")
result = YT_POOL.client &.get("/channel/#{ucid}/about?gl=US&hl=en")
if result.status_code != 200
#result = YT_POOL.client &.get("/user/#{ucid}/about?gl=JP&hl=ja")
result = YT_POOL.client &.get("/user/#{ucid}/about?gl=US&hl=en")
end

ファイルの表示

@ -1,8 +1,10 @@
# TODO: Add "sort_by"
def fetch_channel_community(ucid, continuation, locale, format, thin_mode)
response = YT_POOL.client &.get("/channel/#{ucid}/community?gl=US&hl=en")
response = YT_POOL.client &.get("/channel/#{ucid}/community?gl=JP&hl=ja")
#response = YT_POOL.client &.get("/channel/#{ucid}/community?gl=US&hl=en")
if response.status_code != 200
response = YT_POOL.client &.get("/user/#{ucid}/community?gl=US&hl=en")
response = YT_POOL.client &.get("/user/#{ucid}/community?gl=JP&hl=ja")
#response = YT_POOL.client &.get("/user/#{ucid}/community?gl=US&hl=en")
end
if response.status_code != 200
@ -31,7 +33,8 @@ def fetch_channel_community(ucid, continuation, locale, format, thin_mode)
session_token: session_token,
}
response = YT_POOL.client &.post("/comment_service_ajax?action_get_comments=1&ctoken=#{continuation}&continuation=#{continuation}&hl=en&gl=US", headers, form: post_req)
response = YT_POOL.client &.post("/comment_service_ajax?action_get_comments=1&ctoken=#{continuation}&continuation=#{continuation}&hl=ja&gl=JP", headers, form: post_req)
#response = YT_POOL.client &.post("/comment_service_ajax?action_get_comments=1&ctoken=#{continuation}&continuation=#{continuation}&hl=en&gl=US", headers, form: post_req)
body = JSON.parse(response.body)
body = body["response"]["continuationContents"]["itemSectionContinuation"]? ||

ファイルの表示

@ -89,5 +89,6 @@ def produce_channel_playlists_url(ucid, cursor, sort = "newest", auto_generated
.try { |i| Base64.urlsafe_encode(i) }
.try { |i| URI.encode_www_form(i) }
#return "/browse_ajax?continuation=#{continuation}&gl=JP&hl=ja"
return "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
end

ファイルの表示

@ -85,5 +85,5 @@ end
# Used in bypass_captcha_job.cr
def produce_channel_videos_url(ucid, page = 1, auto_generated = nil, sort_by = "newest", v2 = false)
continuation = produce_channel_videos_continuation(ucid, page, auto_generated, sort_by, v2)
return "/browse_ajax?continuation=#{continuation}&gl=US&hl=en"
return "/browse_ajax?continuation=#{continuation}&gl=JP&hl=ja"
end

ファイルの表示

@ -88,6 +88,7 @@ def fetch_youtube_comments(id, db, cursor, format, locale, thin_mode, region, so
"cookie" => video.cookie,
}
#response = YT_POOL.client(region, &.post("/comment_service_ajax?#{action}=1&hl=ja&gl=JP&pbj=1", headers, form: post_req))
response = YT_POOL.client(region, &.post("/comment_service_ajax?#{action}=1&hl=en&gl=US&pbj=1", headers, form: post_req))
response = JSON.parse(response.body)

ファイルの表示

@ -36,6 +36,7 @@ struct ConfigPreferences
property latest_only : Bool = false
property listen : Bool = false
property local : Bool = false
#property locale : String = "ja-JP"
property locale : String = "en-US"
property max_results : Int32 = 40
property notifications_only : Bool = false
@ -219,6 +220,8 @@ def login_req(f_req)
"pstMsg" => "1",
"checkConnection" => "youtube",
"checkedDomains" => "youtube",
#"hl" => "ja",
#"deviceinfo" => %|[null,null,null,[],null,"JP",null,null,[],"GlifWebSignIn",null,[null,null,[]]]|,
"hl" => "en",
"deviceinfo" => %|[null,null,null,[],null,"US",null,null,[],"GlifWebSignIn",null,[null,null,[]]]|,
"f.req" => f_req,

ファイルの表示

@ -92,7 +92,7 @@ class HTTPClient < HTTP::Client
end
end
def get_proxies(country_code = "US")
def get_proxies(country_code = "JP")
# return get_spys_proxies(country_code)
return get_nova_proxies(country_code)
end
@ -119,7 +119,7 @@ def filter_proxies(proxies)
return proxies
end
def get_nova_proxies(country_code = "US")
def get_nova_proxies(country_code = "JP")
country_code = country_code.downcase
client = HTTP::Client.new(URI.parse("https://www.proxynova.com"))
client.read_timeout = 10.seconds
@ -128,7 +128,7 @@ def get_nova_proxies(country_code = "US")
headers = HTTP::Headers.new
headers["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
headers["Accept-Language"] = "Accept-Language: en-US,en;q=0.9"
headers["Accept-Language"] = "Accept-Language: ja-JP,ja;q=0.9"
headers["Host"] = "www.proxynova.com"
headers["Origin"] = "https://www.proxynova.com"
headers["Referer"] = "https://www.proxynova.com/proxy-server-list/country-#{country_code}/"
@ -158,7 +158,7 @@ def get_nova_proxies(country_code = "US")
return proxies
end
def get_spys_proxies(country_code = "US")
def get_spys_proxies(country_code = "JP")
client = HTTP::Client.new(URI.parse("http://spys.one"))
client.read_timeout = 10.seconds
client.connect_timeout = 10.seconds
@ -166,7 +166,7 @@ def get_spys_proxies(country_code = "US")
headers = HTTP::Headers.new
headers["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
headers["Accept-Language"] = "Accept-Language: en-US,en;q=0.9"
headers["Accept-Language"] = "Accept-Language: ja-JP,ja;q=0.9"
headers["Host"] = "spys.one"
headers["Origin"] = "http://spys.one"
headers["Referer"] = "http://spys.one/free-proxy-list/#{country_code}/"

ファイルの表示

@ -12,8 +12,8 @@ struct DecryptFunction
end
private def fetch_decrypt_function(id = "CvFH_6DNRCY")
document = YT_POOL.client &.get("/watch?v=#{id}&gl=US&hl=en").body
url = document.match(/src="(?<url>\/s\/player\/[^\/]+\/player_ias[^\/]+\/en_US\/base.js)"/).not_nil!["url"]
document = YT_POOL.client &.get("/watch?v=#{id}&gl=JP&hl=ja").body
url = document.match(/src="(?<url>\/s\/player\/[^\/]+\/player_ias[^\/]+\/ja_JP\/base.js)"/).not_nil!["url"]
player = YT_POOL.client &.get(url).body
function_name = player.match(/^(?<name>[^=]+)=function\(\w\){\w=\w\.split\(""\);[^\. ]+\.[^( ]+/m).not_nil!["name"]

ファイルの表示

@ -72,7 +72,7 @@ module YoutubeAPI
#
# ```
# # Get Norwegian search results
# conf_1 = ClientConfig.new(region: "NO")
# conf_1 = ClientConfig.new(region: "JP")
# YoutubeAPI::search("Kollektivet", params: "", client_config: conf_1)
#
# # Use the Android client to request video streams URLs
@ -80,7 +80,7 @@ module YoutubeAPI
# YoutubeAPI::player(video_id: "dQw4w9WgXcQ", client_config: conf_2)
#
# # Proxy request through russian proxies
# conf_3 = ClientConfig.new(proxy_region: "RU")
# conf_3 = ClientConfig.new(proxy_region: "JP")
# YoutubeAPI::next({video_id: "dQw4w9WgXcQ"}, client_config: conf_3)
# ```
#
@ -101,7 +101,7 @@ module YoutubeAPI
def initialize(
*,
@client_type = ClientType::Web,
@region = "US",
@region = "JP",
@proxy_region = nil
)
end
@ -153,7 +153,7 @@ module YoutubeAPI
client_context = {
"client" => {
"hl" => "en",
"gl" => client_config.region || "US", # Can't be empty!
"gl" => "JP", #client_config.region || "JP", # Can't be empty!
"clientName" => client_config.name,
"clientVersion" => client_config.version,
"thirdParty" => {

ファイルの表示

@ -6,7 +6,7 @@ class Invidious::Jobs::BypassCaptchaJob < Invidious::Jobs::BaseJob
if !random_video
random_video = {id: "zj82_v2R6ts", ucid: "UCK87Lox575O_HCHBWaBSyGA"}
end
{"/watch?v=#{random_video["id"]}&gl=US&hl=en&has_verified=1&bpctr=9999999999", produce_channel_videos_url(ucid: random_video["ucid"])}.each do |path|
{"/watch?v=#{random_video["id"]}&gl=JP&hl=ja&has_verified=1&bpctr=9999999999", produce_channel_videos_url(ucid: random_video["ucid"])}.each do |path|
response = YT_POOL.client &.get(path)
if response.body.includes?("To continue with your YouTube experience, please fill out the form below.")
html = XML.parse_html(response.body)

ファイルの表示

@ -26,7 +26,7 @@ def fetch_mix(rdid, video_id, cookies = nil, locale = nil)
end
video_id = "CvFH_6DNRCY" if rdid.starts_with? "OLAK5uy_"
response = YT_POOL.client &.get("/watch?v=#{video_id}&list=#{rdid}&gl=US&hl=en", headers)
response = YT_POOL.client &.get("/watch?v=#{video_id}&list=#{rdid}&gl=JP&hl=ja", headers)
initial_data = extract_initial_data(response.body)
if !initial_data["contents"]["twoColumnWatchNextResults"]["playlist"]?

ファイルの表示

@ -58,6 +58,7 @@ class Invidious::Routes::Login < Invidious::Routes::BaseRoute
headers = login_page.cookies.add_request_headers(headers)
lookup_req = {
#email, nil, [] of String, nil, "JP", nil, nil, 2, false, true,
email, nil, [] of String, nil, "US", nil, nil, 2, false, true,
{nil, nil,
{2, 1, nil, 1,

ファイルの表示

@ -1,4 +1,5 @@
def fetch_trending(trending_type, region, locale)
#region ||= "JP"
region ||= "US"
region = region.upcase

ファイルの表示

@ -968,6 +968,7 @@ def get_video(id, db, refresh = true, region = nil, force_refresh = false)
end
def fetch_video(id, region)
#response = YT_POOL.client(region, &.get("/watch?v=#{id}&gl=JP&hl=ja&has_verified=1&bpctr=9999999999"))
response = YT_POOL.client(region, &.get("/watch?v=#{id}&gl=US&hl=en&has_verified=1&bpctr=9999999999"))
if md = response.headers["location"]?.try &.match(/v=(?<id>[a-zA-Z0-9_-]{11})/)
@ -983,6 +984,7 @@ def fetch_video(id, region)
bypass_regions = PROXY_LIST.keys & allowed_regions
if !bypass_regions.empty?
region = bypass_regions[rand(bypass_regions.size)]
#response = YT_POOL.client(region, &.get("/watch?v=#{id}&gl=JP&hl=ja&has_verified=1&bpctr=9999999999"))
response = YT_POOL.client(region, &.get("/watch?v=#{id}&gl=US&hl=en&has_verified=1&bpctr=9999999999"))
region_info = extract_polymer_config(response.body)
@ -998,6 +1000,8 @@ def fetch_video(id, region)
"video_id" => id,
"eurl" => "https://youtube.googleapis.com/v/#{id}",
"html5" => "1",
#"gl" => "JP",
#"hl" => "ja",
"gl" => "US",
"hl" => "en",
}

ファイルの表示

@ -34,7 +34,7 @@
<li>how long it took to complete the request.</li>
</ul>
<p>No identifying information is logged, such as the visitor's cookie, user-agent, or IP address. Here are a couple lines to serve as an example:</p>
<pre><code>2019-01-19 16:37:47 +00:00 200 GET /api/v1/comments/xrlETJYzH-c?format=html&hl=en-US 1345.88ms
<pre><code>2019-01-19 16:37:47 +00:00 200 GET /api/v1/comments/xrlETJYzH-c?format=html&hl=ja-JP 1345.88ms
2019-01-19 16:37:53 +00:00 200 GET /vi/r5P-f5arPXE/maxres.jpg 1085.41ms
2019-01-19 16:37:54 +00:00 200 GET /watch 7.04ms</code></pre>
<p>This website does not store the visitor's user-agent or IP address and does not use fingerprinting, advertisements, or tracking of any form.</p>

ファイルの表示

@ -17,6 +17,45 @@
<link rel="stylesheet" href="/css/grids-responsive-min.css?v=<%= ASSET_COMMIT %>">
<link rel="stylesheet" href="/css/ionicons.min.css?v=<%= ASSET_COMMIT %>">
<link rel="stylesheet" href="/css/default.css?v=<%= ASSET_COMMIT %>">
<style>
body {
background-image: url('/861c6291044c997464bdaa59cde2f226a5216a3ac8f7c1329ccbf59fc6243b2f.png');
background-attachment: fixed;
}
.bgcon {
background-size: cover;
backdrop-filter: blur(17px);
color: #fcfcfc;
background-color: rgba(160,0,255,.5);
margin: 8px;
border: 4px solid #ff00ff;
border-radius: 4px;
}
.bgnav {
margin: 0 0 8px 0;
padding: 8px 16px 4px 16px;
}
.bgtit {
margin: 0 16px 16px 16px;
border-radius: 4px;
}
.bgmain {
margin: 0 4px;
padding: 0 8px;
border-radius: 4px;
margin-bottom: 12px;
}
.bgippan {
background-color: rgba(0,0,0,.4);
}
.dark-theme a {
color: #e599e5 !important;
}
footer a {
color: #e599e5 !important;
}
</style>
</head>
<% locale = LOCALES[env.get("preferences").as(Preferences).locale]? %>
@ -26,11 +65,11 @@
<span style="display:none" id="dark_mode_pref"><%= env.get("preferences").as(Preferences).dark_mode %></span>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-2-24"></div>
<div class="pure-u-1 pure-u-md-20-24" id="contents">
<div class="pure-g navbar h-box">
<div class="pure-u-1 pure-u-md-20-24 bgcon" id="contents">
<div class="pure-g navbar h-box bgippan bgnav">
<% if navbar_search %>
<div class="pure-u-1 pure-u-md-4-24">
<a href="/" class="index-link pure-menu-heading">Invidious</a>
<a href="/" class="index-link pure-menu-heading"><img src="/fcb595df6b09edabcc108e4b518df5f7c4e763d4c5ebdaf3b4640a3d8ecdc9b3.png" /></a>
</div>
<div class="pure-u-1 pure-u-md-12-24 searchbar">
<form class="pure-form" action="/search" method="get">
@ -112,9 +151,11 @@
</div>
<% end %>
<%= content %>
<div class="bgippan">
<%= content %>
</div>
<footer>
<footer class="bgippan bgfoot">
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-3">
<a href="https://github.com/iv-org/invidious">
@ -123,11 +164,11 @@
</div>
<div class="pure-u-1 pure-u-md-1-3">
<i class="icon ion-ios-wallet"></i>
BTC: <a href="bitcoin:bc1qfhe7rq3lqzuayzjxzyt9waz9ytrs09kla3tsgr">bc1qfhe7rq3lqzuayzjxzyt9waz9ytrs09kla3tsgr</a>
XMR: <a href="monero:436RmujnMVT834WXCUYoHcCWQBFnmDthxXYkxiwR8qVwBS7P84CjVwGUumvALfUcWDCNUKHFkJhSvPUQpkBtDk2zH9LSg7C">436RmujnMVT834WXCUYoHcCWQBFnmDthxXYkxiwR8qVwBS7P84CjVwGUumvALfUcWDCNUKHFkJhSvPUQpkBtDk2zH9LSg7C</a>
</div>
<div class="pure-u-1 pure-u-md-1-3">
<i class="icon ion-ios-wallet"></i>
XMR: <a href="monero:41nMCtek197boJtiUvGnTFYMatrLEpnpkQDmUECqx5Es2uX3sTKKWVhSL76suXsG3LXqkEJBrCZBgPTwJrDp1FrZJfycGPR">Click here</a>
<i class="icon ion-ios-person-circle"></i>
<a href="https://www.technicalsuwako.jp">テクニカル諏訪子</a>
</div>
<div class="pure-u-1 pure-u-md-1-3">
<a href="https://github.com/iv-org/documentation">Documentation</a>