discourse_zendesk_api 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +176 -0
  3. data/lib/zendesk_api/actions.rb +334 -0
  4. data/lib/zendesk_api/association.rb +195 -0
  5. data/lib/zendesk_api/associations.rb +212 -0
  6. data/lib/zendesk_api/client.rb +243 -0
  7. data/lib/zendesk_api/collection.rb +474 -0
  8. data/lib/zendesk_api/configuration.rb +79 -0
  9. data/lib/zendesk_api/core_ext/inflection.rb +3 -0
  10. data/lib/zendesk_api/delegator.rb +5 -0
  11. data/lib/zendesk_api/error.rb +49 -0
  12. data/lib/zendesk_api/helpers.rb +24 -0
  13. data/lib/zendesk_api/lru_cache.rb +39 -0
  14. data/lib/zendesk_api/middleware/request/encode_json.rb +26 -0
  15. data/lib/zendesk_api/middleware/request/etag_cache.rb +52 -0
  16. data/lib/zendesk_api/middleware/request/raise_rate_limited.rb +31 -0
  17. data/lib/zendesk_api/middleware/request/retry.rb +59 -0
  18. data/lib/zendesk_api/middleware/request/upload.rb +86 -0
  19. data/lib/zendesk_api/middleware/request/url_based_access_token.rb +26 -0
  20. data/lib/zendesk_api/middleware/response/callback.rb +21 -0
  21. data/lib/zendesk_api/middleware/response/deflate.rb +17 -0
  22. data/lib/zendesk_api/middleware/response/gzip.rb +19 -0
  23. data/lib/zendesk_api/middleware/response/logger.rb +44 -0
  24. data/lib/zendesk_api/middleware/response/parse_iso_dates.rb +30 -0
  25. data/lib/zendesk_api/middleware/response/parse_json.rb +23 -0
  26. data/lib/zendesk_api/middleware/response/raise_error.rb +26 -0
  27. data/lib/zendesk_api/middleware/response/sanitize_response.rb +11 -0
  28. data/lib/zendesk_api/resource.rb +208 -0
  29. data/lib/zendesk_api/resources.rb +971 -0
  30. data/lib/zendesk_api/sideloading.rb +58 -0
  31. data/lib/zendesk_api/silent_mash.rb +8 -0
  32. data/lib/zendesk_api/track_changes.rb +85 -0
  33. data/lib/zendesk_api/trackie.rb +13 -0
  34. data/lib/zendesk_api/verbs.rb +65 -0
  35. data/lib/zendesk_api/version.rb +3 -0
  36. data/lib/zendesk_api.rb +4 -0
  37. data/util/resource_handler.rb +74 -0
  38. data/util/verb_handler.rb +16 -0
  39. metadata +166 -0
@@ -0,0 +1,971 @@
1
+ module ZendeskAPI
2
+ # @internal The following are redefined later, but needed by some circular resources (e.g. Ticket -> User, User -> Ticket)
3
+
4
+ class Ticket < Resource; end
5
+ class User < Resource; end
6
+ class UserRelated < DataResource; end
7
+ class Category < Resource; end
8
+ class OrganizationMembership < ReadResource; end
9
+ class OrganizationSubscription < ReadResource; end
10
+
11
+ # @internal Begin actual Resource definitions
12
+
13
+ class RecipientAddress < Resource; end
14
+
15
+ class Locale < ReadResource; end
16
+
17
+ class CustomRole < DataResource; end
18
+
19
+ class Role < DataResource
20
+ def to_param
21
+ name
22
+ end
23
+ end
24
+
25
+ class Topic < Resource
26
+ class << self
27
+ def resource_path
28
+ "community/topics"
29
+ end
30
+ end
31
+ end
32
+
33
+ class Bookmark < Resource; end
34
+ class Ability < DataResource; end
35
+ class Group < Resource; end
36
+ class SharingAgreement < ReadResource; end
37
+ class JobStatus < ReadResource; end
38
+
39
+ class Session < ReadResource
40
+ include Destroy
41
+ end
42
+
43
+ class Tag < DataResource
44
+ include Update
45
+ include Destroy
46
+
47
+ alias :name :id
48
+ alias :to_param :id
49
+
50
+ def path(opts = {})
51
+ raise "tags must have parent resource" unless association.options.parent
52
+ super(opts.merge(:with_parent => true, :with_id => false))
53
+ end
54
+
55
+ def changed?
56
+ true
57
+ end
58
+
59
+ def destroy!
60
+ super do |req|
61
+ req.body = attributes_for_save
62
+ end
63
+ end
64
+
65
+ module Update
66
+ def _save(method = :save)
67
+ return self unless @resources
68
+
69
+ @client.connection.post(path) do |req|
70
+ req.body = { :tags => @resources.reject(&:destroyed?).map(&:id) }
71
+ end
72
+
73
+ true
74
+ rescue Faraday::ClientError => e
75
+ if method == :save
76
+ false
77
+ else
78
+ raise e
79
+ end
80
+ end
81
+ end
82
+
83
+ def attributes_for_save
84
+ { self.class.resource_name => [id] }
85
+ end
86
+ end
87
+
88
+ class Attachment < ReadResource
89
+ def initialize(client, attributes = {})
90
+ attributes[:file] ||= attributes.delete(:id)
91
+
92
+ super
93
+ end
94
+
95
+ def save
96
+ upload = Upload.create!(@client, attributes)
97
+ self.token = upload.token
98
+ end
99
+
100
+ def to_param
101
+ token
102
+ end
103
+ end
104
+
105
+ class Upload < Data
106
+ include Create
107
+ include Destroy
108
+
109
+ def id
110
+ token
111
+ end
112
+
113
+ has_many Attachment
114
+
115
+ private
116
+
117
+ def attributes_for_save
118
+ attributes.changes
119
+ end
120
+ end
121
+
122
+ class MobileDevice < Resource
123
+ # Clears this devices' badge
124
+ put :clear_badge
125
+ end
126
+
127
+ class OrganizationRelated < DataResource; end
128
+
129
+ class Organization < Resource
130
+ extend CreateMany
131
+ extend CreateOrUpdate
132
+ extend DestroyMany
133
+
134
+ has Ability, :inline => true
135
+ has Group
136
+ has :related, :class => OrganizationRelated
137
+
138
+ has_many Ticket
139
+ has_many User
140
+ has_many Tag, :extend => Tag::Update, :inline => :create
141
+ has_many OrganizationMembership
142
+ has_many :subscriptions, class: OrganizationSubscription
143
+
144
+ # Gets a incremental export of organizations from the start_time until now.
145
+ # @param [Client] client The {Client} object to be used
146
+ # @param [Integer] start_time The start_time parameter
147
+ # @return [Collection] Collection of {Organization}
148
+ def self.incremental_export(client, start_time)
149
+ ZendeskAPI::Collection.new(client, self, :path => "incremental/organizations?start_time=#{start_time.to_i}")
150
+ end
151
+ end
152
+
153
+ class Brand < Resource
154
+ def destroy!
155
+ self.active = false
156
+ save!
157
+
158
+ super
159
+ end
160
+ end
161
+
162
+ class OrganizationMembership < ReadResource
163
+ include Create
164
+ include Destroy
165
+
166
+ extend CreateMany
167
+ extend DestroyMany
168
+
169
+ has User
170
+ has Organization
171
+ end
172
+
173
+ class OrganizationSubscription < ReadResource
174
+ include Create
175
+ include Destroy
176
+
177
+ has User
178
+ has Organization
179
+ end
180
+
181
+ class Category < Resource
182
+ class << self
183
+ def resource_path
184
+ "help_center/categories"
185
+ end
186
+ end
187
+
188
+ class Section < Resource
189
+ end
190
+
191
+ has_many Section
192
+ end
193
+
194
+ class Section < ReadResource
195
+ class << self
196
+ def resource_path
197
+ "help_center/sections"
198
+ end
199
+ end
200
+
201
+ has Category
202
+
203
+ class Article < Resource
204
+ end
205
+
206
+ has_many Article
207
+ end
208
+
209
+ class Article < ReadResource
210
+ class << self
211
+ def resource_path
212
+ "help_center/articles"
213
+ end
214
+ end
215
+ end
216
+
217
+ class TopicSubscription < Resource
218
+ class << self
219
+ def model_key
220
+ "subscriptions"
221
+ end
222
+ end
223
+
224
+ has Topic
225
+ has User
226
+
227
+ def path(options = {})
228
+ super(options.merge(:with_parent => true))
229
+ end
230
+ end
231
+
232
+ class Topic < Resource
233
+ has_many :subscriptions, :class => TopicSubscription, :inline => true
234
+ has_many Tag, :extend => Tag::Update, :inline => :create
235
+ has_many Attachment
236
+ has_many :uploads, :class => Attachment, :inline => true
237
+ end
238
+
239
+ class Activity < Resource
240
+ has User
241
+ has :actor, :class => User
242
+ end
243
+
244
+ class Setting < UpdateResource
245
+ attr_reader :on
246
+
247
+ def initialize(client, attributes = {})
248
+ # Try and find the root key
249
+ @on = (attributes.keys.map(&:to_s) - %w{association options}).first
250
+
251
+ # Make what's inside that key the root attributes
252
+ attributes.merge!(attributes.delete(@on))
253
+
254
+ super
255
+ end
256
+
257
+ def new_record?
258
+ false
259
+ end
260
+
261
+ def path(options = {})
262
+ super(options.merge(:with_parent => true))
263
+ end
264
+
265
+ def attributes_for_save
266
+ { self.class.resource_name => { @on => attributes.changes } }
267
+ end
268
+ end
269
+
270
+ class SatisfactionRating < ReadResource
271
+ has :assignee, :class => User
272
+ has :requester, :class => User
273
+ has Ticket
274
+ has Group
275
+ end
276
+
277
+ class Search
278
+ class Result < Data; end
279
+
280
+ # Creates a search collection
281
+ def self.search(client, options = {})
282
+ unless (%w{query external_id} & options.keys.map(&:to_s)).any?
283
+ warn "you have not specified a query for this search"
284
+ end
285
+
286
+ ZendeskAPI::Collection.new(client, self, options)
287
+ end
288
+
289
+ # Quack like a Resource
290
+ # Creates the correct resource class from the result_type passed in
291
+ def self.new(client, attributes)
292
+ result_type = attributes["result_type"]
293
+
294
+ if result_type
295
+ result_type = ZendeskAPI::Helpers.modulize_string(result_type)
296
+ klass = ZendeskAPI.const_get(result_type) rescue nil
297
+ end
298
+
299
+ (klass || Result).new(client, attributes)
300
+ end
301
+
302
+ class << self
303
+ def resource_name
304
+ "search"
305
+ end
306
+
307
+ alias :resource_path :resource_name
308
+
309
+ def model_key
310
+ "results"
311
+ end
312
+ end
313
+ end
314
+
315
+ class Request < Resource
316
+ class Comment < DataResource
317
+ include Save
318
+
319
+ has_many :uploads, :class => Attachment, :inline => true
320
+ has :author, :class => User
321
+
322
+ def save
323
+ if new_record?
324
+ save_associations
325
+ true
326
+ else
327
+ false
328
+ end
329
+ end
330
+
331
+ alias :save! :save
332
+ end
333
+
334
+ has Comment, :inline => true
335
+ has_many Comment
336
+
337
+ has Organization
338
+ has Group
339
+ has :requester, :class => User
340
+ end
341
+
342
+ class AnonymousRequest < CreateResource
343
+ def self.singular_resource_name
344
+ 'request'
345
+ end
346
+
347
+ namespace 'portal'
348
+ end
349
+
350
+ class TicketField < Resource; end
351
+
352
+ class TicketMetric < DataResource
353
+ include Read
354
+ end
355
+
356
+ class TicketRelated < DataResource; end
357
+
358
+ class TicketEvent < DataResource
359
+ class Event < Data; end
360
+
361
+ has_many :child_events, :class => Event
362
+ has Ticket
363
+ has :updater, :class => User
364
+
365
+ # Gets a incremental export of ticket events from the start_time until now.
366
+ # @param [Client] client The {Client} object to be used
367
+ # @param [Integer] start_time The start_time parameter
368
+ # @return [Collection] Collection of {TicketEvent}
369
+ def self.incremental_export(client, start_time)
370
+ ZendeskAPI::Collection.new(client, self, :path => "incremental/ticket_events?start_time=#{start_time.to_i}")
371
+ end
372
+ end
373
+
374
+ class Ticket < Resource
375
+ extend CreateMany
376
+ extend UpdateMany
377
+ extend DestroyMany
378
+
379
+ class Audit < DataResource
380
+ class Event < Data
381
+ has :author, :class => User
382
+ end
383
+
384
+ put :trust
385
+
386
+ # need this to support SideLoading
387
+ has :author, :class => User
388
+
389
+ has_many Event
390
+ end
391
+
392
+ class Comment < DataResource
393
+ include Save
394
+
395
+ has_many :uploads, :class => Attachment, :inline => true
396
+ has :author, :class => User
397
+
398
+ def save
399
+ if new_record?
400
+ save_associations
401
+ true
402
+ else
403
+ false
404
+ end
405
+ end
406
+
407
+ alias :save! :save
408
+ end
409
+
410
+ class SatisfactionRating < CreateResource
411
+ class << self
412
+ alias :resource_name :singular_resource_name
413
+ end
414
+ end
415
+
416
+ put :mark_as_spam
417
+ post :merge
418
+
419
+ has :requester, :class => User, :inline => :create
420
+ has :submitter, :class => User
421
+ has :assignee, :class => User
422
+
423
+ has_many :collaborators, :class => User, :inline => true, :extend => (Module.new do
424
+ def to_param
425
+ map(&:id)
426
+ end
427
+ end)
428
+
429
+ has_many Audit
430
+ has :metrics, :class => TicketMetric
431
+ has Group
432
+ has Organization
433
+ has Brand
434
+ has :related, :class => TicketRelated
435
+
436
+ has Comment, :inline => true
437
+ has_many Comment
438
+
439
+ has :last_comment, :class => Comment, :inline => true
440
+ has_many :last_comments, :class => Comment, :inline => true
441
+
442
+ has_many Tag, :extend => Tag::Update, :inline => :create
443
+
444
+ has_many :incidents, :class => Ticket
445
+
446
+ # Gets a incremental export of tickets from the start_time until now.
447
+ # @param [Client] client The {Client} object to be used
448
+ # @param [Integer] start_time The start_time parameter
449
+ # @return [Collection] Collection of {Ticket}
450
+ def self.incremental_export(client, start_time)
451
+ ZendeskAPI::Collection.new(client, self, :path => "incremental/tickets?start_time=#{start_time.to_i}")
452
+ end
453
+
454
+ # Imports a ticket through the imports/tickets endpoint using save!
455
+ # @param [Client] client The {Client} object to be used
456
+ # @param [Hash] attributes The attributes to create.
457
+ # @return [Ticket] Created object or nil
458
+ def self.import!(client, attributes)
459
+ new(client, attributes).tap do |ticket|
460
+ ticket.save!(:path => "imports/tickets")
461
+ end
462
+ end
463
+
464
+ # Imports a ticket through the imports/tickets endpoint
465
+ # @param [Client] client The {Client} object to be used
466
+ # @param [Hash] attributes The attributes to create.
467
+ # @return [Ticket] Created object or nil
468
+ def self.import(client, attributes)
469
+ ticket = new(client, attributes)
470
+ return unless ticket.save(:path => "imports/tickets")
471
+ ticket
472
+ end
473
+ end
474
+
475
+ class SuspendedTicket < ReadResource
476
+ include Destroy
477
+
478
+ # Recovers this suspended ticket to an actual ticket
479
+ put :recover
480
+ end
481
+
482
+ class DeletedTicket < ReadResource
483
+ include Destroy
484
+ extend DestroyMany
485
+
486
+ # Restores this previously deleted ticket to an actual ticket
487
+ put :restore
488
+ put :restore_many
489
+ end
490
+
491
+ class UserViewRow < DataResource
492
+ has User
493
+ def self.model_key
494
+ "rows"
495
+ end
496
+ end
497
+
498
+ class ViewRow < DataResource
499
+ has Ticket
500
+
501
+ # @internal Optional columns
502
+
503
+ has Group
504
+ has :assignee, :class => User
505
+ has :requester, :class => User
506
+ has :submitter, :class => User
507
+ has Organization
508
+
509
+ def self.model_key
510
+ "rows"
511
+ end
512
+ end
513
+
514
+ class RuleExecution < Data
515
+ has_many :custom_fields, :class => TicketField
516
+ end
517
+
518
+ class ViewCount < DataResource; end
519
+
520
+ class Rule < Resource
521
+ private
522
+
523
+ def attributes_for_save
524
+ to_save = [:conditions, :actions, :output].inject({}) { |h, k| h.merge(k => send(k)) }
525
+ { self.class.singular_resource_name.to_sym => attributes.changes.merge(to_save) }
526
+ end
527
+ end
528
+
529
+ class TriggerCategory < Resource; end
530
+
531
+ module Conditions
532
+ def all_conditions=(all_conditions)
533
+ self.conditions ||= {}
534
+ self.conditions[:all] = all_conditions
535
+ end
536
+
537
+ def any_conditions=(any_conditions)
538
+ self.conditions ||= {}
539
+ self.conditions[:any] = any_conditions
540
+ end
541
+
542
+ def add_all_condition(field, operator, value)
543
+ self.conditions ||= {}
544
+ self.conditions[:all] ||= []
545
+ self.conditions[:all] << { :field => field, :operator => operator, :value => value }
546
+ end
547
+
548
+ def add_any_condition(field, operator, value)
549
+ self.conditions ||= {}
550
+ self.conditions[:any] ||= []
551
+ self.conditions[:any] << { :field => field, :operator => operator, :value => value }
552
+ end
553
+ end
554
+
555
+ module Actions
556
+ def add_action(field, value)
557
+ self.actions ||= []
558
+ self.actions << { :field => field, :value => value }
559
+ end
560
+ end
561
+
562
+ class View < Rule
563
+ include Conditions
564
+
565
+ has_many :tickets, :class => Ticket
566
+ has_many :feed, :class => Ticket, :path => "feed"
567
+
568
+ has_many :rows, :class => ViewRow, :path => "execute"
569
+ has :execution, :class => RuleExecution
570
+ has ViewCount, :path => "count"
571
+
572
+ def add_column(column)
573
+ columns = execution.columns.map(&:id)
574
+ columns << column
575
+ self.columns = columns
576
+ end
577
+
578
+ def columns=(columns)
579
+ self.output ||= {}
580
+ self.output[:columns] = columns
581
+ end
582
+
583
+ def self.preview(client, options = {})
584
+ Collection.new(client, ViewRow, options.merge(:path => "views/preview", :verb => :post))
585
+ end
586
+ end
587
+
588
+ class Trigger < Rule
589
+ include Conditions
590
+ include Actions
591
+
592
+ has :execution, :class => RuleExecution
593
+ end
594
+
595
+ class Automation < Rule
596
+ include Conditions
597
+ include Actions
598
+
599
+ has :execution, :class => RuleExecution
600
+ end
601
+
602
+ class Macro < Rule
603
+ include Actions
604
+
605
+ has :execution, :class => RuleExecution
606
+
607
+ # Returns the update to a ticket that happens when a macro will be applied.
608
+ # @param [Ticket] ticket Optional {Ticket} to apply this macro to.
609
+ # @raise [Faraday::ClientError] Raised for any non-200 response.
610
+ def apply!(ticket = nil)
611
+ path = "#{self.path}/apply"
612
+
613
+ if ticket
614
+ path = "#{ticket.path}/#{path}"
615
+ end
616
+
617
+ response = @client.connection.get(path)
618
+ SilentMash.new(response.body.fetch("result", {}))
619
+ end
620
+
621
+ # Returns the update to a ticket that happens when a macro will be applied.
622
+ # @param [Ticket] ticket Optional {Ticket} to apply this macro to
623
+ def apply(ticket = nil)
624
+ apply!(ticket)
625
+ rescue Faraday::ClientError
626
+ SilentMash.new
627
+ end
628
+ end
629
+
630
+ class UserView < Rule
631
+ def self.preview(client, options = {})
632
+ Collection.new(client, UserViewRow, options.merge!(:path => "user_views/preview", :verb => :post))
633
+ end
634
+ end
635
+
636
+ class GroupMembership < Resource
637
+ extend CreateMany
638
+ extend DestroyMany
639
+
640
+ has User
641
+ has Group
642
+ end
643
+
644
+ class User < Resource
645
+ extend CreateMany
646
+ extend UpdateMany
647
+ extend CreateOrUpdate
648
+ extend CreateOrUpdateMany
649
+ extend DestroyMany
650
+
651
+ class GroupMembership < Resource
652
+ put :make_default
653
+ end
654
+
655
+ class Identity < Resource
656
+ # Makes this identity the primary one bumping all other identities down one
657
+ put :make_primary
658
+
659
+ # Verifies this identity
660
+ put :verify
661
+
662
+ # Requests verification for this identity
663
+ put :request_verification
664
+ end
665
+
666
+ any :password
667
+
668
+ # Set a user's password
669
+ def set_password(opts = {})
670
+ password(opts.merge(:verb => :post))
671
+ end
672
+
673
+ # Change a user's password
674
+ def change_password(opts = {})
675
+ password(opts.merge(:verb => :put))
676
+ end
677
+
678
+ # Set a user's password
679
+ def set_password!(opts = {})
680
+ password!(opts.merge(:verb => :post))
681
+ end
682
+
683
+ # Change a user's password
684
+ def change_password!(opts = {})
685
+ password!(opts.merge(:verb => :put))
686
+ end
687
+
688
+ # Gets a incremental export of users from the start_time until now.
689
+ # @param [Client] client The {Client} object to be used
690
+ # @param [Integer] start_time The start_time parameter
691
+ # @return [Collection] Collection of {User}
692
+ def self.incremental_export(client, start_time)
693
+ ZendeskAPI::Collection.new(client, self, :path => "incremental/users?start_time=#{start_time.to_i}")
694
+ end
695
+
696
+ has Organization
697
+
698
+ class Session < Resource
699
+ end
700
+
701
+ class CurrentSession < SingularResource
702
+ class << self
703
+ def singular_resource_name
704
+ 'session'
705
+ end
706
+
707
+ alias :resource_name :singular_resource_name
708
+ end
709
+ end
710
+
711
+ has_many Session
712
+
713
+ def current_session
714
+ ZendeskAPI::User::CurrentSession.find(@client, :user_id => 'me')
715
+ end
716
+
717
+ delete :logout
718
+
719
+ def clear_sessions!
720
+ @client.connection.delete(path + '/sessions')
721
+ end
722
+
723
+ def clear_sessions
724
+ clear_sessions!
725
+ rescue ZendeskAPI::Error::ClientError
726
+ false
727
+ end
728
+
729
+ put :merge
730
+
731
+ has CustomRole, :inline => true, :include => :roles
732
+ has Role, :inline => true, :include_key => :name
733
+ has Ability, :inline => true
734
+ has :related, :class => UserRelated
735
+
736
+ has_many Identity
737
+
738
+ has_many Request
739
+ has_many :requested_tickets, :class => Ticket, :path => 'tickets/requested'
740
+ has_many :assigned_tickets, :class => Ticket, :path => 'tickets/assigned'
741
+ has_many :ccd_tickets, :class => Ticket, :path => 'tickets/ccd'
742
+
743
+ has_many Group
744
+ has_many GroupMembership
745
+ has_many OrganizationMembership
746
+ has_many OrganizationSubscription
747
+
748
+ has_many Setting
749
+ has_many Tag, :extend => Tag::Update, :inline => :create
750
+
751
+ def attributes_for_save
752
+ # Don't send role_id, it's necessary
753
+ # for side-loading, but causes problems on save
754
+ # see #initialize
755
+ attrs = attributes.changes.delete_if do |k, _|
756
+ k == "role_id"
757
+ end
758
+
759
+ { self.class.singular_resource_name => attrs }
760
+ end
761
+
762
+ def handle_response(*)
763
+ super
764
+
765
+ # Needed for proper Role sideloading
766
+ self.role_id = role.name if key?(:role)
767
+ end
768
+ end
769
+
770
+ class DeletedUser < ReadResource
771
+ include Destroy
772
+ end
773
+
774
+ class UserField < Resource; end
775
+ class OrganizationField < Resource; end
776
+
777
+ class OauthClient < Resource
778
+ namespace "oauth"
779
+
780
+ def self.singular_resource_name
781
+ "client"
782
+ end
783
+ end
784
+
785
+ class OauthToken < ReadResource
786
+ include Destroy
787
+ namespace "oauth"
788
+
789
+ def self.singular_resource_name
790
+ "token"
791
+ end
792
+ end
793
+
794
+ class Target < Resource; end
795
+
796
+ module Voice
797
+ include DataNamespace
798
+
799
+ class PhoneNumber < Resource
800
+ namespace "channels/voice"
801
+ end
802
+
803
+ class Address < Resource
804
+ namespace "channels/voice"
805
+ end
806
+
807
+ class Greeting < Resource
808
+ namespace "channels/voice"
809
+ end
810
+
811
+ class GreetingCategory < Resource
812
+ namespace "channels/voice"
813
+ end
814
+
815
+ class Ticket < CreateResource
816
+ namespace "channels/voice"
817
+ end
818
+
819
+ class Agent < ReadResource
820
+ namespace "channels/voice"
821
+
822
+ class Ticket < CreateResource
823
+ def new_record?
824
+ true
825
+ end
826
+
827
+ def self.display!(client, options)
828
+ new(client, options).tap do |resource|
829
+ resource.save!(path: resource.path + '/display')
830
+ end
831
+ end
832
+ end
833
+
834
+ has_many Ticket
835
+ end
836
+ end
837
+
838
+ class TicketForm < Resource
839
+ # TODO
840
+ # post :clone
841
+ end
842
+
843
+ class AppInstallation < Resource
844
+ namespace "apps"
845
+
846
+ def self.singular_resource_name
847
+ "installation"
848
+ end
849
+
850
+ # Don't nest attributes
851
+ def attributes_for_save
852
+ attributes.changes
853
+ end
854
+
855
+ def handle_response(response)
856
+ @attributes.replace(response.body) if response.body
857
+ end
858
+ end
859
+
860
+ class AppNotification < CreateResource
861
+ class << self
862
+ def resource_path
863
+ "apps/notify"
864
+ end
865
+ end
866
+
867
+ # Don't nest attributes
868
+ def attributes_for_save
869
+ attributes.changes
870
+ end
871
+
872
+ def handle_response(response)
873
+ @attributes.replace(response.body) if response.body.is_a?(Hash)
874
+ end
875
+ end
876
+
877
+ class App < Resource
878
+ def initialize(client, attributes = {})
879
+ attributes[:upload_id] ||= nil
880
+
881
+ super
882
+ end
883
+
884
+ def self.create!(client, attributes = {}, &block)
885
+ if file_path = attributes.delete(:upload)
886
+ attributes[:upload_id] = client.apps.uploads.create!(:file => file_path).id
887
+ end
888
+
889
+ super
890
+ end
891
+
892
+ class Plan < Resource
893
+ end
894
+
895
+ class Upload < Data
896
+ class << self
897
+ def resource_path
898
+ "uploads"
899
+ end
900
+ end
901
+
902
+ include Create
903
+
904
+ def initialize(client, attributes)
905
+ attributes[:file] ||= attributes.delete(:id)
906
+
907
+ super
908
+ end
909
+
910
+ # Not nested under :upload, just returns :id
911
+ def save!(*)
912
+ super.tap do
913
+ attributes.id = @response.body["id"]
914
+ end
915
+ end
916
+
917
+ # Always save
918
+ def changed?
919
+ true
920
+ end
921
+
922
+ # Don't nest attributes
923
+ def attributes_for_save
924
+ attributes
925
+ end
926
+ end
927
+
928
+ def self.uploads(client, *args, &block)
929
+ ZendeskAPI::Collection.new(client, Upload, *args, &block)
930
+ end
931
+
932
+ def self.installations(client, *args, &block)
933
+ ZendeskAPI::Collection.new(client, AppInstallation, *args, &block)
934
+ end
935
+
936
+ has Upload, :path => "uploads"
937
+ has_many Plan
938
+
939
+ # Don't nest attributes
940
+ def attributes_for_save
941
+ attributes.changes
942
+ end
943
+
944
+ def handle_response(response)
945
+ @attributes.replace(response.body) if response.body
946
+ end
947
+ end
948
+
949
+ module DynamicContent
950
+ include DataNamespace
951
+
952
+ class Item < ZendeskAPI::Resource
953
+ namespace 'dynamic_content'
954
+
955
+ class Variant < ZendeskAPI::Resource
956
+ end
957
+
958
+ has_many Variant
959
+ end
960
+ end
961
+
962
+ class PushNotificationDevice < DataResource
963
+ def self.destroy_many(client, tokens)
964
+ ZendeskAPI::Collection.new(
965
+ client, self, "push_notification_devices" => tokens,
966
+ :path => "push_notification_devices/destroy_many",
967
+ :verb => :post
968
+ )
969
+ end
970
+ end
971
+ end