1 package com.jetbrains.edu.learning.twitter;
3 import com.intellij.ide.BrowserUtil;
4 import com.intellij.openapi.application.ApplicationManager;
5 import com.intellij.openapi.diagnostic.Logger;
6 import com.intellij.openapi.project.Project;
7 import com.intellij.openapi.ui.DialogBuilder;
8 import com.intellij.openapi.ui.Messages;
9 import com.intellij.openapi.util.io.FileUtil;
10 import com.intellij.ui.DocumentAdapter;
11 import com.intellij.ui.components.JBScrollPane;
12 import com.jetbrains.edu.learning.StudyPluginConfigurator;
13 import com.jetbrains.edu.learning.StudyUtils;
14 import org.jetbrains.annotations.NotNull;
15 import org.jetbrains.annotations.Nullable;
16 import twitter4j.StatusUpdate;
17 import twitter4j.Twitter;
18 import twitter4j.TwitterException;
19 import twitter4j.TwitterFactory;
20 import twitter4j.auth.AccessToken;
21 import twitter4j.auth.RequestToken;
22 import twitter4j.conf.ConfigurationBuilder;
25 import javax.swing.event.DocumentEvent;
26 import javax.swing.event.DocumentListener;
28 import java.io.FileOutputStream;
29 import java.io.IOException;
30 import java.io.InputStream;
33 public class StudyTwitterUtils {
34 private static final Logger LOG = Logger.getInstance(StudyTwitterUtils.class);
37 * Configure twitter instance: authorize if needed or set access token and token secret provided by configurator.
41 * @throws TwitterException
43 public static void configureTwitter(@NotNull final Twitter twitter, @NotNull final Project project,
44 final boolean isAuthorized) throws TwitterException {
46 authorize(project, twitter);
49 StudyPluginConfigurator configurator = StudyUtils.getConfigurator(project);
50 if (configurator != null) {
51 getTwitterForAuthorizedApp(twitter, configurator.getTwitterAccessToken(project), configurator.getTwitterTokenSecret(project));
57 * Set consumer key and secret.
59 * @param consumerSecret
63 public static Twitter getTwitter(@NotNull final String consumerKey, @NotNull final String consumerSecret) {
64 ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
65 configurationBuilder.setOAuthConsumerKey(consumerKey);
66 configurationBuilder.setOAuthConsumerSecret(consumerSecret);
67 return new TwitterFactory(configurationBuilder.build()).getInstance();
71 * Set access token and token secret in Twitter instance
76 private static void getTwitterForAuthorizedApp(Twitter twitter, @NotNull String accessToken,
77 @NotNull String tokenSecret) {
78 AccessToken token = new AccessToken(accessToken, tokenSecret);
79 twitter.setOAuthAccessToken(token);
83 * Authorize user and save tokens by StudyPluginConfigurator#storeTwitterTokens
86 * @throws TwitterException
88 public static void authorize(@NotNull final Project project, @NotNull final Twitter twitter) throws TwitterException {
89 RequestToken requestToken = twitter.getOAuthRequestToken();
90 BrowserUtil.browse(requestToken.getAuthorizationURL());
92 ApplicationManager.getApplication().invokeLater(() -> {
93 String pin = Messages.showInputDialog("Twitter PIN:", "Twitter Authorization", null, "", null);
96 if (pin != null && pin.length() > 0) {
97 token = twitter.getOAuthAccessToken(requestToken, pin);
100 token = twitter.getOAuthAccessToken();
102 StudyPluginConfigurator configurator = StudyUtils.getConfigurator(project);
103 if (configurator != null) {
104 configurator.storeTwitterTokens(project, token.getToken(), token.getTokenSecret());
107 LOG.warn("Plugin configurator not found");
110 catch (TwitterException e) {
111 if (401 == e.getStatusCode()) {
112 LOG.warn("Unable to get the access token.");
115 LOG.warn(e.getMessage());
122 * Show twitter dialog, asking user to tweet about his achievements. Post tweet with provided by panel
124 * As a result of succeeded tweet twitter website is opened in default browser.
126 * @param twitterDialogPanel
128 public static void showPostTweetDialogAndPostTweet(@NotNull Twitter twitter, @NotNull final TwitterDialogPanel twitterDialogPanel) {
129 ApplicationManager.getApplication().invokeLater(() -> {
130 DialogBuilder builder = new DialogBuilder();
131 twitterDialogPanel.addTextFieldVerifier(createTextFieldLengthDocumentListener(builder, twitterDialogPanel));
132 builder.title("Twitter");
133 builder.addOkAction().setText("Tweet");
134 builder.addCancelAction();
135 builder.setCenterPanel(new JBScrollPane(twitterDialogPanel));
136 builder.resizable(true);
137 if (builder.showAndGet()) {
138 StatusUpdate update = new StatusUpdate(twitterDialogPanel.getMessage());
140 InputStream inputStream = twitterDialogPanel.getMediaSource();
141 if (inputStream != null) {
142 File imageFile = FileUtil.createTempFile("twitter_media", "gif");
144 FileUtil.copy(inputStream, new FileOutputStream(imageFile));
145 update.media(imageFile);
147 twitter.updateStatus(update);
148 BrowserUtil.browse("https://twitter.com/");
150 catch (IOException | TwitterException e) {
151 LOG.warn(e.getMessage());
152 Messages.showErrorDialog("Status wasn't updated. Please, check internet connection and try again", "Twitter");
159 * Listener updates label indicating remaining symbols number like in twitter.
164 public static DocumentListener createTextFieldLengthDocumentListener(@NotNull DialogBuilder builder, @NotNull final TwitterDialogPanel panel) {
165 return new DocumentAdapter() {
167 protected void textChanged(DocumentEvent e) {
168 int length = e.getDocument().getLength();
169 if (length > 140 || length == 0) {
170 builder.setOkActionEnabled(false);
171 panel.getRemainSymbolsLabel().setText("<html><font color='red'>" + String.valueOf(140 - length) + "</font></html>");
174 builder.setOkActionEnabled(true);
175 panel.getRemainSymbolsLabel().setText(String.valueOf(140 - length));
183 * Class provides structure for twitter dialog panel
185 public abstract static class TwitterDialogPanel extends JPanel {
188 * Provides tweet text
191 @NotNull public abstract String getMessage();
195 * @return Input stream of media should be posted or null if there's nothing to post
197 @Nullable public abstract InputStream getMediaSource();
201 * @return label that will be used to show remained symbol number
203 @NotNull public abstract JLabel getRemainSymbolsLabel();
206 * Api to add document listener to field containing tweet text
207 * @param documentListener
209 public abstract void addTextFieldVerifier(@NotNull final DocumentListener documentListener);