1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
# -*- coding: utf-8 -*-
miquire :core, "miquire", "plugin"
# プラグインのロードに関すること
module Miquire::Plugin
class << self
include Enumerable
# ロードパスの配列を返す。
# ロードパスに追加したい場合は、以下のようにすればいい
#
# Miquire::Plugin.loadpath << 'pathA' << 'pathB'
def loadpath
@loadpath ||= [] end
# プラグインのファイル名(フルパス)で繰り返す。
def each
iterated = Set.new
detected = []
loadpath.reverse.each { |path|
Dir[File.join(File.expand_path(path), '*')].each { |file|
if FileTest.directory?(file) and FileTest.exist?(File.join(file, File.basename(file))+'.rb')
file = File.join(file, File.basename(file))+'.rb'
elsif not file.end_with?('.rb'.freeze)
next end
plugin_name = File.basename(file, '.rb')
if not iterated.include? plugin_name
iterated << plugin_name
detected << file end } }
detected.sort_by{ |a|
[:bundle == get_kind(a) ? 0 : 1, a]
}.each(&Proc.new) end
def each_spec
each{ |path|
spec = get_spec path
yield spec if spec } end
def to_hash
result = {}
each_spec{ |spec|
result[spec[:slug]] = spec }
result end
# 受け取ったパスにあるプラグインのスラッグを返す
# ==== Args
# [path] パス(String)
# ==== Return
# プラグインスラッグ(Symbol)
def get_slug(path)
type_strict path => String
spec = get_spec(path)
if spec
spec[:slug]
else
File.basename(path, ".rb").to_sym end end
# specファイルがあればそれを返す
# ==== Args
# [path] パス(String)
# ==== Return
# specファイルの内容か、存在しなければnil
def get_spec(path)
type_strict path => String
plugin_dir = FileTest.directory?(path) ? path : File.dirname(path)
spec_filename = File.join(plugin_dir, ".mikutter.yml")
deprecated_spec = false
unless FileTest.exist? spec_filename
spec_filename = File.join(plugin_dir, "spec")
deprecated_spec = true end
if FileTest.exist? spec_filename
YAML.load_file(spec_filename).symbolize
.merge(kind: get_kind(path),
path: plugin_dir,
deprecated_spec: deprecated_spec)
elsif FileTest.exist? path
{ slug: File.basename(path, ".rb").to_sym,
kind: get_kind(path),
path: plugin_dir,
deprecated_spec: false } end end
def get_spec_by_slug(slug)
type_strict slug => Symbol
to_hash[slug] end
# プラグインがthirdpartyかbundleかを返す
def get_kind(path)
type_strict path => String
if path.start_with?(Environment::PLUGIN_PATH)
:bundle
else
:thirdparty end end
def load_all
each_spec{ |spec|
begin
load spec
rescue Miquire::LoadError => e
::Plugin.call(:modify_activity,
kind: "system",
title: "#{spec[:slug]} load failed",
date: Time.new,
exception: e,
description: e.to_s) end } end
def load(spec)
type_strict spec => tcor(Hash, Symbol, String)
case spec
when Symbol, String
spec = spec.to_sym
if ::Plugin.instance_exist?(spec)
return true end
spec = get_spec_by_slug(spec)
if not spec
return false end
else
if ::Plugin.instance_exist?(spec[:slug])
return true end end
if defined?(spec[:depends][:mikutter]) and spec[:depends][:mikutter]
version = Environment::Version.new(*(spec[:depends][:mikutter].split(".").map(&:to_i) + ([0]*4))[0...4])
if Environment::VERSION < version
raise Miquire::LoadError, "plugin #{spec[:slug]}: #{Environment::NAME} version too old (#{spec[:depends][:mikutter]} required, but #{Environment::NAME} version is #{Environment::VERSION})"
return false end end
if defined? spec[:depends][:plugin]
spec[:depends][:plugin].map(&:to_sym).each{ |depended_plugin_slug|
begin
::Plugin.instance_exist?(depended_plugin_slug) or
load(depended_plugin_slug) or
raise Miquire::LoadError
rescue Miquire::LoadError
raise Miquire::LoadError, "plugin #{spec[:slug]}: dependency error: plugin #{depended_plugin_slug} was not loaded." end } end
notice "plugin loaded: " + File.join(spec[:path], "#{spec[:slug]}.rb")
::Plugin.create(spec[:slug].to_sym) do
self.spec = spec end
Kernel.load File.join(spec[:path], "#{spec[:slug]}.rb")
if spec[:deprecated_spec]
title = "#{spec[:slug]}: specファイルは非推奨になりました。"
Plugin.call(:modify_activity,
{ plugin: spec[:slug],
kind: "error",
title: title,
date: Time.now,
spec: spec,
description: "#{title}\n代わりに.mikutter.ymlを使ってください。"}) end
true end
end
end
|