Coverage for mindsdb / integrations / handlers / zendesk_handler / zendesk_tables.py: 0%

104 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-21 00:36 +0000

1import pandas as pd 

2from typing import List 

3from mindsdb.integrations.libs.api_handler import APITable 

4from mindsdb.integrations.utilities.handlers.query_utilities import ( 

5 SELECTQueryParser, 

6 SELECTQueryExecutor, 

7) 

8from mindsdb.utilities import log 

9from mindsdb_sql_parser import ast 

10import zenpy 

11 

12logger = log.getLogger(__name__) 

13 

14 

15class ZendeskUsersTable(APITable): 

16 """Zendesk Users Table implementation""" 

17 

18 def select(self, query: ast.Select) -> pd.DataFrame: 

19 """Pulls data from the zendesk list users API 

20 

21 Parameters 

22 ---------- 

23 query : ast.Select 

24 Given SQL SELECT query 

25 

26 Returns 

27 ------- 

28 pd.DataFrame 

29 Zendesk users 

30 

31 Raises 

32 ------ 

33 ValueError 

34 If the query contains an unsupported condition 

35 """ 

36 

37 select_statement_parser = SELECTQueryParser(query, "users", self.get_columns()) 

38 

39 selected_columns, where_conditions, order_by_conditions, result_limit = select_statement_parser.parse_query() 

40 

41 subset_where_conditions = [] 

42 api_filters = {} 

43 for op, arg1, arg2 in where_conditions: 

44 if arg1 in self.get_columns(): 

45 if op != "=": 

46 raise NotImplementedError(f"Unknown op: {op}. Only '=' is supported.") 

47 api_filters[arg1] = arg2 

48 subset_where_conditions.append([op, arg1, arg2]) 

49 

50 result = self.handler.zen_client.users(**api_filters) 

51 response = [] 

52 if isinstance(result, zenpy.lib.generator.BaseResultGenerator): 

53 for user in result: 

54 response.append(user.to_dict()) 

55 else: 

56 response.append(result.to_dict()) 

57 

58 df = pd.DataFrame(response, columns=self.get_columns()) 

59 

60 select_statement_executor = SELECTQueryExecutor( 

61 df, selected_columns, subset_where_conditions, order_by_conditions, result_limit 

62 ) 

63 

64 df = select_statement_executor.execute_query() 

65 

66 return df 

67 

68 def get_columns(self) -> List[str]: 

69 """Gets all columns to be returned in pandas DataFrame responses 

70 

71 Returns 

72 ------- 

73 List[str] 

74 List of columns 

75 """ 

76 

77 return [ 

78 "active", 

79 "alias", 

80 "chat_only", 

81 "created_at", 

82 "custom_role_id", 

83 "details", 

84 "email", 

85 "external_id", 

86 "id", 

87 "last_login_at", 

88 "locale", 

89 "locale_id", 

90 "moderator", 

91 "name", 

92 "notes", 

93 "only_private_comments", 

94 "organization_id", 

95 "phone", 

96 "photo", 

97 "restricted_agent", 

98 "role", 

99 "shared", 

100 "shared_agent", 

101 "signature", 

102 "suspended", 

103 "tags", 

104 "ticket_restriction", 

105 "time_zone", 

106 "two_factor_auth_enabled", 

107 "updated_at", 

108 "url", 

109 "verified", 

110 "iana_time_zone", 

111 "shared_phone_number", 

112 "role_type", 

113 "default_group_id", 

114 "report_csv", 

115 ] 

116 

117 

118class ZendeskTicketsTable(APITable): 

119 """Zendesk tickets Table implementation""" 

120 

121 def select(self, query: ast.Select) -> pd.DataFrame: 

122 """Pulls data from the zendesk tickets API 

123 

124 Parameters 

125 ---------- 

126 query : ast.Select 

127 Given SQL SELECT query 

128 

129 Returns 

130 ------- 

131 pd.DataFrame 

132 Ticket ID Data 

133 

134 Raises 

135 ------ 

136 ValueError 

137 If the query contains an unsupported condition 

138 """ 

139 

140 select_statement_parser = SELECTQueryParser(query, "tickets", self.get_columns()) 

141 

142 selected_columns, where_conditions, order_by_conditions, result_limit = select_statement_parser.parse_query() 

143 

144 subset_where_conditions = [] 

145 api_filters = {} 

146 for op, arg1, arg2 in where_conditions: 

147 if arg1 in self.get_columns(): 

148 if op != "=": 

149 raise NotImplementedError(f"Unknown op: {op}. Only '=' is supported.") 

150 api_filters[arg1] = arg2 

151 subset_where_conditions.append([op, arg1, arg2]) 

152 

153 result = self.handler.zen_client.tickets(**api_filters) 

154 response = [] 

155 if isinstance(result, zenpy.lib.generator.BaseResultGenerator): 

156 for ticket in result: 

157 response.append(ticket.to_dict()) 

158 else: 

159 response.append(result.to_dict()) 

160 

161 df = pd.DataFrame(response, columns=self.get_columns()) 

162 

163 select_statement_executor = SELECTQueryExecutor( 

164 df, selected_columns, subset_where_conditions, order_by_conditions, result_limit 

165 ) 

166 

167 df = select_statement_executor.execute_query() 

168 

169 return df 

170 

171 def get_columns(self) -> List[str]: 

172 """Gets all columns to be returned in pandas DataFrame responses 

173 

174 Returns 

175 ------- 

176 List[str] 

177 List of columns 

178 """ 

179 

180 return [ 

181 "assignee_id", 

182 "brand_id", 

183 "collaborator_ids", 

184 "created_at", 

185 "custom_fields", 

186 "description", 

187 "due_at", 

188 "external_id", 

189 "fields", 

190 "forum_topic_id", 

191 "group_id", 

192 "has_incidents", 

193 "id", 

194 "organization_id", 

195 "priority", 

196 "problem_id", 

197 "raw_subject", 

198 "recipient", 

199 "requester_id", 

200 "sharing_agreement_ids", 

201 "status", 

202 "subject", 

203 "submitter_id", 

204 "tags", 

205 "type", 

206 "updated_at", 

207 "url", 

208 "generated_timestamp", 

209 "follower_ids", 

210 "email_cc_ids", 

211 "is_public", 

212 "custom_status_id", 

213 "followup_ids", 

214 "ticket_form_id", 

215 "allow_channelback", 

216 "allow_attachments", 

217 "from_messaging_channel", 

218 "satisfaction_rating.assignee_id", 

219 "satisfaction_rating.created_at", 

220 "satisfaction_rating.group_id", 

221 "satisfaction_rating.id", 

222 "satisfaction_rating.requester_id", 

223 "satisfaction_rating.score", 

224 "satisfaction_rating.ticket_id", 

225 "satisfaction_rating.updated_at", 

226 "satisfaction_rating.url", 

227 "via.channel", 

228 "via.source.rel", 

229 ] 

230 

231 

232class ZendeskTriggersTable(APITable): 

233 """Zendesk Triggers Table implementation""" 

234 

235 def select(self, query: ast.Select) -> pd.DataFrame: 

236 """Pulls data from the zendesk triggers API 

237 

238 Parameters 

239 ---------- 

240 query : ast.Select 

241 Given SQL SELECT query 

242 

243 Returns 

244 ------- 

245 pd.DataFrame 

246 Trigger Data 

247 

248 Raises 

249 ------ 

250 ValueError 

251 If the query contains an unsupported condition 

252 """ 

253 

254 select_statement_parser = SELECTQueryParser(query, "triggers", self.get_columns()) 

255 

256 selected_columns, where_conditions, order_by_conditions, result_limit = select_statement_parser.parse_query() 

257 

258 subset_where_conditions = [] 

259 api_filters = {} 

260 for op, arg1, arg2 in where_conditions: 

261 if arg1 in self.get_columns(): 

262 if op != "=": 

263 raise NotImplementedError(f"Unknown op: {op}. Only '=' is supported.") 

264 api_filters[arg1] = arg2 

265 subset_where_conditions.append([op, arg1, arg2]) 

266 

267 result = self.handler.zen_client.triggers(**api_filters) 

268 response = [] 

269 if isinstance(result, zenpy.lib.generator.BaseResultGenerator): 

270 for trigger in result: 

271 response.append(trigger.to_dict()) 

272 else: 

273 response.append(result.to_dict()) 

274 

275 df = pd.DataFrame(response, columns=self.get_columns()) 

276 

277 select_statement_executor = SELECTQueryExecutor( 

278 df, selected_columns, subset_where_conditions, order_by_conditions, result_limit 

279 ) 

280 

281 df = select_statement_executor.execute_query() 

282 

283 return df 

284 

285 def get_columns(self) -> List[str]: 

286 """Gets all columns to be returned in pandas DataFrame responses 

287 

288 Returns 

289 ------- 

290 List[str] 

291 List of columns 

292 """ 

293 

294 return [ 

295 "actions", 

296 "active", 

297 "description", 

298 "id", 

299 "position", 

300 "title", 

301 "url", 

302 "updated_at", 

303 "created_at", 

304 "default", 

305 "raw_title", 

306 "category_id", 

307 "conditions.all", 

308 "conditions.any", 

309 ] 

310 

311 

312class ZendeskActivitiesTable(APITable): 

313 """Zendesk Activities Table implementation""" 

314 

315 def select(self, query: ast.Select) -> pd.DataFrame: 

316 """Pulls data from the zendesk activities API 

317 

318 Parameters 

319 ---------- 

320 query : ast.Select 

321 Given SQL SELECT query 

322 

323 Returns 

324 ------- 

325 pd.DataFrame 

326 Activity list Data 

327 

328 Raises 

329 ------ 

330 ValueError 

331 If the query contains an unsupported condition 

332 """ 

333 

334 select_statement_parser = SELECTQueryParser(query, "activities", self.get_columns()) 

335 

336 selected_columns, where_conditions, order_by_conditions, result_limit = select_statement_parser.parse_query() 

337 

338 subset_where_conditions = [] 

339 api_filters = {} 

340 for op, arg1, arg2 in where_conditions: 

341 if arg1 in self.get_columns(): 

342 if op != "=": 

343 raise NotImplementedError(f"Unknown op: {op}. Only '=' is supported.") 

344 api_filters[arg1] = arg2 

345 subset_where_conditions.append([op, arg1, arg2]) 

346 

347 result = self.handler.zen_client.activities(**api_filters) 

348 response = [] 

349 if isinstance(result, zenpy.lib.generator.BaseResultGenerator): 

350 for activity in result: 

351 response.append(activity.to_dict()) 

352 else: 

353 response.append(result.to_dict()) 

354 

355 df = pd.DataFrame(response, columns=self.get_columns()) 

356 

357 select_statement_executor = SELECTQueryExecutor( 

358 df, selected_columns, subset_where_conditions, order_by_conditions, result_limit 

359 ) 

360 

361 df = select_statement_executor.execute_query() 

362 

363 return df 

364 

365 def get_columns(self) -> List[str]: 

366 """Gets all columns to be returned in pandas DataFrame responses 

367 

368 Returns 

369 ------- 

370 List[str] 

371 List of columns 

372 """ 

373 

374 return [ 

375 "created_at", 

376 "id", 

377 "title", 

378 "updated_at", 

379 "url", 

380 "verb", 

381 "user_id", 

382 "actor_id", 

383 "actor.id", 

384 "actor.url", 

385 "actor.name", 

386 "actor.email", 

387 "actor.created_at", 

388 "actor.updated_at", 

389 "actor.time_zone", 

390 "actor.iana_time_zone", 

391 "actor.phone", 

392 "actor.shared_phone_number", 

393 "actor.photo", 

394 "actor.locale_id", 

395 "actor.locale", 

396 "actor.organization_id", 

397 "actor.role", 

398 "actor.verified", 

399 "actor.external_id", 

400 "actor.tags", 

401 "actor.alias", 

402 "actor.active", 

403 "actor.shared", 

404 "actor.shared_agent", 

405 "actor.last_login_at", 

406 "actor.two_factor_auth_enabled", 

407 "actor.signature", 

408 "actor.details", 

409 "actor.notes", 

410 "actor.role_type", 

411 "actor.custom_role_id", 

412 "actor.moderator", 

413 "actor.ticket_restriction", 

414 "actor.only_private_comments", 

415 "actor.restricted_agent", 

416 "actor.suspended", 

417 "actor.default_group_id", 

418 "actor.report_csv", 

419 "user.active", 

420 "user.alias", 

421 "user.chat_only", 

422 "user.created_at", 

423 "user.custom_role_id", 

424 "user.details", 

425 "user.email", 

426 "user.external_id", 

427 "user.id", 

428 "user.last_login_at", 

429 "user.locale", 

430 "user.locale_id", 

431 "user.moderator", 

432 "user.name", 

433 "user.notes", 

434 "user.only_private_comments", 

435 "user.organization_id", 

436 "user.phone", 

437 "user.photo", 

438 "user.restricted_agent", 

439 "user.role", 

440 "user.shared", 

441 "user.shared_agent", 

442 "user.signature", 

443 "user.suspended", 

444 "user.tags", 

445 "user.ticket_restriction", 

446 "user.time_zone", 

447 "user.two_factor_auth_enabled", 

448 "user.updated_at", 

449 "user.url", 

450 "user.verified", 

451 "user.iana_time_zone", 

452 "user.shared_phone_number", 

453 "user.role_type", 

454 "user.default_group_id", 

455 "user.report_csv", 

456 "target.active", 

457 "target.content_type", 

458 "target.created_at", 

459 "target.id", 

460 "target.method", 

461 "target.password", 

462 "target.target_url", 

463 "target.title", 

464 "target.type", 

465 "target.url", 

466 "target.username", 

467 "target.ticket.assignee_id", 

468 "target.ticket.brand_id", 

469 "target.ticket.collaborator_ids", 

470 "target.ticket.created_at", 

471 "target.ticket.custom_fields", 

472 "target.ticket.description", 

473 "target.ticket.due_at", 

474 "target.ticket.external_id", 

475 "target.ticket.fields", 

476 "target.ticket.forum_topic_id", 

477 "target.ticket.group_id", 

478 "target.ticket.has_incidents", 

479 "target.ticket.id", 

480 "target.ticket.organization_id", 

481 "target.ticket.priority", 

482 "target.ticket.problem_id", 

483 "target.ticket.raw_subject", 

484 "target.ticket.recipient", 

485 "target.ticket.requester_id", 

486 "target.ticket.satisfaction_rating", 

487 "target.ticket.sharing_agreement_ids", 

488 "target.ticket.status", 

489 "target.ticket.subject", 

490 "target.ticket.submitter_id", 

491 "target.ticket.tags", 

492 "target.ticket.type", 

493 "target.ticket.updated_at", 

494 "target.ticket.url", 

495 "target.ticket.via", 

496 ]