freefeed-client 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 51d600de0410a6c2e6341267d64986af26b39add
4
+ data.tar.gz: 2c3b31d286d4b5cb477d38389b00306cb973540e
5
+ SHA512:
6
+ metadata.gz: a1aed947a23f1fcc9b9ae852841ecc72688455e0ae499cd504b05a510a823edf3cd0e0a762c8d5cad748673be74d0958824e5c0451628c5a6e4a2469eb81d174
7
+ data.tar.gz: 2f6299a90a0d4e7e783604d2c7d27f00fcc917ce9ac7f212c6303826231aa31727be25bcac965fe3bb4f134738a86bcd14d8f16a20deca7cd248c8a09a7a0e73
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.13.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in freefeed.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Ilia Zemskov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # freefeed-client
2
+
3
+ Ruby wrapper for [Freefeed API](https://fetsh.github.io/freefeed-api).
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/feefeed-client.svg)](http://badge.fury.io/rb/freefeed-client)
6
+
7
+ ## Installation
8
+
9
+ Add following line to your Gemfile:
10
+
11
+ ```ruby
12
+ gem 'freefeed-client'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```shell
18
+ $ bundle
19
+ ```
20
+
21
+ Or install it system-wide:
22
+
23
+ ```shell
24
+ $ gem install freefeed-client
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ First things first, you need to [obtain a token](https://fetsh.github.io/freefeed-api/#authentication) for your user. Then create your api client like this:
30
+
31
+ ```ruby
32
+ require 'freefeed'
33
+
34
+ client = Freefeed::Client.new('yourFreefeedAPIToken')
35
+
36
+ post = Freefeed::Types::PostCreate.new(
37
+ {
38
+ post: {
39
+ body: 'Hello World!'
40
+ },
41
+ meta: {
42
+ feeds: ['yourusername']
43
+ }
44
+ }
45
+ )
46
+
47
+ post_resource = Freefeed::Post.new(client: client)
48
+
49
+ post_resource.create(post)
50
+ ```
51
+
52
+ You can skip instantiating resource, but I'm not sure if this is a good practice:
53
+
54
+ ```ruby
55
+ require 'freefeed'
56
+
57
+ client = Freefeed::Client.new('yourFreefeedAPIToken')
58
+
59
+ post = Freefeed::Types::PostCreate.new(
60
+ {
61
+ post: {
62
+ body: 'Hello World!'
63
+ },
64
+ meta: {
65
+ feeds: ['yourusername']
66
+ }
67
+ }
68
+ )
69
+
70
+ client.posts.create(post)
71
+ ```
72
+
73
+ You can even skip instantiating post type, but you will lose some validation:
74
+
75
+
76
+ ```ruby
77
+ require 'freefeed'
78
+
79
+ client = Freefeed::Client.new('yourFreefeedAPIToken')
80
+
81
+ client.posts.create({post: {body: 'Hello World!'}, meta: {feeds: ['yourusername']}})
82
+ ```
83
+
84
+ ## Logging
85
+
86
+ By default, `freefeed-client` logs everything to STDOUT. You can change this behavior and provide your own logger class with someo ptions. See example below:
87
+
88
+ ```ruby
89
+ client = Freefeed::Client.new(
90
+ 'yourFreefeedAPIToken',
91
+ logger: Logger.new('log.txt'),
92
+ logger_options: {bodies: false, headers: false}
93
+ )
94
+ ```
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "freefeed"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/freefeed.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'freefeed/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'freefeed-client'
8
+ spec.version = Freefeed::VERSION
9
+ spec.authors = ['Ilia Zemskov']
10
+ spec.email = ['me@fetsh.me']
11
+
12
+ spec.summary = 'Ruby wrapper for FreeFeed API.'
13
+ spec.homepage = 'https://github.com/fetsh/freefeed-client'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = 'bin'
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_dependency 'faraday'
24
+ spec.add_dependency 'faraday_middleware'
25
+ spec.add_dependency 'multi_json'
26
+ spec.add_dependency 'dry-types'
27
+ spec.add_dependency 'dry-struct'
28
+ spec.add_dependency 'activesupport'
29
+
30
+
31
+ spec.add_development_dependency 'bundler', '~> 1.13'
32
+ spec.add_development_dependency 'rake'
33
+ spec.add_development_dependency 'rspec', '~> 3.0'
34
+ end
@@ -0,0 +1,90 @@
1
+ module Freefeed
2
+ class Client
3
+ HOST = 'freefeed.net'.freeze
4
+
5
+ attr_accessor :api_token, :faraday_options, :resources
6
+
7
+ def initialize(api_token = nil, faraday_options = {})
8
+ @api_token = api_token
9
+ @faraday_options = faraday_options
10
+ end
11
+
12
+ def authenticate(username:, password:)
13
+ Session.new(client: self)
14
+ .create(username: username, password: password).tap do |re|
15
+ @api_token = re.fetch('authToken')
16
+ end
17
+ end
18
+
19
+ def call(endpoint, params = {}, headers = {})
20
+ guard_wrong_endpoint(endpoint)
21
+ call!(
22
+ ENDPOINTS[endpoint][:method], path(endpoint),
23
+ build_options(endpoint, params), headers
24
+ )
25
+ end
26
+
27
+ def call!(verb, endpoint, params = {}, headers = {})
28
+ response = conn.send(
29
+ verb, endpoint, params, auth_header.merge(headers)
30
+ )
31
+ handle_erros(response)
32
+ prepare_response(response)
33
+ end
34
+
35
+ private
36
+
37
+ def conn
38
+ @conn ||= Faraday.new(url: "https://#{HOST}") do |faraday|
39
+ faraday.request :multipart
40
+ faraday.response(
41
+ :logger,
42
+ (faraday_options[:logger] || Logger.new(STDOUT)),
43
+ (faraday_options[:logger_options] || { bodies: true, headers: true })
44
+ )
45
+ faraday.request :json
46
+ faraday.adapter faraday_options[:adapter] || Faraday.default_adapter
47
+ end
48
+ end
49
+
50
+ def guard_wrong_endpoint(endpoint)
51
+ raise Exceptions::WrongEndpoint unless ENDPOINTS.keys.include?(endpoint)
52
+ end
53
+
54
+ def build_options(endpoint, params)
55
+ default_params(endpoint).merge(sanitize_params(endpoint, params))
56
+ end
57
+
58
+ def path(endpoint)
59
+ (endpoint.start_with?('/') ? '' : BASE_PATH) + endpoint.split('#').first
60
+ end
61
+
62
+ def default_params(endpoint)
63
+ {}.merge(ENDPOINTS[endpoint][:default_params] || {})
64
+ end
65
+
66
+ def sanitize_params(endpoint, params)
67
+ return {} unless ENDPOINTS[endpoint][:params]
68
+ params.delete_if do |key, _|
69
+ !ENDPOINTS[endpoint][:params].include?(key.to_s)
70
+ end
71
+ end
72
+
73
+ def handle_erros(response)
74
+ raise(
75
+ Exceptions::ResponseError.new(response),
76
+ 'Freefeed API has returned the error'
77
+ ) unless response.status == 200
78
+ end
79
+
80
+ def prepare_response(response)
81
+ MultiJson.load(response.body.to_s)
82
+ rescue MultiJson::LoadError
83
+ response.body
84
+ end
85
+
86
+ def auth_header
87
+ api_token.nil? ? {} : { 'x-authentication-token': api_token }
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,27 @@
1
+ module Freefeed
2
+ module Exceptions
3
+ class ResponseError < StandardError
4
+ attr_reader :response
5
+
6
+ def initialize(response)
7
+ @response = response
8
+ end
9
+
10
+ def to_s
11
+ super + format(' (%s)', data.map { |k, v| %(#{k}: "#{v}") }.join(', '))
12
+ end
13
+
14
+ private
15
+
16
+ def data
17
+ @data ||= begin
18
+ MultiJson.load(response.body)
19
+ rescue MultiJson::DecodeError
20
+ { uri: response.env.url.to_s, errors: response.body.to_s }
21
+ end.merge(code: response.status)
22
+ end
23
+ end
24
+ class WrongEndpoint < StandardError
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ module Freefeed
2
+ class Archive < ResourceKitling::Resource
3
+ actions do
4
+ action :restoration do
5
+ verb :post
6
+ version :v2
7
+ path '/archives/restoration'
8
+ end
9
+ action :activities do
10
+ verb :put
11
+ version :v2
12
+ path '/archives/activities'
13
+ end
14
+ action :post_by_old_name do
15
+ verb :get
16
+ version :v2
17
+ path '/archives/post-by-old-name/:name'
18
+ end
19
+ action :stats do
20
+ verb :get
21
+ version :v2
22
+ path '/archives-stats'
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+ module Freefeed
2
+ class Attachment < ResourceKitling::Resource
3
+ actions do
4
+ action :create do
5
+ verb :post
6
+ version :v1
7
+ path '/attachments'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Freefeed
2
+ class Bookmarklet < ResourceKitling::Resource
3
+ actions do
4
+ action :create do
5
+ verb :post
6
+ version :v1
7
+ path '/bookmarklet'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,36 @@
1
+ module Freefeed
2
+ class Comment < ResourceKitling::Resource
3
+ actions do
4
+ action :create do
5
+ verb :post
6
+ version :v1
7
+ path '/comments'
8
+ end
9
+ action :update do
10
+ verb :put
11
+ version :v1
12
+ path '/comments/:id'
13
+ end
14
+ action :destroy do
15
+ verb :delete
16
+ version :v1
17
+ path '/comments/:id'
18
+ end
19
+ action :like do
20
+ verb :post
21
+ version :v2
22
+ path '/comments/:id/like'
23
+ end
24
+ action :unlike do
25
+ verb :post
26
+ version :v2
27
+ path '/comments/:id/unlike'
28
+ end
29
+ action :likes do
30
+ verb :get
31
+ version :v2
32
+ path '/comments/:id/likes'
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,61 @@
1
+ module Freefeed
2
+ class Group < ResourceKitling::Resource
3
+ actions do
4
+ action :create do
5
+ verb :post
6
+ version :v1
7
+ path '/groups'
8
+ end
9
+ action :sudo_create do
10
+ verb :post
11
+ version :v1
12
+ path '/groups/sudo'
13
+ end
14
+ action :update_profile_picture do
15
+ verb :post
16
+ version :v1
17
+ path '/groups/:name/updateProfilePicture'
18
+ end
19
+ action :admin do
20
+ verb :post
21
+ version :v1
22
+ path '/groups/:name/subscribers/:username/admin'
23
+ end
24
+ action :unadmin do
25
+ verb :post
26
+ version :v1
27
+ path '/groups/:name/subscribers/:username/unadmin'
28
+ end
29
+ action :send_request do
30
+ verb :post
31
+ version :v1
32
+ path '/groups/:name/sendRequest'
33
+ end
34
+ action :accept_request do
35
+ verb :post
36
+ version :v1
37
+ path '/groups/:name/acceptRequest/:username'
38
+ end
39
+ action :reject_request do
40
+ verb :post
41
+ version :v1
42
+ path '/groups/:name/rejectRequest/:username'
43
+ end
44
+ action :unsubscribe_from_group do
45
+ verb :post
46
+ version :v1
47
+ path '/groups/:name/unsubscribeFromGroup/:username'
48
+ end
49
+ action :manage do
50
+ verb :get
51
+ version :v2
52
+ path '/managedGroups'
53
+ end
54
+ action :all do
55
+ verb :get
56
+ version :v2
57
+ path '/allGroups'
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,16 @@
1
+ module Freefeed
2
+ class Invitation < ResourceKitling::Resource
3
+ actions do
4
+ action :create do
5
+ verb :post
6
+ version :v2
7
+ path '/invitations'
8
+ end
9
+ action :get do
10
+ verb :get
11
+ version :v2
12
+ path '/invitations/:id'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ module Freefeed
2
+ class Notification < ResourceKitling::Resource
3
+ actions do
4
+ action :all do
5
+ verb :get
6
+ version :v2
7
+ path '/notifications'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module Freefeed
2
+ class Password < ResourceKitling::Resource
3
+ actions do
4
+ action :create do
5
+ verb :post
6
+ version :v1
7
+ path '/passwords'
8
+ end
9
+ action :update do
10
+ verb :put
11
+ version :v1
12
+ path '/passwords/:token'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,61 @@
1
+ module Freefeed
2
+ class Post < ResourceKitling::Resource
3
+ actions do
4
+ action :create do
5
+ verb :post
6
+ version :v1
7
+ path '/posts'
8
+ end
9
+ action :get do
10
+ verb :get
11
+ version :v2
12
+ path '/posts/:id'
13
+ end
14
+ action :update do
15
+ verb :put
16
+ version :v1
17
+ path '/posts/:id'
18
+ end
19
+ action :destroy do
20
+ verb :delete
21
+ version :v1
22
+ path '/posts/:id'
23
+ end
24
+ action :like do
25
+ verb :post
26
+ version :v1
27
+ path '/posts/:id/like'
28
+ end
29
+ action :unlike do
30
+ verb :post
31
+ version :v1
32
+ path '/posts/:id/unlike'
33
+ end
34
+ action :hide do
35
+ verb :post
36
+ version :v1
37
+ path '/posts/:id/hide'
38
+ end
39
+ action :unhide do
40
+ verb :post
41
+ version :v1
42
+ path '/posts/:id/unhide'
43
+ end
44
+ action :disable_comments do
45
+ verb :post
46
+ version :v1
47
+ path '/posts/:id/disableComments'
48
+ end
49
+ action :enable_comments do
50
+ verb :post
51
+ version :v1
52
+ path '/posts/:id/enableComments'
53
+ end
54
+ action :opengraph do
55
+ verb :get
56
+ version :v2
57
+ path '/posts-opengraph/:id'
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,11 @@
1
+ module Freefeed
2
+ class Request < ResourceKitling::Resource
3
+ actions do
4
+ action :revoke do
5
+ verb :post
6
+ version :v2
7
+ path '/requests/:username/revoke'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Freefeed
2
+ class Search < ResourceKitling::Resource
3
+ actions do
4
+ action :search do
5
+ verb :get
6
+ version :v2
7
+ path '/search'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Freefeed
2
+ class Session < ResourceKitling::Resource
3
+ actions do
4
+ action :create do
5
+ verb :post
6
+ version :v1
7
+ path '/session'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Freefeed
2
+ class Stat < ResourceKitling::Resource
3
+ actions do
4
+ action :stats do
5
+ verb :get
6
+ version :v2
7
+ path '/stats'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module Freefeed
2
+ class Summary < ResourceKitling::Resource
3
+ actions do
4
+ action :general do
5
+ verb :get
6
+ version :v2
7
+ path '/summary/:days'
8
+ end
9
+ action :by_user do
10
+ verb :get
11
+ version :v2
12
+ path '/summary/:username/:days'
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,41 @@
1
+ module Freefeed
2
+ class Timeline < ResourceKitling::Resource
3
+ actions do
4
+ action :bestof do
5
+ verb :get
6
+ version :v2
7
+ path '/bestof'
8
+ end
9
+ action :home do
10
+ verb :get
11
+ version :v2
12
+ path '/timelines/home'
13
+ end
14
+ action :discussions do
15
+ verb :get
16
+ version :v2
17
+ path '/timelines/filter/discussions'
18
+ end
19
+ action :directs do
20
+ verb :get
21
+ version :v2
22
+ path '/timelines/filter/directs'
23
+ end
24
+ action :posts do
25
+ verb :get
26
+ version :v2
27
+ path '/timelines/:username'
28
+ end
29
+ action :likes do
30
+ verb :get
31
+ version :v2
32
+ path '/timelines/:username/likes'
33
+ end
34
+ action :comments do
35
+ verb :get
36
+ version :v2
37
+ path '/timelines/:username/comments'
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,121 @@
1
+ module Freefeed
2
+ class User < ResourceKitling::Resource
3
+ actions do
4
+ action :create do
5
+ verb :post
6
+ version :v1
7
+ path '/users'
8
+ end
9
+ action :sudo_create do
10
+ verb :post
11
+ version :v1
12
+ path '/users/sudo'
13
+ end
14
+ action :send_request do
15
+ verb :post
16
+ version :v1
17
+ path '/users/:username/sendRequest'
18
+ end
19
+ action :revoke_request do
20
+ verb :post
21
+ version :v2
22
+ path '/requests/:username/revoke'
23
+ end
24
+ action :accept_request do
25
+ verb :post
26
+ version :v1
27
+ path '/users/acceptRequest/:username'
28
+ end
29
+ action :reject_request do
30
+ verb :post
31
+ version :v1
32
+ path '/users/rejectRequest/:username'
33
+ end
34
+ action :unsubscribe_from_me do
35
+ verb :post
36
+ version :v1
37
+ path '/users/:username/unsubscribeFromMe'
38
+ end
39
+ action :show do
40
+ verb :get
41
+ version :v1
42
+ path '/users/:username'
43
+ end
44
+ action :update_password do
45
+ verb :put
46
+ version :v1
47
+ path '/users/updatePassword'
48
+ end
49
+ action :update_profile_picture do
50
+ verb :post
51
+ version :v1
52
+ path '/users/updateProfilePicture'
53
+ end
54
+ action :update do
55
+ verb :put
56
+ version :v1
57
+ path '/users/:id'
58
+ end
59
+ action :ban do
60
+ verb :post
61
+ version :v1
62
+ path '/users/:username/ban'
63
+ end
64
+ action :unban do
65
+ verb :post
66
+ version :v1
67
+ path '/users/:username/unban'
68
+ end
69
+ action :subscribe do
70
+ verb :post
71
+ version :v1
72
+ path '/users/:username/subscribe'
73
+ end
74
+ action :unsubscribe do
75
+ verb :post
76
+ version :v1
77
+ path '/users/:username/unsubscribe'
78
+ end
79
+ action :subscribers do
80
+ verb :get
81
+ version :v1
82
+ path '/users/:username/subscribers'
83
+ end
84
+ action :subscriptions do
85
+ verb :get
86
+ version :v1
87
+ path '/users/:username/subscriptions'
88
+ end
89
+ action :blocked do
90
+ verb :get
91
+ version :v2
92
+ path '/users/blockedByMe'
93
+ end
94
+ action :unread_directs_number do
95
+ verb :get
96
+ version :v2
97
+ path '/users/getUnreadDirectsNumber'
98
+ end
99
+ action :unread_notifications_number do
100
+ verb :get
101
+ version :v2
102
+ path '/users/getUnreadNotificationsNumber'
103
+ end
104
+ action :mark_all_directs_as_read do
105
+ verb :get
106
+ version :v2
107
+ path '/users/markAllDirectsAsRead'
108
+ end
109
+ action :mark_all_notifications_as_read do
110
+ verb :post
111
+ version :v2
112
+ path '/users/markAllNotificationsAsRead'
113
+ end
114
+ action :whoami do
115
+ verb :get
116
+ version :v2
117
+ path '/users/whoami'
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,17 @@
1
+ require 'dry-types'
2
+ require 'dry-struct'
3
+ module Freefeed
4
+ module Types
5
+ class Bookmarklet < Dry::Struct
6
+ attribute :title, Types::Body
7
+ attribute :comment, Types::Strict::String.meta(omittable: true)
8
+ attribute :image, Types::Strict::String.meta(omittable: true)
9
+ attribute :images, Types::Strict::Array.of(
10
+ Types::Strict::String
11
+ ).meta(omittable: true)
12
+ attribute :meta, Types::Hash.schema(
13
+ feeds: Types::AccountName | Types::Feeds
14
+ ).meta(omittable: true)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ require 'dry-types'
2
+ require 'dry-struct'
3
+ module Freefeed
4
+ module Types
5
+ class CommentCreate < Dry::Struct
6
+ attribute :comment, Types::Hash.schema(
7
+ body: Types::Body,
8
+ postId: Types::UID
9
+ )
10
+ end
11
+
12
+ class CommentUpdate < Dry::Struct
13
+ attribute :comment, Types::Hash.schema(body: Types::Body)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,24 @@
1
+ require 'dry-types'
2
+ require 'dry-struct'
3
+ module Freefeed
4
+ module Types
5
+ class PostCreate < Dry::Struct
6
+ attribute :post, Types::Hash.schema(
7
+ body: Types::Body,
8
+ attachments: Types::Attachments.meta(omittable: true)
9
+ )
10
+ attribute :meta, Types::Hash.schema(
11
+ commentsDisabled: Types::Strict::Bool.default(false),
12
+ feeds: Types::AccountName | Types::Feeds
13
+ )
14
+ end
15
+
16
+ class PostUpdate < Dry::Struct
17
+ attribute :post, Types::Hash.schema(
18
+ body: Types::Body.meta(omittable: true),
19
+ attachments: Types::Attachments.meta(omittable: true),
20
+ feeds: Types::Feeds.meta(omittable: true)
21
+ )
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ require 'dry-types'
2
+ require 'dry-struct'
3
+ module Freefeed
4
+ module Types
5
+ include Dry::Types.module
6
+
7
+ Body = Types::Strict::String.constrained(min_size: 1, format: %r{\S+})
8
+ UID = Types::Strict::String.constrained(
9
+ format: %r{^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$}
10
+ )
11
+ UserName = Types::Strict::String.constrained(
12
+ min_size: 3, max_size: 25, format: %r{^[A-Za-z0-9]+$}
13
+ )
14
+ GroupName = Types::Strict::String.constrained(
15
+ min_size: 3, max_size: 25, format: %r{^[A-Za-z0-9]+(-[a-zA-Z0-9]+)*$}
16
+ )
17
+ AccountName = UserName | GroupName
18
+ Attachments = Types::Strict::Array.of(UID)
19
+ Feeds = Types::Strict::Array.of(AccountName)
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module Freefeed
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/freefeed.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'logger'
4
+ require 'multi_json'
5
+ require 'resource_kitling'
6
+ require 'freefeed/version'
7
+ require 'freefeed/exceptions'
8
+ require 'freefeed/client'
9
+ require 'active_support/inflector'
10
+
11
+ require 'freefeed/resources/archive'
12
+ require 'freefeed/resources/attachment'
13
+ require 'freefeed/resources/bookmarklet'
14
+ require 'freefeed/resources/comment'
15
+ require 'freefeed/resources/group'
16
+ require 'freefeed/resources/invitation'
17
+ require 'freefeed/resources/notification'
18
+ require 'freefeed/resources/password'
19
+ require 'freefeed/resources/post'
20
+ require 'freefeed/resources/request'
21
+ require 'freefeed/resources/search'
22
+ require 'freefeed/resources/session'
23
+ require 'freefeed/resources/stat'
24
+ require 'freefeed/resources/summary'
25
+ require 'freefeed/resources/timeline'
26
+ require 'freefeed/resources/user'
27
+
28
+ require 'freefeed/types'
29
+ require 'freefeed/types/bookmarklet'
30
+ require 'freefeed/types/comment'
31
+ require 'freefeed/types/post'
32
+
33
+ ResourceKitling::Resource.subclasses.each do |sc|
34
+ mn = sc.to_s.downcase.split('::').last.pluralize
35
+ if Freefeed::Client.method_defined?(mn)
36
+ raise(
37
+ ArgumentError,
38
+ "Method '#{mn}' is already defined on Freefeed::Client"
39
+ )
40
+ end
41
+ Freefeed::Client.send(:define_method, mn) do
42
+ instance_variable_get("@#{mn}") || instance_variable_set(
43
+ "@#{mn}", sc.new(client: self)
44
+ )
45
+ end
46
+ end
@@ -0,0 +1,101 @@
1
+ module ResourceKitling
2
+ require 'forwardable'
3
+ class ActionCollection
4
+ extend Forwardable
5
+ def_delegators :@collection, :find, :<<, :each, :include?
6
+ def initialize
7
+ @collection = []
8
+ end
9
+
10
+ def action(name, &block)
11
+ action = Action.new(name)
12
+ action.instance_eval(&block) if block_given?
13
+ action.tap { |a| @collection << a }
14
+ end
15
+ end
16
+
17
+ class Action
18
+ attr_reader :name
19
+
20
+ def initialize(name)
21
+ @name = name
22
+ @verb = :get
23
+ @version = 'v1'
24
+ @path = path
25
+ end
26
+
27
+ def verb(v = nil)
28
+ @verb = v if v
29
+ @verb
30
+ end
31
+
32
+ def version(v = nil)
33
+ @version = v if v
34
+ @version
35
+ end
36
+
37
+ def path(path = nil, &block)
38
+ raise "You must pass either a block or a string for paths" if path and block_given?
39
+ @path = path if path
40
+ @path = block if block_given?
41
+ @path
42
+ end
43
+
44
+ def generated_path(values = {})
45
+ values.inject("/#{version}/#{path}") do |np, (key, value)|
46
+ np.gsub(":#{key}", value.to_s)
47
+ end
48
+ end
49
+ end
50
+ class Resource
51
+ class << self
52
+ attr_accessor :_actions
53
+ attr_reader :subclasses
54
+ def inherited(subclass)
55
+ superclass.inherited(subclass) if superclass.respond_to?(:inherited)
56
+ @subclasses ||= []
57
+ @subclasses << subclass
58
+ end
59
+ end
60
+
61
+ def self.actions(&block)
62
+ self._actions ||= ActionCollection.new
63
+ if block_given?
64
+ self._actions.instance_eval(&block)
65
+ # MethodFactory.construct(self, self._actions)
66
+ self._actions.each do |action|
67
+ if method_defined?(action.name)
68
+ raise(
69
+ ArgumentError,
70
+ "Action '#{action.name}' is already defined on `#{self}`"
71
+ )
72
+ end
73
+ method_block = method_for_action(action)
74
+ send(:define_method, action.name, &method_block)
75
+ end
76
+ end
77
+ self._actions
78
+ end
79
+
80
+ def self.method_for_action(action)
81
+ Proc.new do |*args|
82
+ pathopts = action.path.include?(':') ? args.shift : {}
83
+ payload = args.shift
84
+ payload = payload.to_h if payload.respond_to?(:to_h)
85
+ client.call!(
86
+ action.verb, action.generated_path(pathopts), payload, *args
87
+ )
88
+ end
89
+ end
90
+
91
+ def actions
92
+ self.class.actions
93
+ end
94
+
95
+ attr_reader :client
96
+
97
+ def initialize(client: nil)
98
+ @client = client
99
+ end
100
+ end
101
+ end
metadata ADDED
@@ -0,0 +1,207 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: freefeed-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ilia Zemskov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-10-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: multi_json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: dry-types
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: dry-struct
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: bundler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.13'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.13'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.0'
139
+ description:
140
+ email:
141
+ - me@fetsh.me
142
+ executables:
143
+ - console
144
+ - setup
145
+ extensions: []
146
+ extra_rdoc_files: []
147
+ files:
148
+ - ".gitignore"
149
+ - ".rspec"
150
+ - ".travis.yml"
151
+ - Gemfile
152
+ - LICENSE.txt
153
+ - README.md
154
+ - Rakefile
155
+ - bin/console
156
+ - bin/setup
157
+ - freefeed.gemspec
158
+ - lib/freefeed.rb
159
+ - lib/freefeed/client.rb
160
+ - lib/freefeed/exceptions.rb
161
+ - lib/freefeed/resources/archive.rb
162
+ - lib/freefeed/resources/attachment.rb
163
+ - lib/freefeed/resources/bookmarklet.rb
164
+ - lib/freefeed/resources/comment.rb
165
+ - lib/freefeed/resources/group.rb
166
+ - lib/freefeed/resources/invitation.rb
167
+ - lib/freefeed/resources/notification.rb
168
+ - lib/freefeed/resources/password.rb
169
+ - lib/freefeed/resources/post.rb
170
+ - lib/freefeed/resources/request.rb
171
+ - lib/freefeed/resources/search.rb
172
+ - lib/freefeed/resources/session.rb
173
+ - lib/freefeed/resources/stat.rb
174
+ - lib/freefeed/resources/summary.rb
175
+ - lib/freefeed/resources/timeline.rb
176
+ - lib/freefeed/resources/user.rb
177
+ - lib/freefeed/types.rb
178
+ - lib/freefeed/types/bookmarklet.rb
179
+ - lib/freefeed/types/comment.rb
180
+ - lib/freefeed/types/post.rb
181
+ - lib/freefeed/version.rb
182
+ - lib/resource_kitling.rb
183
+ homepage: https://github.com/fetsh/freefeed-client
184
+ licenses:
185
+ - MIT
186
+ metadata: {}
187
+ post_install_message:
188
+ rdoc_options: []
189
+ require_paths:
190
+ - lib
191
+ required_ruby_version: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ required_rubygems_version: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ">="
199
+ - !ruby/object:Gem::Version
200
+ version: '0'
201
+ requirements: []
202
+ rubyforge_project:
203
+ rubygems_version: 2.5.2.1
204
+ signing_key:
205
+ specification_version: 4
206
+ summary: Ruby wrapper for FreeFeed API.
207
+ test_files: []