social_nets_db 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,525 @@
1
+ behance:
2
+ name: Behance
3
+ icons:
4
+ font_awesome: behance
5
+ color: "#1769ff"
6
+ domain: behance.com
7
+ tags:
8
+ - art
9
+ - design
10
+ - recruiting
11
+ profile_url:
12
+ by_username: "https://${domain}/${uid}"
13
+ by_account_id: "https://${domain}/${uid}"
14
+
15
+ bitchute:
16
+ name: Bitchute
17
+ icons:
18
+ color: "#ef4137"
19
+ domain: bitchute.com
20
+ tags:
21
+ - video-hosting
22
+ - anti-censorship
23
+ profile_url:
24
+ by_username: https://${domain}/profile/${uid}
25
+
26
+ bitclout:
27
+ name: Bitclout
28
+ icons:
29
+ color: "#ef4137"
30
+ domain: bitclout.com
31
+ tags:
32
+ - social net
33
+ - crypto
34
+ profile_url:
35
+ by_username: https://${domain}/u/${uid}
36
+
37
+ blogger:
38
+ name: Blogger
39
+ icons:
40
+ font_awesome: "link"
41
+ color: "#ff8000"
42
+ domain: blogger.com
43
+ tags:
44
+ - obsolete
45
+ profile_url:
46
+ by_username: https://${uid}.blogspot.com
47
+
48
+ discord:
49
+ name: Discord
50
+ icons:
51
+ color: "#7289da"
52
+ domain: discord.com
53
+ tags:
54
+ - gaming
55
+ profile_url:
56
+ by_account_id: "https://discord.gg/${uid}"
57
+
58
+ dribble:
59
+ name: Dribble
60
+ icons:
61
+ font_awesome: "dribble"
62
+ color: "#ea4c89"
63
+ domain: dribble.com
64
+ tags:
65
+ - art
66
+ - design
67
+ - portfolio
68
+ profile_url:
69
+ by_username: https://${domain}/${uid}
70
+ by_account_id: "https://${domain}/${uid}"
71
+
72
+ email:
73
+ name: E-mail
74
+ icons:
75
+ font_awesome: "at"
76
+ color: "#ea4c89"
77
+ domain: gmail.com
78
+ tags:
79
+ - protocols
80
+ profile_url:
81
+ by_username: ${uid}
82
+
83
+ ens:
84
+ name: Ethereum namespace
85
+ icons:
86
+ color: "#5284ff"
87
+ domain: ens.domains
88
+ tags:
89
+ -
90
+ profile_url:
91
+ by_username: https://${uid}.eth
92
+
93
+ facebook:
94
+ name: Facebook
95
+ icons:
96
+ font_awesome: "facebook"
97
+ color: "#3C5A99"
98
+ domain: facebook.com
99
+ tags:
100
+ - social net
101
+ profile_url:
102
+ by_username: https://${domain}/${uid}
103
+ by_account_id: "https://${domain}/${uid}"
104
+
105
+ fl.ru:
106
+ name: FL
107
+ icons:
108
+ color: "#4ea828"
109
+ domain: fl.ru
110
+ tags:
111
+ - free-lance
112
+ - design
113
+ - programming
114
+ profile_url:
115
+ by_username: https://${domain}/users/${uid}/
116
+
117
+ flote:
118
+ name: Flote
119
+ icons:
120
+ color: "#01f"
121
+ domain: flote.app
122
+ tags:
123
+ - anti-censorship
124
+ - social net
125
+ profile_url:
126
+ by_username: https://${domain}/user/${uid}/
127
+
128
+ freelansim:
129
+ name: Фрилансим
130
+ icons:
131
+ color: "#4abfb4"
132
+ domain: freelansim.ru
133
+ tags:
134
+ - free-lance
135
+ - design
136
+ - programming
137
+ profile_url:
138
+ by_username: https://${domain}/freelancers/${uid}
139
+
140
+ gab:
141
+ name: Gab
142
+ icons:
143
+ color: "#21cf7a"
144
+ domain: gab.com
145
+ tags:
146
+ - anti-censorship
147
+ - social net
148
+ profile_url:
149
+ by_username: https://${domain}/${uid}
150
+
151
+ gettr:
152
+ name: Gettr
153
+ icons:
154
+ color: "#ff0013"
155
+ domain: gettr.com
156
+ tags:
157
+ - anti-censorship
158
+ - social net
159
+ profile_url:
160
+ by_username: https://${domain}/user/${uid}
161
+
162
+ habr:
163
+ name: Habrahabr
164
+ icons:
165
+ color: "#65a3be"
166
+ domain: habr.com
167
+ tags:
168
+ - recruiting
169
+ - programming
170
+ - blog
171
+ profile_url:
172
+ by_username: https://${domain}/ru/users/${uid}/
173
+
174
+ habr-career:
175
+ name: Хабр Карьера
176
+ icons:
177
+ color: "#64c178"
178
+ domain: career.habr.com
179
+ tags:
180
+ - recruiting
181
+ - programming
182
+ profile_url:
183
+ by_username: https://${domain}/${uid}/
184
+
185
+ hh:
186
+ name: HeadHunter
187
+ icons:
188
+ color: "#D6001C"
189
+ domain: hh.ru
190
+ tags:
191
+ - recruiting
192
+ profile_url:
193
+ by_account_id: "https://${domain}/resume/${uid}"
194
+
195
+ github:
196
+ name: GitHub
197
+ icons:
198
+ font_awesome: "github"
199
+ color: "#333333"
200
+ domain: github.com
201
+ tags:
202
+ - programming
203
+ - recruiting
204
+ profile_url:
205
+ by_username: https://${domain}/${uid}
206
+ by_account_id: "https://${domain}/${uid}"
207
+
208
+ gitlab:
209
+ name: GitLab
210
+ icons:
211
+ font_awesome: "gitlab"
212
+ color: "#fa7035"
213
+ domain: gitlab.com
214
+ tags:
215
+ - programming
216
+ - recruiting
217
+ profile_url:
218
+ by_username: https://${domain}/${uid}
219
+
220
+ instagram:
221
+ name: Instagram
222
+ icons:
223
+ font_awesome: "instagram"
224
+ color: "#e1306c"
225
+ domain: instagram.com
226
+ tags:
227
+ - social net
228
+ profile_url:
229
+ by_username: https://${domain}/${uid}
230
+
231
+ lbry:
232
+ name: LBRY
233
+ icons:
234
+ color: "#38d9a9"
235
+ domain: lbry.tv
236
+ tags:
237
+ - video-hosting
238
+ profile_url:
239
+ by_username: https://${domain}/@${uid}
240
+
241
+ linkedin:
242
+ name: LinkedIn
243
+ icons:
244
+ font_awesome: "linkedin"
245
+ color: "#0077b5"
246
+ domain: linkedin.com
247
+ tags:
248
+ - recruiting
249
+ - social net
250
+ profile_url:
251
+ by_username: https://${domain}/in/${uid}
252
+
253
+ livejournal:
254
+ name: LiveJournal
255
+ icons:
256
+ font_awesome: "livejournal"
257
+ color: "#00A3D9"
258
+ domain: livejournal.com
259
+ tags:
260
+ - blog
261
+ - obsolete
262
+ profile_url:
263
+ by_username: https://${uid}.${domain}
264
+
265
+ locals:
266
+ name: Locals
267
+ icons:
268
+ color: "#e73348"
269
+ domain: locals.com
270
+ tags:
271
+ - anti-censorship
272
+ - paywall
273
+ profile_url:
274
+ by_username: https://${uid}.${domain}
275
+
276
+ manosphere:
277
+ name: Manosphere
278
+ icons:
279
+ color: "#d84c47"
280
+ domain: manosphere.tv
281
+ tags:
282
+ - anti-censorship
283
+ - paywall
284
+ profile_url:
285
+ by_username: https://${domain}/@${uid}
286
+
287
+ medium:
288
+ name: Medium
289
+ icons:
290
+ font_awesome: "medium"
291
+ color: "#00ab6c"
292
+ domain: medium.com
293
+ tags:
294
+ - blog
295
+ - paywall
296
+ profile_url:
297
+ by_username: https://${uid}.${domain}
298
+
299
+ minds:
300
+ name: Minds
301
+ icons:
302
+ color: "#ffdd63"
303
+ domain: minds.com
304
+ tags:
305
+ - anti-censorship
306
+ - crypto
307
+ - social net
308
+ profile_url:
309
+ by_username: https://${domain}/${uid}
310
+
311
+ my.mail.ru:
312
+ name: Мой мир
313
+ icons:
314
+ color: "#005FF9"
315
+ domain: my.mail.ru
316
+ tags:
317
+ - obsolete
318
+ - social net
319
+ profile_url:
320
+ by_username: https://${domain}/mail/${uid}/
321
+
322
+ odysee:
323
+ name: Odysee
324
+ icons:
325
+ color: "#000000"
326
+ domain: odysee.com
327
+ tags:
328
+ - anti-censorship
329
+ - crypto
330
+ - video-hosting
331
+ profile_url:
332
+ by_username: https://${domain}/@${uid}/
333
+
334
+ odnoklassniki:
335
+ name: Одноклассники
336
+ icons:
337
+ font_awesome: "odnoklassniki"
338
+ color: "#e47d08"
339
+ domain: ok.ru
340
+ tags:
341
+ - obsolete
342
+ - social net
343
+ profile_url:
344
+ by_username: https://${domain}/${uid}/
345
+
346
+ paypal:
347
+ name: PayPal
348
+ icons:
349
+ font_awesome: "paypal"
350
+ color: "#0070ba"
351
+ domain: paypal.com
352
+ tags:
353
+ - payment service
354
+ profile_url:
355
+ by_username: https://${domain}/${uid}
356
+
357
+ patreon:
358
+ name: Patreon
359
+ icons:
360
+ color: "#ff424d"
361
+ domain: patreon.com
362
+ tags:
363
+ - paywall
364
+ profile_url:
365
+ by_username: https://${domain}/${uid}
366
+
367
+ remoteok:
368
+ name: RemoteOK
369
+ icons:
370
+ color: "#ff4742"
371
+ domain: remoteok.io
372
+ tags:
373
+ - design
374
+ - programming
375
+ - recruiting
376
+ profile_url:
377
+ by_username: https://${domain}/@${uid}
378
+
379
+ rokfin:
380
+ name: Rokfin
381
+ icons:
382
+ color: "#08AD9F"
383
+ domain: rokfin.com
384
+ tags:
385
+ - anti-censorship
386
+ - video-hosting
387
+ profile_url:
388
+ by_username: https://${domain}/${uid}
389
+
390
+ rumble:
391
+ name: Rumble
392
+ icons:
393
+ font_awesome: "play-circle"
394
+ color: "#74a441"
395
+ domain: rumble.com
396
+ tags:
397
+ - anti-censorship
398
+ - video-hosting
399
+ profile_url:
400
+ by_username: https://${domain}/c/${uid}
401
+
402
+ stackoverflow:
403
+ name: StackOverflow
404
+ icons:
405
+ font_awesome: "stackoverflow"
406
+ color: "#F48024"
407
+ domain: stackoverflow.com
408
+ tags:
409
+ - recruiting
410
+ - programming
411
+ profile_url:
412
+ by_account_id: "https://${domain}/users/${uid}?tab=profile"
413
+
414
+ subscribestar:
415
+ name: SubscribeStar
416
+ icons:
417
+ color: "#ff4081"
418
+ domain: subscribestar.com
419
+ tags:
420
+ - paywall
421
+ profile_url:
422
+ by_username: https://${domain}/${uid}
423
+
424
+ substack:
425
+ name: SubStack
426
+ icons:
427
+ color: "#ff4081"
428
+ domain: substack.com
429
+ tags:
430
+ - paywall
431
+ - blog
432
+ profile_url:
433
+ by_username: https://${uid}.${domain}
434
+
435
+ telegram:
436
+ name: Telegram
437
+ icons:
438
+ font_awesome: "telegram"
439
+ color: "#0088cc"
440
+ domain: telegram.com
441
+ tags:
442
+ - anti-censorship
443
+ - blog
444
+ - messenger
445
+ profile_url:
446
+ by_username: https://t.me/${uid}
447
+
448
+ tiktok:
449
+ name: TikTok
450
+ icons:
451
+ color: "#fe2c55"
452
+ domain: tiktok.com
453
+ tags:
454
+ - video-hosting
455
+ profile_url:
456
+ by_username: https://${domain}/@${uid}
457
+
458
+ twitter:
459
+ name: Twitter
460
+ icons:
461
+ font_awesome: "twitter"
462
+ color: "#1da1f2"
463
+ domain: twitter.com
464
+ tags:
465
+ - social net
466
+ profile_url:
467
+ by_username: https://${domain}/${uid}
468
+
469
+ upwork:
470
+ name: UpWork
471
+ icons:
472
+ color: "#37A000"
473
+ domain: upwork.com
474
+ tags:
475
+ - design
476
+ - freelancers
477
+ - programming
478
+ profile_url:
479
+ by_account_id: "https://${domain}/freelancers/~${uid}"
480
+
481
+ vkontakte:
482
+ name: Вконтакте
483
+ icons:
484
+ font_awesome: "vk"
485
+ color: "#45668e"
486
+ domain: vkontakte.com
487
+ tags:
488
+ - social net
489
+ profile_url:
490
+ by_username: https://${domain}/${uid}
491
+ by_account_id: "https://${domain}/id${uid}"
492
+
493
+ youtube:
494
+ name: YouTube
495
+ icons:
496
+ font_awesome: "youtube"
497
+ color: "#ff0000"
498
+ domain: youtube.com
499
+ tags:
500
+ - video-hosting
501
+ profile_url:
502
+ by_username: https://${domain}/c/${uid}
503
+ by_account_id: "https://${domain}/channel/${uid}"
504
+
505
+ youtube_profile:
506
+ name: YouTube
507
+ icons:
508
+ font_awesome: "youtube"
509
+ color: "#ff0000"
510
+ domain: youtube.com
511
+ tags:
512
+ - video-hosting
513
+ profile_url:
514
+ by_username: https://${domain}/${uid}
515
+
516
+ website:
517
+ name: Web site
518
+ icons:
519
+ font_awesome: "link"
520
+ color: "#ff0000"
521
+ domain:
522
+ tags:
523
+ - protocols
524
+ profile_url:
525
+ by_username: ${uid}
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FnValidations
4
+
5
+ module_function
6
+
7
+ def validate_argument_type! argument, permitted_types
8
+ types = Array(permitted_types)
9
+ type_names = types.map { |klass| "`#{klass}`" }.join(" or ")
10
+ valid = types.any? { |type| argument.is_a? type }
11
+ message = "#{type_names} is expected, you pass a `#{argument.class}` (#{argument})"
12
+ fail TypeError, message unless valid
13
+ argument
14
+ end
15
+
16
+ def validate_collection_item_types! collection, permitted_types
17
+ types = Array(permitted_types)
18
+ type_names = types.map { |name| "`#{name}`" }.join(" or ")
19
+ valid = collection.all? { |item| types.include?(item.class) }
20
+ message = "#{type_names} is expected, one the items you pass is of incorrect type"
21
+ fail TypeError, message unless valid
22
+ collection
23
+ end
24
+
25
+ def validate_argument_boolean! argument
26
+ validate_argument_type! argument, [TrueClass, FalseClass]
27
+ end
28
+
29
+ def validate_argument_presence! argument
30
+ validate_argument_type! argument, [String, Symbol]
31
+ return argument if argument.is_a?(Symbol)
32
+ message = "You must pass a non-empty String, you are passing #{argument.inspect}"
33
+ fail ArgumentError, message unless argument.is_a?(String) && argument != ""
34
+ argument
35
+ end
36
+
37
+ def validate_argument_positive! argument
38
+ validate_argument_type! argument, Numeric
39
+ message = "You must pass a positive value, you pass #{argument.inspect}"
40
+ fail ArgumentError, message unless argument.positive?
41
+ argument
42
+ end
43
+
44
+ end
45
+
46
+ # RSpec.describe FnValidations do
47
+
48
+ # include described_class
49
+
50
+ # context "invalid input" do
51
+ # it do expect { validate_argument_type! 1, String }.to raise_exception(ArgumentError) end
52
+ # it do expect { validate_argument_type! 1, [String] }.to raise_exception(ArgumentError) end
53
+ # it do expect { validate_argument_type! 1, [Hash, String] }.to raise_exception(ArgumentError) end
54
+ # end
55
+
56
+ # context "valid input" do
57
+ # it do expect { validate_argument_type! 1, Integer }.not_to raise_exception(ArgumentError) end
58
+ # it do expect { validate_argument_type! 1, [Integer] }.not_to raise_exception(ArgumentError) end
59
+ # it do expect { validate_argument_type! 1, [Integer, Hash] }.not_to raise_exception(ArgumentError) end
60
+ # end
61
+
62
+ # context "valid by ancestory" do
63
+ # it do expect { validate_argument_type! 1, Numeric }.not_to raise_exception(ArgumentError) end
64
+ # it do expect { validate_argument_type! [], Enumerable }.not_to raise_exception(ArgumentError) end
65
+ # end
66
+
67
+ # end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SocialNetsDB
4
+ class SocialNet
5
+
6
+ # To have methods both on class & instance
7
+ extend Support
8
+ include Support
9
+ extend FnValidations
10
+ include FnValidations
11
+
12
+ def initialize(uid, data)
13
+ validate_argument_type! data, Hash
14
+ validate_argument_type! uid, [String, Symbol]
15
+ @data, @uid = data, uid
16
+ end
17
+
18
+ attr_accessor :uid
19
+
20
+ [:color, :domain, :icons, :name].each do |method_symbol|
21
+ define_method(method_symbol) do
22
+ to_h[method_symbol.to_s]
23
+ end
24
+ end
25
+
26
+ def to_h
27
+ self.class.send :raw_data_for, @uid
28
+ end
29
+
30
+ def url
31
+ "https://#{domain}"
32
+ end
33
+
34
+ def user_page(username: nil, account_id: nil)
35
+ return unless page = to_h["profile_url"]
36
+ return unless template = page["by_username"] || page["by_account_id"]
37
+ uid = [username, account_id].select { present_str? _1 }.first or fail(ArgumentError, "Either a username or an account id must be provided")
38
+
39
+ if username && page["by_username"]
40
+ fail ArgumentError, "Either a username or an account id must be provided" unless present_str?(username)
41
+ template.sub("${domain}", domain).sub("${uid}", username)
42
+ elsif account_id && page["by_account_id"]
43
+ fail ArgumentError, "Either a username or an account id must be provided" unless present_str?(account_id)
44
+ template.sub("${domain}", domain).sub("${uid}", account_id)
45
+ end
46
+ end
47
+
48
+ def user_page_methods
49
+ ["account_id", "username"].select { |key| present_str? to_h.dig("profile_url", "by_#{key}") }
50
+ end
51
+
52
+
53
+ # Class methods
54
+
55
+ class << self
56
+
57
+ # TODO this must be transofrmed into array of structs
58
+ def all
59
+ RECORDS
60
+ end
61
+
62
+ # @param [String] name Social network name
63
+ # @param [String, Symbol] uid Social network UID
64
+ #
65
+ def find_by(name: nil, uid: nil)
66
+ return find_by_uid(uid) if present_str?(uid)
67
+ return find_by_name(name) if present_str?(name)
68
+ fail ArgumentError, "`name:` or `uid:` must be provided. You are passing name: #{name.inspect}, uid: #{uid.inspect}"
69
+ end
70
+
71
+ def find_by_name(name)
72
+ validate_argument_presence! name
73
+ return unless record = RECORDS.select { |uid, data| data["name"] == name }.first
74
+ find_by_uid record[0]
75
+ end
76
+
77
+ # @param [String, Symbol] uid Social network UID
78
+ #
79
+ def find_by_uid(uid)
80
+ validate_argument_type! uid, String
81
+ validate_argument_presence! uid
82
+
83
+ # unless uids.include?(@uid = uid)
84
+ # fail ArgumentError, "Social net with UID #{uid} is not recognized. Currently supported UIDs are: #{uids.join(", ")}. To add a new social net, send us a PR."
85
+ # end
86
+ return unless data = raw_data_for(uid)
87
+ self.new(uid, data)
88
+ end
89
+
90
+ private def raw_data_for(uid)
91
+ RECORDS[uid.to_s]
92
+ end
93
+
94
+ def names
95
+ RECORDS.map { |uid, data| data[:name] }
96
+ end
97
+
98
+ def uids
99
+ RECORDS.map { |uid, data| data[:uid].to_s }
100
+ end
101
+
102
+ def values_for_select
103
+ RECORDS.map { |uid, data| [data[:name], uid] }
104
+ end
105
+
106
+ alias_method :find, :find_by_uid
107
+
108
+ end
109
+
110
+ end
111
+ end