Advertisement
Guest User

Untitled

a guest
Jul 30th, 2017
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.79 KB | None | 0 0
  1. STDOUT.sync = true
  2.  
  3. module Enumerable
  4. def none?
  5. if block_given?
  6. not self.any? { |e| yield e }
  7. else
  8. not self.any?
  9. end
  10. end
  11. end
  12.  
  13. module Og
  14. module EntityMixin
  15. class_extension do
  16. def find_or_create_with params
  17. unless obj = self.query_by_example(params).first
  18. obj = self.create_with(params)
  19. end
  20. return obj
  21. end
  22. end
  23. end
  24. end
  25.  
  26. class Object
  27. def to_numeric
  28. Integer(self) rescue Float(self) rescue self
  29. end
  30.  
  31. def numeric?
  32. to_numeric == self
  33. end
  34. end
  35.  
  36. class Contact
  37. property :name, String
  38. property :address, String
  39.  
  40. belongs_to ContactBook
  41. belongs_to User
  42. end
  43.  
  44. class ContactBook
  45. include Og::EntityMixin
  46. property :name, String
  47.  
  48. belongs_to User
  49. has_many Contact
  50. end
  51.  
  52. class User
  53. property :name, String
  54. property :email, String
  55. property :login, String
  56. property :password, String
  57.  
  58. has_many ContactBook
  59. has_many Contact
  60.  
  61. def password
  62. @password
  63. end
  64.  
  65. def password=(pwd)
  66. @password = self.class.encode_password pwd
  67. end
  68.  
  69. def self.encode_password pwd
  70. Digest::SHA1.hexdigest(pwd)
  71. end
  72. end
  73.  
  74. class Numeric
  75. def even?
  76. self % 2 == 0
  77. end
  78.  
  79. def odd?
  80. !even?
  81. end
  82. end
  83.  
  84. class Array
  85. def to_hash
  86. Hash[*(self.map{|k,v| [k,v]}.flatten)]
  87. end
  88. end
  89.  
  90. module NIMAP
  91. class Envelope
  92. def initialize uid
  93. #TODO: make sure that the @@cache works over different sessions
  94. @@cache ||= {}
  95. envelope uid.to_i
  96. end
  97.  
  98. def envelope uid = (@envelope.uid rescue nil)
  99. if uid
  100. unless @envelope || @envelope = @@cache[uid]
  101. @envelope = OpenStruct.new
  102. Server.fetch_envelope(uid).each_pair do |key, val|
  103. if val.respond_to? :to_ary
  104. node = OpenStruct.new
  105. val.first.each_pair do |nkey, nval|
  106. node.send("#{nkey}=", (nval ? Kconv.toutf8(nval.to_s) : nil))
  107. end
  108. @envelope.send("#{key}=", node)
  109. else
  110. @envelope.send("#{key}=", (val ? Kconv.toutf8(val.to_s) : nil))
  111. end
  112. end
  113. @envelope.from.address = "#{@envelope.from.mailbox}@#{@envelope.from.host}".downcase
  114. @envelope.date = Time.parse(@envelope.date)
  115. @envelope.uid = uid
  116. return false if @@cache.include?(@envelope)
  117. @@cache[uid] = @envelope
  118. Thread.new do
  119. fetch_parts
  120. end
  121. end
  122. return @envelope
  123. end
  124. end
  125.  
  126. def uid; envelope.uid end
  127. def subject; envelope.subject end
  128. def date; envelope.date end
  129. def from; envelope.from end
  130. def to; envelope.to end
  131.  
  132. def body
  133. Server.fetch(uid, "BODY")
  134. end
  135.  
  136. def ==(other)
  137. return false unless other.is_a?(self.class)
  138. # note that little ! here
  139. result = [
  140. :subject, :date, :from, :to
  141. ].all?{ |e|
  142. other.send(e) == self.send(e)
  143. }
  144. result
  145. end
  146.  
  147. def fetch_parts
  148. starter = ['TEXT', 0]
  149. content = true
  150. while content
  151. current = starter.shift
  152. content = body_part(current)
  153. p content
  154. starter << current.succ
  155. end
  156. end
  157.  
  158. def body_part part = 'TEXT'
  159. body = (envelope.body ||= {})
  160. begin
  161. envelope.body[part] ||= Server.fetch(uid, "BODY[#{part}]")
  162. rescue Net::IMAP::NoResponseError
  163. return false
  164. end
  165. end
  166.  
  167. def text
  168. text = body_part 1
  169. text = body_part if text.empty?
  170. text = body_part 2 if text.empty?
  171. #text = NKF.nkf("-s", Net::IMAP.decode_utf7(text.to_s))
  172. text = Kconv.toutf8(text)
  173. {
  174. "=20\r\n" => "\n"
  175. }.each do |pattern, replacement|
  176. text.gsub!(pattern, replacement)
  177. end
  178. ["\r\n", "\n\r", "\n", "<br /><br />"].each{|n| text.gsub!(n, "<br />")}
  179. uris = URI.extract(text)
  180. uris = uris.map{|u| URI.parse(u).to_s rescue nil}.compact.uniq
  181. uris.each{|u| text.gsub!(u, %{<a href="#{u}">#{u}</a>}) }
  182. return text
  183. end
  184.  
  185. def multipart_extract struct
  186. extracted = []
  187. if struct.respond_to? :parts
  188. extracted << struct.parts.map{|part| multipart_extract(part)}
  189. else
  190. if struct
  191. extracted << "#{struct.media_type}/#{struct.subtype}"
  192. end
  193. end
  194. extracted
  195. end
  196.  
  197. def self.[] uid
  198. self.new uid
  199. end
  200.  
  201. def self.create_with mail
  202. pp mail
  203. end
  204.  
  205. def self.cache_flush
  206. @@cache ||= {}
  207. print("Cache size before: #{@@cache.size}")
  208. @@cache.clear
  209. puts(", and after #{@@cache.size}")
  210. end
  211. end
  212.  
  213. class Server
  214. class << self
  215. def method_missing meth, *args, &block
  216. server = Nitro::Session.current[:server]
  217. server.send(meth, *args, &block)
  218. end
  219. end
  220.  
  221. def method_missing meth, *args, &block
  222. p [:method_missing, meth, args]
  223. connect unless @imap
  224. imap :send, meth, *args, &block
  225. end
  226.  
  227. def initialize host = 'localhost', user = nil, pass = nil
  228. raise "provide username and password" unless [user,pass].all?
  229. connect @host = host, @user = user, @pass = pass
  230. end
  231.  
  232. def imap
  233. connect unless @imap
  234. @imap
  235. end
  236.  
  237. def connect host = 'localhost', user = @user, pass = @pass
  238. @imap = Net::IMAP.new(host)
  239. imap :authenticate, 'LOGIN', user, pass
  240. @imap
  241. end
  242.  
  243. def disconnect
  244. return true if imap :disconnected?
  245. imap :disconnect
  246. end
  247.  
  248. def reconnect
  249. disconnect
  250. connect
  251. end
  252.  
  253. def check_mail
  254. p [:check_mail]
  255. examine @mailbox[:name], :force
  256. end
  257.  
  258. # open mailbox read-only
  259. def examine mailbox, force = nil
  260. @mailbox ||= {}
  261. mailbox = mailbox.to_s.upcase
  262. if (@mailbox.values_at(:mode, :name) != [:read_only, mailbox]) || force
  263. imap :examine, mailbox
  264. Envelope.cache_flush
  265. @mailbox = {:mode => :read_only, :name => mailbox}
  266. end
  267. end
  268.  
  269. # open mailbox read/write
  270. def select mailbox, force = nil
  271. @mailbox ||= {}
  272. mailbox = mailbox.to_s.upcase
  273. if @mailbox.values_at(:mode, :name) != [:read_write, mailbox] || force
  274. imap :select, mailbox
  275. Envelope.cache_flush
  276. @mailbox = {:mode => :read_write, :name => mailbox}
  277. end
  278. end
  279.  
  280. def status mailbox = @mailbox[:name]
  281. imap(:status, mailbox, %w(MESSAGES RECENT UNSEEN)).map{|k,v| [k.downcase.to_sym, v]}.to_hash
  282. end
  283.  
  284. def delete uid
  285. imap :select, @mailbox[:name]
  286. imap :store, uid, " FLAGS", [:Deleted]
  287. imap :expunge
  288. examine(@mailbox[:name], :force)
  289. imap :examine, @mailbox[:name]
  290. end
  291.  
  292. def mailbox mailbox = 'inbox', query = 'all', start = 0, size = 30
  293. start, size = start.to_i, size.to_i
  294. mails = []
  295. examine mailbox rescue reconnect
  296.  
  297. #debugger
  298.  
  299. begin
  300. time = Time.now
  301. results = sort(query) rescue []
  302. mails = []
  303. results.reverse.each do |result|
  304. mail = Envelope.new(result)
  305. mails << mail unless mails.include?(mail)
  306. if mails.size >= size
  307. puts "finished fetching #{mails.size}/#{size} mails after #{Time.now - time} seconds"
  308. return mails.sort_by{|m| m.date}.reverse
  309. end
  310. end
  311. rescue
  312. return mails
  313. end
  314. end
  315.  
  316. def fetch uid, opt
  317. s = imap :uid_fetch, uid, opt.to_s.upcase
  318. s.first.attr[opt.to_s]
  319. end
  320.  
  321. def fetch_envelopes *uids
  322. threads = imap :uid_thread, 'REFERENCES', 'ALL', 'UTF-8'
  323. pp threads.map do |t|
  324. Evelope.new t.seqno
  325. end
  326. end
  327.  
  328. def fetch_envelope uid
  329. fetch(uid, 'ENVELOPE')
  330. end
  331.  
  332. # recent, all, new, not, or ...
  333. def search query = 'recent'
  334. imap :uid_search, param_transform(query)
  335. end
  336.  
  337. def sort query = 'all', keys = 'date'
  338. keys, query = [keys, query].map{|e| param_transform(e)}
  339. imap :uid_sort, keys, query, 'UTF-8'
  340. end
  341.  
  342. def param_transform *args
  343. # %w(foo bar) %w(FOO BAR) "foo bar" "FOO BAR" ["foo bar", "foobar"]
  344. [args].flatten.map{|s| s.split.map{|s| [s.upcase]}}.flatten
  345. end
  346.  
  347. # just a proxy to @imap so nothing blows up
  348. # use that instead of @imap
  349. def imap meth, *args, &block
  350. p [:imap, meth, args, block]
  351. begin
  352. Timeout::timeout(10) do
  353. return @imap.send(meth, *args, &block)
  354. end
  355. rescue Object => ex
  356. if [IOError, ThreadError].include? ex.class and not failure
  357. reconnect
  358. failure = true
  359. retry
  360. else
  361. p :imap_error
  362. p ex.class
  363. puts ex
  364. pp ex.backtrace
  365. raise
  366. end
  367. end
  368. end
  369. end
  370. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement