/
github_friends.rb
executable file
·130 lines (98 loc) · 2.81 KB
/
github_friends.rb
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
#!/usr/bin/env ruby
# frozen_string_literal: true
# Given a username, retrieves the user's following and followers and categorize them into:
# - mutual followers
# - only followers
# - only following
require 'finer_struct'
require 'octokit'
require 'optparse'
require_relative 'lib/config'
require_relative 'lib/github_auth'
DEFAULT_CONFIG_FILE = File.expand_path('~/.githubtools.conf')
def parse_cmdline
options = FinerStruct::Mutable.new(
config_file: DEFAULT_CONFIG_FILE,
force_auth: false,
mutual_friends: false,
only_friends: false,
only_followers: false,
username: nil
)
opts = OptionParser.new
opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} [options] username"
opts.on('-h', '-?', '--help', 'Option help') {
puts opts
exit
}
opts.on('-m', '--mutual', 'Show mutual friends') {
options.mutual_friends = true
}
opts.on('-r', '--only-friends', 'Show only-friends') {
options.only_friends = true
}
opts.on('-o', '--only-followers', 'Show only-followers') {
options.only_followers = true
}
opts.on('--auth', 'Ignore saved access token and force reauthentication') {
options.force_auth = true
}
opts.on('--config-file=FNAME', "Config file name. Default is #{DEFAULT_CONFIG_FILE}") { |fname|
options.config_file = fname
}
opts.separator ' If none of -m/-r/-o are specified, display all 3 categories.'
opts.parse!
if ARGV.empty?
warn 'Error: username argument missing!'
warn opts
exit 1
end
options.username = ARGV.first
if !options.mutual_friends && !options.only_friends && !options.only_followers
# If none of the 3 options are specified, show everything.
options.mutual_friends = options.only_friends = options.only_followers = true
end
options
end
def show_list(list)
if list.empty?
puts 'n/a'
return
end
list.sort_by(&:downcase).each_with_index { |name, i|
puts "#{i + 1}: #{name}"
}
end
def report_ff(client, options)
username = options.username
begin
following = Set.new(client.following(username).map(&:login))
followers = Set.new(client.followers(username).map(&:login))
rescue Octokit::NotFound
warn "User #{username} not found!"
exit 1
end
if options.mutual_friends
puts 'Mutual following:'
show_list following & followers
puts
end
if options.only_friends
puts 'Only following:'
show_list following - followers
puts
end
if options.only_followers
puts 'Only followers:'
show_list followers - following
puts
end
end
options = parse_cmdline
config = Config.new
config.load_config(options.config_file)
auth = GithubAuth.new(config: config, force_auth: options.force_auth)
access_token = auth.access_token
client = Octokit::Client.new(auto_paginate: true, access_token: access_token)
report_ff(client, options)
__END__