Commits

Shihab Hamid  committed b4c0448

halway through some code

  • Participants
  • Parent commits 233ca4e

Comments (0)

Files changed (9)

             <version>1.0.2</version>
             <scope>provided</scope>
         </dependency>
+
+        <!-- twitter4j client to execute twitter searches -->
+        <dependency>
+            <groupId>org.twitter4j</groupId>
+            <artifactId>twitter4j-core</artifactId>
+            <version>[2.2,)</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.twitter4j</groupId>
+            <artifactId>twitter4j-stream</artifactId>
+            <version>[2.2,)</version>
+        </dependency>
     </dependencies>
 
     <build>

File src/main/java/com/atlascamp/mywork/tweets/ExampleMacro.java

-package com.atlascamp.mywork.tweets;
-
-import java.util.Map;
-import java.util.List;
-
-import com.atlassian.confluence.content.render.xhtml.ConversionContext;
-import com.atlassian.confluence.macro.Macro;
-import com.atlassian.confluence.macro.MacroExecutionException;
-import com.atlassian.confluence.pages.PageManager;
-import com.atlassian.confluence.pages.Page;
-import com.atlassian.confluence.spaces.SpaceManager;
-import com.atlassian.confluence.user.AuthenticatedUserThreadLocal;
-import com.atlassian.user.User;
-import com.opensymphony.util.TextUtils;
-
-/**
- * This very simple macro shows you the very basic use-case of displaying *something* on the Confluence page where it is used.
- * Use this example macro to toy around, and then quickly move on to the next example - this macro doesn't
- * really show you all the fun stuff you can do with Confluence.
- */
-public class ExampleMacro implements Macro
-{
-
-    // We just have to define the variables and the setters, then Spring injects the correct objects for us to use. Simple and efficient.
-    // You just need to know *what* you want to inject and use.
-
-    private final PageManager pageManager;
-    private final SpaceManager spaceManager;
-
-    public ExampleMacro(PageManager pageManager, SpaceManager spaceManager)
-    {
-        this.pageManager = pageManager;
-        this.spaceManager = spaceManager;
-    }
-
-    /**
-     * This method returns XHTML to be displayed on the page that uses this macro
-     * we just do random stuff here, trying to show how you can access the most basic
-     * managers and model objects. No emphasis is put on beauty of code nor on
-     * doing actually useful things :-)
-     */
-    @Override
-    public String execute(Map<String, String> parameters, String body, ConversionContext context) throws MacroExecutionException
-    {
-        // in this most simple example, we build the result in memory, appending HTML code to it at will.
-        // this is something you absolutely don't want to do once you start writing plugins for real. Refer
-        // to the next example for better ways to render content.
-        StringBuffer result = new StringBuffer();
-
-        // get the currently logged in user and display his name
-        User user = AuthenticatedUserThreadLocal.getUser();
-        if (user != null)
-        {
-            String greeting = "<p>Hello <b>" + TextUtils.htmlEncode(user.getFullName()) + "</b>.</p>";
-            result.append(greeting);
-        }
-
-        //get the pages added in the last 55 days to the DS space ("Demo Space"), and display them
-        List<Page> list = pageManager.getRecentlyAddedPages(55, "DS");
-        result.append("<p>");
-        result.append("Some stats for <b>Demonstration Space</b>:");
-        result.append("<table class=\"confluenceTable\">");
-        result.append("<thead><tr><th class=\"confluenceTh\">Page</th><th class=\"confluenceTh\">Number of children</th></tr></thead>");
-        result.append("<tbody>");
-        for (Page page : list)
-        {
-            int numberOfChildren = page.getChildren().size();
-            String pageWithChildren = "<tr><td class=\"confluenceTd\">" + TextUtils.htmlEncode(page.getTitle()) + "</td><td class=\"confluenceTd\" style=\"text-align:right\">" + numberOfChildren + "</td></tr>";
-            result.append(pageWithChildren);
-        }
-        result.append("</tbody>");
-        result.append("</table>");
-        result.append("</p>");
-
-        // and show the number of all spaces in this installation.
-        String spaces = "<p>Altogether, this installation has <b>" + spaceManager.getAllSpaces().size() + "</b> spaces.</p>";
-        result.append(spaces);
-
-        // this concludes our little demo. Now you should understand the basics of code injection use in Confluence, and how
-        // to get a really simple macro running.
-
-        return result.toString();
-    }
-
-    @Override
-    public BodyType getBodyType()
-    {
-        return BodyType.NONE;
-    }
-
-    @Override
-    public OutputType getOutputType()
-    {
-        return OutputType.BLOCK;
-    }
-
-}

File src/main/java/com/atlascamp/mywork/tweets/Main.java

+package com.atlascamp.mywork.tweets;
+
+import twitter4j.*;
+
+import java.io.IOException;
+
+public class Main
+{
+    public static void main(String[] args) throws TwitterException, IOException
+    {
+        StatusListener listener = new StatusListener(){
+            public void onStatus(Status status) {
+                System.out.println(status.getUser().getName() + " : " + status.getText());
+            }
+            public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {}
+            public void onTrackLimitationNotice(int numberOfLimitedStatuses) {}
+
+            @Override
+            public void onScrubGeo(long l, long l1)
+            {
+                throw new RuntimeException();
+            }
+
+            public void onException(Exception ex) {
+                ex.printStackTrace();
+            }
+        };
+        TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
+        twitterStream.addListener(listener);
+        // sample() method internally creates a thread which manipulates TwitterStream and calls these adequate listener methods continuously.
+        twitterStream.sample();
+    }
+}

File src/main/java/com/atlascamp/mywork/tweets/MyWorkTweetsLocaleService.java

+package com.atlascamp.mywork.tweets;
+
+import com.atlassian.confluence.languages.Language;
+import com.atlassian.confluence.languages.LanguageManager;
+import com.atlassian.confluence.languages.LocaleManager;
+import com.atlassian.mywork.service.LocaleService;
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+
+import java.util.Locale;
+
+/**
+ * Unfortunately there isn't a way to get the list of configured locales in the system via SAL.
+ */
+public class MyWorkTweetsLocaleService implements LocaleService
+{
+    private final LanguageManager languageManager;
+
+    public MyWorkTweetsLocaleService(LanguageManager languageManager)
+    {
+        this.languageManager = languageManager;
+    }
+
+    @Override
+    public Iterable<Locale> getLocales()
+    {
+        return Lists.transform(languageManager.getLanguages(), new Function<Language, Locale>()
+        {
+            @Override
+            public Locale apply(Language language)
+            {
+                return language.getLocale();
+            }
+        });
+    }
+
+    @Override
+    public Locale getDefaultLocale()
+    {
+        return LocaleManager.DEFAULT_LOCALE;
+    }
+}

File src/main/java/com/atlascamp/mywork/tweets/TweetsRegistrationProvider.java

+package com.atlascamp.mywork.tweets;
+
+import com.atlassian.mywork.service.RegistrationProvider;
+
+/**
+ * Let's WorkBox know where to find the registration configuration
+ * details like i18n and in-line actions.
+ */
+public class TweetsRegistrationProvider implements RegistrationProvider
+{
+    @Override
+    public String getApplication()
+    {
+        return getPackage();
+    }
+
+    @Override
+    public String getPackage()
+    {
+        return "com.atlascamp.mywork.tweets";
+    }
+
+    @Override
+    public String getPluginId()
+    {
+        return getPackage() + ".mywork-tweets";
+    }
+}

File src/main/java/com/atlascamp/mywork/tweets/TwitterListener.java

+package com.atlascamp.mywork.tweets;
+
+import com.atlassian.crowd.embedded.api.CrowdService;
+import com.atlassian.crowd.search.EntityDescriptor;
+import com.atlassian.crowd.search.builder.QueryBuilder;
+import com.atlassian.crowd.search.query.entity.EntityQuery;
+import com.atlassian.event.api.EventPublisher;
+import com.atlassian.mywork.model.NotificationBuilder;
+import com.atlassian.mywork.service.NotificationService;
+import org.springframework.beans.factory.DisposableBean;
+import twitter4j.*;
+import twitter4j.conf.ConfigurationBuilder;
+
+/**
+ * A simple social media monitoring tool that uses the
+ * Twitter streaming API to scan for tweets matching a
+ * particular query.
+ *
+ * Once a tweet is identified, it is then broadcast to
+ * a predefined group of users in Confluence via WorkBox.
+ */
+public class TwitterListener implements StatusListener, DisposableBean
+{
+    // configuration
+    private static final String USERNAME = "atlascampbob";
+    private static final String PASSWORD = "";
+    private static final String GROUP = "marketing";
+    private static final String[] SEARCH = { "test :)" };
+
+    // dependencies
+    private final NotificationService notificationService;
+    private final CrowdService crowdService;
+    private final TwitterStream twitterStream;
+
+    public TwitterListener(EventPublisher eventPublisher, NotificationService notificationService, CrowdService crowdService)
+    {
+        // inject dependencies
+        this.notificationService = notificationService;
+        this.crowdService = crowdService;
+
+        // configure twitter
+        ConfigurationBuilder configBuilder = new ConfigurationBuilder().setUser(USERNAME).setPassword(PASSWORD);
+        this.twitterStream = new TwitterStreamFactory(configBuilder.build()).getInstance();
+
+        // start streaming
+        twitterStream.addListener(this);
+        twitterStream.filter(new FilterQuery().track(SEARCH));
+    }
+
+    public void onStatus(Status status)
+    {
+        System.out.println(status.getUser().getName() + " : " + status.getText());
+
+        notificationService.createOrUpdate("admin", new NotificationBuilder()
+                            .application("com.atlascamp.mywork.tweets.mywork-tweets")
+                            .entity("twitter")
+                            .action("tweet")
+                            .title(status.getUser().getName())
+                            .description(status.getText())
+                            .createNotification());
+    }
+
+    @Override
+    public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice)
+    {
+    }
+
+    @Override
+    public void onTrackLimitationNotice(int i)
+    {
+    }
+
+    @Override
+    public void onScrubGeo(long l, long l1)
+    {
+    }
+
+    @Override
+    public void onException(Exception e)
+    {
+        e.printStackTrace();
+    }
+
+    @Override
+    public void destroy() throws Exception
+    {
+        twitterStream.shutdown();
+    }
+
+    private Iterable<String> getUsersInGroup(String group)
+    {
+        return crowdService.search(QueryBuilder
+                .queryFor(String.class, EntityDescriptor.user())
+                .childrenOf(EntityDescriptor.group())
+                .withName(group)
+                .returningAtMost(EntityQuery.ALL_RESULTS));
+    }
+}

File src/main/resources/META-INF/spring/myWorkTweets.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:osgi="http://www.springframework.org/schema/osgi"
+       xsi:schemaLocation="
+            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+            http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd ">
+
+    <osgi:service id="osgiLocaleService"
+                  ref="localeService"
+                  interface="com.atlassian.mywork.service.LocaleService"/>
+
+    <osgi:service ref="registrationProvider"
+                  interface="com.atlassian.mywork.service.RegistrationProvider"
+                  depends-on="osgiLocaleService"/>
+
+</beans>

File src/main/resources/atlassian-plugin.xml

         <vendor name="${project.organization.name}" url="${project.organization.url}" />
     </plugin-info>
 
-    <xhtml-macro name="mywork-tweets" class="com.atlascamp.mywork.tweets.ExampleMacro" key="my-macro">
-        <parameters/>
-    </xhtml-macro>
+    <component key="twitterListener" class="com.atlascamp.mywork.tweets.TwitterListener"/>
+    <component key="registrationProvider" class="com.atlascamp.mywork.tweets.TweetsRegistrationProvider"/>
+    <component key="localeService" class="com.atlascamp.mywork.tweets.MyWorkTweetsLocaleService"/>
+
+    <component-import key="eventPublisher" interface="com.atlassian.event.api.EventPublisher"/>
+    <component-import key="crowdService" interface="com.atlassian.crowd.embedded.api.CrowdService"/>
+    <component-import key="notificationService" interface="com.atlassian.mywork.service.NotificationService"/>
+    <!--<component-import key="registrationProvider" interface="com.atlassian.mywork.service.RegistrationProvider"/>-->
+
 </atlassian-plugin>

File src/main/resources/com/atlascamp/mywork/tweets/registration-i18n.properties

+com.atlascamp.mywork.tweets.twitter.tweet.title={user} tweeted {title}
+com.atlascamp.mywork.tweets.twitter.tweet.aggregate={0} tweet on {1}
+com.atlascamp.mywork.tweets.twitter.tweet.aggregates={0} tweets on {1}
+com.atlascamp.mywork.tweets.twitter.tweet.aggregatenew={0} new tweet on {1}
+com.atlascamp.mywork.tweets.twitter.tweet.aggregatenews={0} new tweets on {1}
+com.atlascamp.mywork.tweets.twitter.tweet.older={0} older tweets on this tweet
+com.atlascamp.mywork.tweets.twitter.tweet.olders={0} older tweets on this tweet