Skip to content

Commit

Permalink
Initial commit. Skyper!
Browse files Browse the repository at this point in the history
  • Loading branch information
Antti committed Apr 20, 2012
1 parent 7eb2625 commit bea2b66
Show file tree
Hide file tree
Showing 20 changed files with 556 additions and 3 deletions.
3 changes: 3 additions & 0 deletions Gemfile
@@ -0,0 +1,3 @@
source 'https://rubygems.org'

gemspec
16 changes: 16 additions & 0 deletions Gemfile.lock
@@ -0,0 +1,16 @@
PATH
remote: .
specs:
skyper (0.1.0)
rb-appscript (>= 0.3.0)

GEM
remote: https://rubygems.org/
specs:
rb-appscript (0.6.1)

PLATFORMS
ruby

DEPENDENCIES
skyper!
22 changes: 22 additions & 0 deletions LICENSE
@@ -0,0 +1,22 @@
Copyright (c) 2012 Andriy Dmytrenko

MIT License

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 changes: 33 additions & 3 deletions README.md
@@ -1,4 +1,34 @@
skyper
======
# Skyper

Ruby Skype API
A ruby gem, implementing Skype public API.
https://developer.skype.com/public-api-reference

Currently works only on MacOS X, using AppleScript to connect to Skype.
Inspired by rb-skypemac.


## Installation

Add this line to your application's Gemfile:

gem 'skyper'

And then execute:

$ bundle

Or install it yourself as:

$ gem install skyper

## Usage

TODO: Write usage instructions here

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
2 changes: 2 additions & 0 deletions Rakefile
@@ -0,0 +1,2 @@
#!/usr/bin/env rake
require "bundler/gem_tasks"
8 changes: 8 additions & 0 deletions lib/skyper.rb
@@ -0,0 +1,8 @@
$:.unshift File.expand_path('../',__FILE__)
module Skyper
autoload :SkypeObject, 'skyper/skype_object'
autoload :User, 'skyper/user'
autoload :Chat, 'skyper/chat'
autoload :Group, 'skyper/group'
end
Dir[File.join(File.dirname(__FILE__), 'skyper/**/*.rb')].sort.each { |lib| require lib }
50 changes: 50 additions & 0 deletions lib/skyper/call.rb
@@ -0,0 +1,50 @@
module Skyper
# Represents a Skype call. Developer is responsible for calling Call#hangup at the end of each call, whether it was placed
# by the caller or is an answered call.
class Call < SkypeObject
property_reader :TIMESTAMP => Time, :PARTNER_HANDLE => Skyper::User, :RATE => Integer
property_reader *%w[PARTNER_DISPNAME TARGET_IDENTITY CONF_ID TYPE STATUS VIDEO_STATUS VIDEO_SEND_STATUS FAILUREREASON SUBJECT
PSTN_NUMBER DURATION PSTN_STATUS CONF_PARTICIPANTS_COUNT VM_DURATION VM_ALLOWED_DURATION RATE_CURRENCY RATE_PRECISION INPUT OUTPUT CAPTURE_MIC VAA_INPUT_STATUS
FORWARDED_BY TRANSFER_ACTIVE TRANSFER_STATUS TRANSFERRED_BY TRANSFERRED_TO]
self.object_name = "CALL"
class << self
def active_call_ids
r = Skype.send_command "SEARCH ACTIVECALLS"
r.gsub(/CALLS /, "").split(", ")
end

def active_calls
Call.active_call_ids.map { |id| Call.new id unless id == "COMMAND_PENDING"}
end

def create(*users)
user_handles = users.map { |u| (u.is_a? User) ? u.handle : u }
status = Skype.send_command "CALL #{user_handles.join(', ')}"
if status =~ /CALL (\d+) STATUS/
call = Call.new($1)
else
raise RuntimeError.new("Call failed. Skype returned '#{status}'")
end
end
end

# Attempts to hang up a call. <b>Note</b>: If Skype hangs while placing the call, this method could hang indefinitely.
# <u>Use Skype#Call instead of this method unless you like memory leaks</u>.
# Raises SkypeError if an error is reported from the Skype API
def hangup
self.status = "FINISHED"
end

def send_video(toggle_flag)
alter("#{bool_to_flag(toggle_flag)}_VIDEO_SEND")
end

def rcv_video(toggle_flag)
alter("#{bool_to_flag(toggle_flag)}_VIDEO_RECEIVE")
end
protected
def bool_to_flag(bool)
bool ? "START" : "STOP"
end
end
end
42 changes: 42 additions & 0 deletions lib/skyper/chat.rb
@@ -0,0 +1,42 @@
module Skyper
class Chat < SkypeObject
property_accessor *%w[NAME TIMESTAMP ADDER POSTERS TOPIC TOPICXML ACTIVEMEMBERS FRIENDLYNAME BOOKMARKED MEMBEROBJECTS PASSWORDHINT GUIDELINES
OPTIONS DESCRIPTION DIALOG_PARTNER ACTIVITY_TIMESTAMP TYPE MYSTATUS MYROLE BLOB APPLICANTS]
property_reader :RECENTCHATMESSAGES => Array
property_reader :STATUS, :MEMBERS, :CHATMESSAGES
self.object_name = "CHAT"
attr_reader :id

class << self
# create by user_handle
def create(user_handle)
r = Skype.send_command "CHAT CREATE #{user_handle}"
Chat.parse_from r
end

# Returns an array of your Skype recent chats
def recent_chats
r = Skype.send_command "SEARCH RECENTCHATS"
chat_ids = parse_type(r.sub(/^CHATS\s+/, ""), Array)
chat_ids.map do |id|
Chat.new(id)
end
end
end

# chat message to chat
def chat_message(message)
r = Skype.send_command "CHATMESSAGE #{id} #{message}"
ChatMessage.parse_from(r)
end

def recent_chat_messages
self.recentchatmessages.map {|id| ChatMessage.new(id)}
end

def set_topic(topic)
alter('SETTOPIC', topic)
end

end
end
7 changes: 7 additions & 0 deletions lib/skyper/chat_message.rb
@@ -0,0 +1,7 @@
module Skyper
class ChatMessage < Skyper::SkypeObject
property_accessor :BODY, :FROM_DISPNAME, :TYPE, :STATUS, :LEAVEREASON, :CHATNAME, :IS_EDITABLE, :EDITED_BY, :EDITED_TIMESTAMP, :OPTIONS, :ROLE
property_reader :TIMESTAMP => Time, :FROM_HANDLE => Skyper::User, :USERS => Array
self.object_name = "CHATMESSAGE"
end
end
31 changes: 31 additions & 0 deletions lib/skyper/group.rb
@@ -0,0 +1,31 @@
module Skyper
class Group < SkypeObject
#TYPE: {ALL | CUSTOM | HARDWIRED | SHARED_GROUP | PROPOSED_SHARED_GROUP}
property_reader :TYPE, :CUSTOM_GROUP_ID, :NROFUSERS, :NROFUSERS_ONLINE, :USERS
property_accessor :DISPLAYNAME
self.object_name = "GROUP"

class << self
# Returns hash of symols (group types) => Group objects
def groups
r = Skype.send_command "SEARCH GROUPS ALL"
r.gsub!(/^\D+/, "")
group_ids = r.split /,\s*/
group_ids.map do |id|
Group.new(id)
end
end
end

# Returns array of skype names of users in this group
def member_user_names
r = users
r && r.sub(/^.*USERS /, "").split(", ") or []
end

# Returns array of Users in this Group
def user_objects
member_user_names.map { |h| User.new h }
end
end
end
18 changes: 18 additions & 0 deletions lib/skyper/iam.rb
@@ -0,0 +1,18 @@
module Skyper

# Singleton for managing Skype user status
class Iam
@@STATUSES = [:ONLINE, :OFFLINE, :SKYPEME, :AWAY, :NA, :DND, :INVISIBLE]

def Iam.set_user_status(status)
raise NoMethodError.new("#{status} in #{Iam.to_s}") if not @@STATUSES.index status.upcase.to_sym
Skype.send_command "SET USERSTATUS #{status}"
end

# Handles all of the user status permutations accepted by Skype otherwise Errors.
# For example, <i>Iam.away</i> is legal.
def Iam.method_missing(id)
Iam.set_user_status(id.id2name)
end
end
end
26 changes: 26 additions & 0 deletions lib/skyper/platform/mac.rb
@@ -0,0 +1,26 @@
module Skyper
module Mac
class Connection
attr_accessor :logger
attr_reader :options

def initialize(options={})
@options = options
@logger ||= Logger.new(STDOUT).tap do |logger|
logger.level = Logger::ERROR
end
end

# @param[String] command Skype command
def send_command(command)
params = {:script_name => options[:script_name].to_s, :command => command}
logger.debug "#{self.class}##{__method__} params: #{params.inspect}"
response = Appscript::app('Skype').send_ params
response.tap do
logger.debug "#{self.class}##{__method__} response: #{response}"
end
end

end
end
end
9 changes: 9 additions & 0 deletions lib/skyper/profile.rb
@@ -0,0 +1,9 @@
module Skyper
class Profile < SkypeObject
property_reader *%w[PSTN_BALANCE PSTN_BALANCE_CURRENCY SMS_VALIDATED_NUMBERS]
property_accessor *%w[FULLNAME SEX LANGUAGES COUNTRY IPCOUNTRY PROVINCE CITY PHONE_HOME PHONE_OFFICE PHONE_MOBILE HOMEPAGE ABOUT MOOD_TEXT RICH_MOOD_TEXT TIMEZONE
CALL_APPLY_CF CALL_NOANSWER_TIMEOUT CALL_FORWARD_RULES CALL_SEND_TO_VM]
property_accessor :BIRTHDAY => Time
self.object_name = "PROFILE"
end
end
95 changes: 95 additions & 0 deletions lib/skyper/skype.rb
@@ -0,0 +1,95 @@
require 'appscript'
require 'logger'
require 'singleton'
require 'forwardable'

module Skyper

# Singleton for interfacing with Skype
class Skype
include Singleton
attr_accessor :script_name
attr_reader :connection

def initialize
@connection = Skyper::Mac::Connection.new
send_command("PROTOCOL 8")
end

# @param[String] command Skype command
def send_command(command)
@connection.send_command(command)
end

def profile
@profile ||= Profile.new(nil)
end

# Initiates a Skype call
def call(*users)
Call.create(*users)
end

# Returns an Array of Call IDs if there is an incoming Skype call otherwise nil
def incoming_calls
Call.active_calls
end

# Answers a call given a skype Call ID. Returns an Array of Call objects.
def answer(call)
cmd = "ALTER CALL #{call.call_id} ANSWER"
r = Skype.send_command cmd
raise RuntimeError("Failed to answer call. Skype returned '#{r}'") unless r == cmd
end

# Returns an Array of Group
def groups
@groups ||= Group.groups
end

# Returns Array of all User in a particular Group type. Accepts types as defined by Group.types
def find_users_of_type(group_type)
groups.find { |g| g.type == group_type}.users
end

# Returns an array of users online friends as User objects
def online_friends
find_users_of_type "ONLINE_FRIENDS"
end

# Array of all User that are friends of the current user
def all_friends
find_users_of_type "ALL_FRIENDS"
end

# Array of all User defined as Skype Out users
def skypeout_friends
find_users_of_type "SKYPEOUT_FRIENDS"
end

# Array of all User that the user knows
def all_users
find_users_of_type "ALL_USERS"
end

# Array of User recently contacted by the user, friends or not
def recently_contacted_users
find_users_of_type "RECENTLY_CONTACTED_USERS"
end

# Array of User waiting for authorization
def users_waiting_for_authorization
find_users_of_type "USERS_WAITING_MY_AUTHORIZATION"
end

# Array of User blocked
def blocked_users
find_users_of_type "USERS_BLOCKED_BY_ME"
end
class << self
extend Forwardable
def_delegators :instance, *Skyper::Skype.instance_methods(false)
end
end

end
4 changes: 4 additions & 0 deletions lib/skyper/skype_error.rb
@@ -0,0 +1,4 @@
module Skyper
class SkypeError<StandardError
end
end

0 comments on commit bea2b66

Please sign in to comment.