-
Notifications
You must be signed in to change notification settings - Fork 1
/
github_friends.rb
executable file
·140 lines (107 loc) · 3.05 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
131
132
133
134
135
136
137
138
139
140
#!/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, userdata)
if list.empty?
puts 'n/a'
return
end
list.sort_by(&:downcase).each_with_index { |username, i|
puts "#{i + 1}: #{username} ( #{userdata[username].html_url} )"
}
end
def report_ff(client, options)
username = options.username
userdata = {}
following = Set.new
followers = Set.new
begin
client.following(username).each { |user|
userdata[user.login] = user
following << user.login
}
client.followers(username).each { |user|
userdata[user.login] = user
followers << user.login
}
rescue Octokit::NotFound
warn "User #{username} not found!"
exit 1
end
if options.mutual_friends
puts 'Mutual following:'
show_list(following & followers, userdata)
puts
end
if options.only_friends
puts 'Only following:'
show_list(following - followers, userdata)
puts
end
if options.only_followers
puts 'Only followers:'
show_list(followers - following, userdata)
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__