プロジェクト

全般

プロフィール

« | » 

リビジョン df4ee0a0

みぞ @mizo0203 さんが約7年前に追加

Add Source Code. fixes #236 @8h

差分を表示:

.classpath
1
<?xml version="1.0" encoding="UTF-8"?>
2
<classpath>
3
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
4
		<attributes>
5
			<attribute name="maven.pomderived" value="true"/>
6
		</attributes>
7
	</classpathentry>
8
	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
9
		<attributes>
10
			<attribute name="maven.pomderived" value="true"/>
11
		</attributes>
12
	</classpathentry>
13
	<classpathentry including="**/*.java" kind="src" output="target/classes" path="src">
14
		<attributes>
15
			<attribute name="optional" value="true"/>
16
			<attribute name="maven.pomderived" value="true"/>
17
		</attributes>
18
	</classpathentry>
19
	<classpathentry kind="output" path="target/classes"/>
20
</classpath>
.gitignore
1
/target
.project
1
<?xml version="1.0" encoding="UTF-8"?>
2
<projectDescription>
3
	<name>TwitterTimelineTalker</name>
4
	<comment></comment>
5
	<projects>
6
	</projects>
7
	<buildSpec>
8
		<buildCommand>
9
			<name>org.eclipse.jdt.core.javabuilder</name>
10
			<arguments>
11
			</arguments>
12
		</buildCommand>
13
		<buildCommand>
14
			<name>org.eclipse.m2e.core.maven2Builder</name>
15
			<arguments>
16
			</arguments>
17
		</buildCommand>
18
	</buildSpec>
19
	<natures>
20
		<nature>org.eclipse.jdt.core.javanature</nature>
21
		<nature>org.eclipse.m2e.core.maven2Nature</nature>
22
	</natures>
23
</projectDescription>
.settings/org.eclipse.core.resources.prefs
1
eclipse.preferences.version=1
2
encoding/<project>=UTF-8
3
encoding/src=UTF-8
.settings/org.eclipse.jdt.core.prefs
1
eclipse.preferences.version=1
2
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
3
org.eclipse.jdt.core.compiler.compliance=1.7
4
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
5
org.eclipse.jdt.core.compiler.source=1.7
.settings/org.eclipse.m2e.core.prefs
1
activeProfiles=
2
eclipse.preferences.version=1
3
resolveWorkspaceProjects=true
4
version=1
pom.xml
1
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3
	<modelVersion>4.0.0</modelVersion>
4

  
5
	<groupId>com.mizo0203</groupId>
6
	<artifactId>TwitterTimelineTalker</artifactId>
7
	<version>0.0.1-SNAPSHOT</version>
8
	<packaging>jar</packaging>
9

  
10
	<properties>
11
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
12
	</properties>
13

  
14
	<build>
15
		<sourceDirectory>src</sourceDirectory>
16
		<outputDirectory>target/classes</outputDirectory>
17
		<resources>
18
			<resource>
19
				<directory>src</directory>
20
				<excludes>
21
					<exclude>**/*.java</exclude>
22
				</excludes>
23
			</resource>
24
		</resources>
25
		<plugins>
26
			<plugin>
27
				<artifactId>maven-compiler-plugin</artifactId>
28
				<version>3.1</version>
29
				<configuration>
30
					<source>1.7</source>
31
					<target>1.7</target>
32
				</configuration>
33
			</plugin>
34
		</plugins>
35
	</build>
36

  
37
	<dependencies>
38
		<dependency>
39
			<groupId>org.twitter4j</groupId>
40
			<artifactId>twitter4j-core</artifactId>
41
			<version>[4.0,)</version>
42
		</dependency>
43
		<dependency>
44
			<groupId>org.twitter4j</groupId>
45
			<artifactId>twitter4j-stream</artifactId>
46
			<version>[4.0,)</version>
47
		</dependency>
48
	</dependencies>
49
</project>
src/com/mizo0203/twitter/timeline/talker/Application.java
1
package com.mizo0203.twitter.timeline.talker;
2

  
3
import twitter4j.conf.Configuration;
4
import twitter4j.conf.ConfigurationBuilder;
5

  
6
/**
7
 * Java アプリケーション起動時に実行されるクラス
8
 * 
9
 * @author みぞ@CrazyBeatCoder
10
 */
11
public class Application {
12

  
13
  public static void main(String[] args) {
14
    TwitterTimelineTalker twitterTimelineTalker;
15
    Talker talker;
16

  
17
    try {
18
      talker = new Talker();
19
      twitterTimelineTalker =
20
          new TwitterTimelineTalker(new Arguments(args).twitterConfiguration, talker);
21
    } catch (IllegalArgumentException | IllegalStateException e) {
22
      System.err.println(e.getMessage());
23
      return;
24
    }
25

  
26
    twitterTimelineTalker.start();
27
    talker.talkAsync("アプリケーションを起動しました", Talker.YukkuriVoice.REIMU);
28
  }
29

  
30
  /**
31
   * Java アプリケーション起動時に指定する引数のデータクラス
32
   * 
33
   * @author みぞ@CrazyBeatCoder
34
   */
35
  private static class Arguments {
36

  
37
    private final Configuration twitterConfiguration;
38

  
39
    private Arguments(String[] args) throws IllegalArgumentException {
40
      if (args.length < Argument.values().length) {
41
        StringBuilder exceptionMessage = new StringBuilder();
42
        exceptionMessage.append(Argument.values().length + " つの引数を指定してください。\n");
43
        for (Argument arg : Argument.values()) {
44
          exceptionMessage.append((arg.ordinal() + 1) + " つ目: " + arg.detail + "\n");
45
        }
46
        throw new IllegalArgumentException(exceptionMessage.toString());
47
      }
48

  
49
      String consumer_key = args[Argument.CONSUMER_KEY.ordinal()];
50
      String consumer_secret = args[Argument.CONSUMER_SECRET.ordinal()];
51
      String access_token = args[Argument.ACCESS_TOKEN.ordinal()];
52
      String access_token_secret = args[Argument.ACCESS_TOKEN_SECRET.ordinal()];
53

  
54
      twitterConfiguration = new ConfigurationBuilder().setOAuthConsumerKey(consumer_key)
55
          .setOAuthConsumerSecret(consumer_secret).setOAuthAccessToken(access_token)
56
          .setOAuthAccessTokenSecret(access_token_secret).build();
57
    }
58

  
59
  }
60

  
61
  /**
62
   * Java アプリケーション起動時に指定する引数の定義
63
   * 
64
   * @author みぞ@CrazyBeatCoder
65
   */
66
  private enum Argument {
67
    CONSUMER_KEY("Twitter Application's Consumer Key (API Key)"), //
68
    CONSUMER_SECRET("Twitter Application's Consumer Secret (API Secret)"), //
69
    ACCESS_TOKEN("Twitter Account's Access Token"), //
70
    ACCESS_TOKEN_SECRET("Twitter Account's Access Token Secret"), //
71
    ;
72

  
73
    private final String detail;
74

  
75
    private Argument(String detail) {
76
      this.detail = detail;
77
    }
78
  }
79
}
src/com/mizo0203/twitter/timeline/talker/RuntimeUtil.java
1
package com.mizo0203.twitter.timeline.talker;
2

  
3
import java.io.IOException;
4

  
5
public class RuntimeUtil {
6

  
7
  public static void execute(String[] cmdarray) {
8
    try {
9
      Process process = Runtime.getRuntime().exec(cmdarray);
10
      process.waitFor();
11
      process.destroy();
12
    } catch (IOException | InterruptedException e) {
13
      e.printStackTrace();
14
    }
15
  }
16

  
17
}
src/com/mizo0203/twitter/timeline/talker/Talker.java
1
package com.mizo0203.twitter.timeline.talker;
2

  
3
import java.io.BufferedWriter;
4
import java.io.File;
5
import java.io.FileWriter;
6
import java.io.IOException;
7
import java.io.PrintWriter;
8
import java.util.concurrent.ExecutorService;
9
import java.util.concurrent.Executors;
10

  
11
public class Talker {
12

  
13
  private static final String AQUESTALK_PI_PATH = "./aquestalkpi/AquesTalkPi";
14

  
15
  private final ExecutorService mSingleThreadExecutor = Executors.newSingleThreadExecutor();
16

  
17
  public Talker() throws IllegalStateException, SecurityException {
18
    File file = new File(AQUESTALK_PI_PATH);
19
    if (!file.isFile()) {
20
      throw new IllegalStateException(file.getPath() + " に AquesTalk Pi がありません。\n"
21
          + "https://www.a-quest.com/products/aquestalkpi.html\n" + "からダウンロードしてください。");
22
    }
23
    if (!file.canExecute()) {
24
      throw new IllegalStateException(file.getPath() + " に実行権限がありません。");
25
    }
26
  }
27

  
28
  public void talkAsync(final String text, final YukkuriVoice voice) {
29
    mSingleThreadExecutor.submit(new Runnable() {
30

  
31
      @Override
32
      public void run() {
33
        try {
34
          File file = new File("text.txt");
35
          PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
36
          pw.println(text);
37
          pw.flush();
38
          pw.close();
39
          RuntimeUtil.execute(new String[] {AQUESTALK_PI_PATH, "-v", voice.value, "-f", "text.txt",
40
              "-o", "out.wav"});
41
          RuntimeUtil.execute(new String[] {"sh", "-c", "aplay < out.wav"}); // 起動コマンドを指定する
42
          Thread.sleep(2000);
43
        } catch (IOException | InterruptedException e) {
44
          e.printStackTrace();
45
        }
46
      }
47

  
48
    });
49
  }
50

  
51
  public static enum YukkuriVoice {
52
    REIMU("f1"), //
53
    MARISA("f2"), //
54
    ;
55

  
56
    private final String value;
57

  
58
    private YukkuriVoice(String value) {
59
      this.value = value;
60
    }
61
  }
62

  
63
}
src/com/mizo0203/twitter/timeline/talker/TwitterTimelineTalker.java
1
package com.mizo0203.twitter.timeline.talker;
2

  
3
import twitter4j.StallWarning;
4
import twitter4j.Status;
5
import twitter4j.StatusDeletionNotice;
6
import twitter4j.StatusListener;
7
import twitter4j.TwitterStream;
8
import twitter4j.TwitterStreamFactory;
9
import twitter4j.conf.Configuration;
10

  
11
public class TwitterTimelineTalker {
12

  
13
  private boolean mVoice_f1 = true;
14
  private final TwitterStream mTwitterStream;
15
  private final Talker mTalker;
16

  
17
  public TwitterTimelineTalker(Configuration configuration, Talker talker) {
18
    mTwitterStream = new TwitterStreamFactory(configuration).getInstance();
19
    mTwitterStream.addListener(new MyStatusListener());
20
    mTalker = talker;
21
  }
22

  
23
  public void start() {
24
    mTwitterStream.user();
25
  }
26

  
27
  private class MyStatusListener implements StatusListener {
28

  
29
    public void onStatus(final Status status) {
30
      if (!"ja".equalsIgnoreCase(status.getLang())) {
31
        return;
32
      }
33
      final StringBuffer buffer = new StringBuffer();
34
      buffer.append(status.getUser().getName());
35
      buffer.append("さんから、");
36
      buffer.append(status.getText());
37
      System.out.println(buffer);
38

  
39
      // System.out.println("@" + status.getUser().getScreenName() + " | "
40
      // + status.getText() + " 【 https://twitter.com/" +
41
      // status.getUser().getScreenName() + "/status/" + status.getId() +
42
      // " 】");
43
      // こんな感じでstatusについている名前とかを色々表示させるとさらに欲しい情報にたどり着けると思います
44

  
45

  
46
      mTalker.talkAsync(UrlUtil.convURLEmpty(buffer).replaceAll("\n", "。"),
47
          (mVoice_f1 ? Talker.YukkuriVoice.REIMU : Talker.YukkuriVoice.MARISA));
48
      mVoice_f1 = !mVoice_f1;
49

  
50
    }
51

  
52
    public void onDeletionNotice(StatusDeletionNotice sdn) {
53
      System.err.println("onDeletionNotice.");
54
    }
55

  
56
    public void onTrackLimitationNotice(int i) {
57
      System.err.println("onTrackLimitationNotice.(" + i + ")");
58
    }
59

  
60
    public void onScrubGeo(long lat, long lng) {
61
      System.err.println("onScrubGeo.(" + lat + ", " + lng + ")");
62
    }
63

  
64
    public void onException(Exception excptn) {
65
      System.err.println("onException.");
66
    }
67

  
68
    @Override
69
    public void onStallWarning(StallWarning arg0) {}
70
  }
71

  
72
}
src/com/mizo0203/twitter/timeline/talker/UrlUtil.java
1
package com.mizo0203.twitter.timeline.talker;
2

  
3
import java.util.regex.Matcher;
4
import java.util.regex.Pattern;
5

  
6
/**
7
 * http://chat-messenger.net/blog-entry-40.html
8
 */
9
public class UrlUtil {
10
  /** URLを抽出するための正規表現パターン */
11
  private static final Pattern convURLLinkPtn = Pattern.compile(
12
      "(http://|https://){1}[\\w\\.\\-/:\\#\\?\\=\\&\\;\\%\\~\\+]+", Pattern.CASE_INSENSITIVE);
13

  
14
  /**
15
   * 指定された文字列内のURLを、正規表現を使用し、 空文字列に変換する。
16
   * 
17
   * @param str 指定の文字列。
18
   * @return リンクに変換された文字列。
19
   */
20
  public static String convURLEmpty(CharSequence str) {
21
    Matcher matcher = convURLLinkPtn.matcher(str);
22
    return matcher.replaceAll("");
23
  }
24
}

他の形式にエクスポート: Unified diff