рджрд┐рд▓рдЪрд╕реНрдк рдбреЗрд╕реНрдХрдЯреЙрдк рд╡реЙрд▓рдкреЗрдкрд░ рдХреА рдЦреЛрдЬ рдореЗрдВ
theotaku.com рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ
рджреЗрдЦрддреЗ рд╣реБрдП, рдореИрдВрдиреЗ рдЦреБрдж рдХреЛ рдпрд╣ рд╕реЛрдЪрдХрд░ рдкрдХрдбрд╝рд╛ рдХрд┐ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд▓рд┐рдЦрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдЬреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдореЗрд░реЗ рдмрдЬрд╛рдп рд╡реЙрд▓рдкреЗрдкрд░ рдХреЛ рдЯреИрдЧ рдХрд░рдХреЗ рдЦреБрдж рдХреЛ рдЯреИрдЧ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рддрдереНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд┐ рдореИрдВ рдореБрдЦреНрдп рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд░реВрдк рдореЗрдВ
рдореИрдХ рдУрдПрд╕ рдПрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рднреА рдЗрд╕ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЗ рд▓рд┐рдП рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░
рдХреЛрдХреЛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣реЛрдирд╛ рд╡рд╛рдВрдЫрдиреАрдп рд╣реИред рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ, рдореИрдВ рдпрд╣ рд╕рдм рдЬрд╛рд╡рд╛ рдореЗрдВ рдирд╣реАрдВ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдмреЗрд╢рдХ рдХрдИ рд╡рд┐рдХрд▓реНрдк рдереЗ, рд▓реЗрдХрд┐рди рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдореИрдВ рдХреБрдЫ рдФрд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдФрд░ рдЙрд╕реА рд╕рдордп рдХреБрдЫ рдирдпрд╛ рд╕реАрдЦрддрд╛ рдерд╛ред рдореБрдЭреЗ рддреБрд░рдВрдд
рдореИрдХрд░рд╛рдмреА рдФрд░
рдХреЛрдХреЛ рдХреЗ рд╕рд╛рде рдЗрд╕рдХреЗ рдШрдирд┐рд╖реНрда рдПрдХреАрдХрд░рдг рдХреА рдпрд╛рдж рдЖ рдЧрдИред рдЗрд╕ рд╡рд┐рдЪрд╛рд░ рдХреЗ рд╕рд╛рде, рдореИрдВ рддреБрд░рдВрдд
http://www.macruby.org/ рдкрд░ рдЪрдврд╝ рдЧрдпрд╛ рдФрд░ рдирд╡реАрдирддрдо рд╕реНрдерд┐рд░ рд╕рдВрд╕реНрдХрд░рдг 0.10 рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ред рд╕реНрдерд╛рдкрдирд╛ рдХреЗ рдмрд╛рдж, рдореИрдВрдиреЗ рдЕрдкрдирд╛ рдкрд╕рдВрджреАрджрд╛
Xcode рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдФрд░
AnimeWallpaperDownloader рдирд╛рдордХ рдПрдХ рдирдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ
рд╣рдорд╛рд░реЗ
MacRuby рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдХрдИ рдлрд╛рдЗрд▓реЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЬреЛ
Xcode рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрдирд╛рддрд╛ рд╣реИред рдкрд╣рд▓реА рдлрд╝рд╛рдЗрд▓
main.m рд╣реИ рдЬреЛ рдмрд╕
MacRuby рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ
rb_main.rb рдЪрд▓рд╛рддреА рд╣реИ
rb_main.rb рдПрдХ рдХрд╛рдлреА рд╕рд░рд▓ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ, рдпрд╣ рдЕрдиреНрдп рд╕рднреА
рд░реВрдмреА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рд▓реЛрдб рдХрд░рддреА рд╣реИ рдФрд░ рдЪрд▓рддреА рд╣реИ
NSApplicationMain framework 'Cocoa'
рдЕрдВрддрд┐рдо рдлрд╝рд╛рдЗрд▓ рдЬреЛ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмрдирд╛рдИ рд╣реИ,
AppDelegate.rb рд╣реИ , рдЬреЛ
NSApplicationDelegate рдХреА рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рддрд╛ рд╣реИред рдЗрд╕рдореЗрдВ рдПрдХ рдЦрд╛рд▓реА
ApplicationDidFinishLaunching рд╡рд┐рдзрд┐ рд╣реИ рдЬрд┐рд╕реЗ рддрдм рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рд╣рдорд╛рд░рд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╢реБрд░реВ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
class AppDelegate attr_accessor :window def applicationDidFinishLaunching(a_notification)
рдпрд╣рд╛рдБ
attr_accessor: рд╡рд┐рдВрдбреЛ IBOutlet * рд╡рд┐рдВрдбреЛ рдХреА рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рддрд╛ рд╣реИ рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╣рдорд╛рд░реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреА рд╡рд┐рдВрдбреЛ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ
MainMenu.xib рдЦреЛрд▓реЗрдВ рдФрд░ рд╣рдорд╛рд░реЗ рд╡реЙрд▓рдкреЗрдкрд░ рдбрд╛рдЙрдирд▓реЛрдбрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдПрдВ

рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдорд╛рд░реЗ
AppDelegate рдореЗрдВ рддрд░реАрдХреЗ рдФрд░
рдЖрдЙрдЯрд▓реЗрдЯ рдЬреЛрдбрд╝реЗрдВ
class AppDelegate attr_accessor :window attr_accessor :tags attr_accessor :size attr_accessor :number attr_accessor :saveInto attr_accessor :startButton attr_accessor :output attr_accessor :downprogress attr_accessor :downloader attr_accessor :img def applicationDidFinishLaunching(a_notification) @startButton.setEnabled(false) @downprogress.setStringValue('') @output.setStringValue('') @saveInto.stringValue = NSHomeDirectory()+"/Pictures" end def windowWillClose(a_notification) NSApp.terminate(self) end def controlTextDidChange(notification) sender = notification.object if sender == tags @startButton.setEnabled(@tags.stringValue.size > 0) elsif sender == number begin @number.setIntValue(@number.intValue) if @number.intValue < 0 @number.setIntValue(-@number.intValue) elsif @number.intValue == 0 @number.setIntValue(20) end rescue @number.setIntValue(20) end end end def browse(sender) dialog = NSOpenPanel.openPanel dialog.canChooseFiles = false dialog.canChooseDirectories = true dialog.allowsMultipleSelection = false if dialog.runModalForDirectory(nil, file:nil) == NSOKButton @saveInto.stringValue = dialog.filenames.first end end def startStop(sender) if @downloader == nil @downloader = Downloader.new(@tags.stringValue,@size.selectedItem.title,@number.stringValue,@saveInto.stringValue,self) @downloader.start @startButton.setTitle("Stop Download") else @downloader.stop @downloader = nil @startButton.setTitle("Start Download") end end def changeImage(file) @img.setImage(NSImage.alloc.initByReferencingFile(file)) end def clearStatus @downprogress.setStringValue('') end def setStatus(i,m) @downprogress.setStringValue("Downloading "+i.to_s()+" of "+m.to_s()) end def setStatusEnd(i) @downprogress.setStringValue("Downloaded "+i.to_s()+" wallpapers") end def puts(val) $stdout.puts val @output.setStringValue(val) end def stopped @startButton.setTitle("Start Download") down = @downloader @downloader = nil down.stop end end
рдпрд╣рд╛рдБ рд╕рдм рдХреБрдЫ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИред
WindowWillClose рдФрд░
controlTextDidChange рддрд░реАрдХреЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╡рд┐рдВрдбреЛ рдФрд░ рдкрд╣рд▓реЗ рдЯреЗрдХреНрд╕реНрдЯ рдлрд╝реАрд▓реНрдб рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рддрд░реАрдХреЗ рд╣реИрдВ (рдЖрдк рдЯреИрдЧ рджрд░реНрдЬ рдХрд░рдиреЗ рддрдХ рдХреБрдЫ рднреА рдбрд╛рдЙрдирд▓реЛрдб рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ)ред
рдмреНрд░рд╛рдЙрдЬрд╝ рд╡рд┐рдзрд┐ рдЙрд╕ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЛ рдЪреБрдирдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдбрд╛рдпрд▓реЙрдЧ рдмреЙрдХреНрд╕ рдЦреЛрд▓рддреА рд╣реИ рдЬрд╣рд╛рдВ рд╣рдо рдЕрдкрдиреЗ рд╡реЙрд▓рдкреЗрдкрд░ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВ, рд╣рдо рдЗрд╕реЗ
рдмреНрд░рд╛рдЙрдЬ рдмрдЯрди рд╕реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред
StartStop рд╡рд┐рдзрд┐ рдХреВрджрдирд╛ рд╢реБрд░реВ рдХрд░рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ
рд╕реНрдЯрд╛рд░реНрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдмрдЯрди рд╕реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рд╢реЗрд╖ рд╡рд┐рдзрд┐рдпрд╛рдВ рд╕рд╣рд╛рдпрдХ рд╣реИрдВ рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ
рдбрд╛рдЙрдирд▓реЛрдбрд░ рд╡рд░реНрдЧ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рд▓рд┐рдВрдХ рдЦреЛрдЬрдиреЗ рдФрд░ рд╡реЙрд▓рдкреЗрдкрд░ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░реЗрдВрдЧреЗ
require 'thread' require 'net/http' class Downloader attr_accessor :tags, :size, :number, :saveTo, :thread attr_accessor :app, :exit def initialize(tags, size, number, saveTo, app) @tags = tags.sub(' ','_') @size = size == 'Any' ? '' : size.sub('x','_') @number = number @saveTo = saveTo @app = app @exit = false end def getIndexPage(page) walls = {} url = 'http://www.theotaku.com/wallpapers/tags/'+tags+'/?sort_by=&resolution='+size+'&date_filter=&category=&page='+page.to_s() @app.puts 'getting index for page: '+page.to_s() @app.puts url response = Net::HTTP.get_response(URI.parse(url)) res = response.body res.each_line { |line| f = line.index('wallpapers/view') while f != nil b = line.rindex('"',f) e = line.index('"',b+1) u = line[b+1,eb].gsub('"','') walls[u] = u line = line.sub(u,'') f = line.index('wallpapers/view') end } @app.puts 'got '+walls.size.to_s()+' wallpapers' return walls.keys end def downloadWall(url) @app.puts 'downloading '+url response = Net::HTTP.get_response(URI.parse(url)) res = response.body b = res.index('src',res.rindex('wall_holder'))+5 e = res.index('"',b) img = res[b,eb] self.downloadFile(img) end def downloadFile(url) name = url[url.rindex('/')+1,1000] if File.exists?(@saveTo+'/'+name) @app.puts 'wallpaper already saved '+name @app.changeImage(@saveTo+'/'+name) else @app.puts 'downloading file '+url response = Net::HTTP.get_response(URI.parse(url)) open(@saveTo+'/'+name, 'wb') { |file| file.write(response.body) } @app.puts 'wallpaper saved '+name @app.changeImage(@saveTo+'/'+name) end end def getWallUrl(i,url,size) sizes = {} i = i+1 @app.puts 'getting '+url+' sizes' response = Net::HTTP.get_response(URI.parse(url)) res = response.body res.each_line { |line| f = line.index('wallpapers/download') while f != nil b = line.rindex('\'',f) e = line.index('\'',b+1) u = line[b+1,eb] u = u.gsub('\'','') sizes[u] = u line = line.sub(u,'') f = line.index('wallpapers/download') end } sizef = @size.sub('_','-by-') sizes = sizes.keys() if sizef == '' maxi = 0 max = 0 i = 0 sizes.each { |s| f = s.rindex('/') l = s[f+1,100] l = l.sub('-by-',' ') l = l.split(' ') rs = l[0].to_i()*l[1].to_i() if rs > max maxi = i max = rs end i = i+1 } return sizes[maxi] else sizes.each { |s| if s =~ /
рдХреНрдпрд╛ рдПрдХ рд╡рд┐рд╢рд╛рд▓ рд╡рд░реНрдЧ рд╕рдЪ рд╣реИ? рд╣рд╛рдВ, рдпрд╣ рддрд░реНрдХ рд╕реЗ рднрд░рд╛ рд╣реБрдЖ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдм рдХреБрдЫ рдХрд╛рдлреА рддреБрдЪреНрдЫ рд╣реИред
рдкреНрд░рд╛рд░рдВрдн рд╡рд┐рдзрд┐ рдмрд╕ рдПрдХ рдЕрд▓рдЧ рдзрд╛рдЧрд╛ рд╢реБрд░реВ рдХрд░рддреА рд╣реИ рдЬреЛ рд╣рдорд╛рд░реЗ рд╡реЙрд▓рдкреЗрдкрд░ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдЧреА, рдЗрд╕реЗ рд░реЛрдХрддреА рд╣реИред рддрд░реАрдХреЗ
getIndexPage ,
getWallUrl ,
downloadWall forotaku.com рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ
рд╣реИрдВ рдФрд░ рдЗрдирдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рддрд░реНрдХ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рддреБрдЪреНрдЫ рд╣реИрдВ рдФрд░ рдЯреИрдЧ рджреНрд╡рд╛рд░рд╛ рд╡реЙрд▓рдкреЗрдкрд░ рдХреА рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рд╡рд╛рдВрдЫрд┐рдд рдЖрдХрд╛рд░ рдХреЗ рд╡рд╛рдВрдЫрд┐рдд рд▓рд┐рдВрдХ рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ рдФрд░ рдЗрди рд╡реЙрд▓рдкреЗрдкрд░ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ
рдкрд░рд┐рдгрд╛рдо рд░рд╡рд┐рд╡рд╛рд░ рдХреА рд╢рд╛рдо, рдЖрддреНрдо-рд╕рдВрддреБрд╖реНрдЯрд┐ рдХреА рдПрдХ рдЕрдЪреНрдЫреА рднрд╛рд╡рдирд╛, рдФрд░
рдореИрдХ рдУрдПрд╕ рдПрдХреНрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╡рд┐рдХрд╛рд╕ рдордВрдЪ рдХреЗ рд░реВрдк рдореЗрдВ
рдореИрдХрд░рд╛рдмреА рдХреЗ рднрд╡рд┐рд╖реНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рджрд┐рд▓рдЪрд╕реНрдк рд╡рд┐рдЪрд╛рд░ рднреА рдмрд┐рддрд╛рдП рдЧрдП рдереЗред рдмреЗрд╢рдХ, рдПрдХ
рд░реЗрдХ рдерд╛ рдФрд░ рдХреБрдЫ рдЪреАрдЬреЗрдВ рдирд╣реАрдВ рдХреА рдЬрд╛ рд╕рдХрддреА рдереАрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐
MacRuby рдордВрдЪ рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ рд╣рд╛рд╕рд┐рд▓ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рд░рд╣рд╛ рд╣реИ рдФрд░ рдЗрд╕рдХрд╛ рднрд╡рд┐рд╖реНрдп рдЙрдЬреНрдЬреНрд╡рд▓ рд╣реИред
рдЖрдк
рдпрд╣рд╛рдВ рдкрд░рд┐рдгрд╛рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЖрдк
рдпрд╣рд╛рдВ рд╕реЗ рддреИрдпрд╛рд░ рдирд┐рд░реНрдорд╛рдг
рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ
рд╣реИрдВ (рдЖрдкрдХреЗ рдкрд╛рд╕
MacRuby рд╕реНрдерд╛рдкрд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП)
рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж
рдЕрд▓рд╡рд┐рджрд╛ рдПрдирдЖрдИрдЖрдИ

UPD: рдкрд╛рд░реНрд╕рд░ рдХреЛ
рд░рд┐рдлрд▓реЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
рдПрд╕реНрдЯреЗ рдХрд╛ рд╢реБрдХреНрд░рд┐рдпрд╛ , рдпрд╣ рд╕рд┐рд░реНрдл рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд▓рдЧ рд░рд╣рд╛ рд╣реИ,
рдЧрд┐рддреБрдм рдкрд░ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рджреЗрдЦреЗрдВ