プロジェクト

全般

プロフィール

« | » 

リビジョン 493ff79f

みぞ @mizo0203 さんがほぼ6年前に追加

Change application name from TwitterTimelineTalker to TimelineTalker.

差分を表示:

.idea/artifacts/TimelineTalker_jar.xml
1
<component name="ArtifactManager">
2
  <artifact type="jar" name="TimelineTalker:jar">
3
    <output-path>$PROJECT_DIR$/out/artifacts/TimelineTalker_jar</output-path>
4
    <root id="archive" name="TimelineTalker.jar">
5
      <element id="module-output" name="TimelineTalker"/>
6
      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/twitter4j/twitter4j-core/4.0.6/twitter4j-core-4.0.6.jar" path-in-jar="/" />
7
      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/twitter4j/twitter4j-stream/4.0.6/twitter4j-stream-4.0.6.jar" path-in-jar="/" />
8
    </root>
9
  </artifact>
10
</component>
.idea/artifacts/TwitterTimelineTalker_jar.xml
1
<component name="ArtifactManager">
2
  <artifact type="jar" name="TwitterTimelineTalker:jar">
3
    <output-path>$PROJECT_DIR$/out/artifacts/TwitterTimelineTalker_jar</output-path>
4
    <root id="archive" name="TwitterTimelineTalker.jar">
5
      <element id="module-output" name="TwitterTimelineTalker" />
6
      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/twitter4j/twitter4j-core/4.0.6/twitter4j-core-4.0.6.jar" path-in-jar="/" />
7
      <element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/twitter4j/twitter4j-stream/4.0.6/twitter4j-stream-4.0.6.jar" path-in-jar="/" />
8
    </root>
9
  </artifact>
10
</component>
.idea/compiler.xml
6 6
        <sourceOutputDir name="target/generated-sources/annotations" />
7 7
        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
8 8
        <outputRelativeToContentRoot value="true" />
9
        <module name="TwitterTimelineTalker" />
9
        <module name="TimelineTalker"/>
10 10
      </profile>
11 11
    </annotationProcessing>
12 12
    <bytecodeTargetLevel>
13
      <module name="TwitterTimelineTalker" target="1.7" />
13
      <module name="TimelineTalker" target="1.7"/>
14 14
    </bytecodeTargetLevel>
15 15
  </component>
16 16
</project>
.idea/modules.xml
2 2
<project version="4">
3 3
  <component name="ProjectModuleManager">
4 4
    <modules>
5
      <module fileurl="file://$PROJECT_DIR$/TwitterTimelineTalker.iml" filepath="$PROJECT_DIR$/TwitterTimelineTalker.iml" />
5
      <module fileurl="file://$PROJECT_DIR$/TimelineTalker.iml" filepath="$PROJECT_DIR$/TimelineTalker.iml"/>
6 6
    </modules>
7 7
  </component>
8 8
</project>
TimelineTalker.iml
1
<?xml version="1.0" encoding="UTF-8"?>
2
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
3
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
4
    <output url="file://$MODULE_DIR$/target/classes" />
5
    <output-test url="file://$MODULE_DIR$/target/test-classes" />
6
    <content url="file://$MODULE_DIR$">
7
      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
8
      <excludeFolder url="file://$MODULE_DIR$/target" />
9
    </content>
10
    <orderEntry type="inheritedJdk" />
11
    <orderEntry type="sourceFolder" forTests="false" />
12
    <orderEntry type="library" name="Maven: org.twitter4j:twitter4j-core:4.0.6" level="project" />
13
    <orderEntry type="library" name="Maven: org.twitter4j:twitter4j-stream:4.0.6" level="project" />
14
  </component>
15
</module>
TwitterTimelineTalker.iml
1
<?xml version="1.0" encoding="UTF-8"?>
2
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
3
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
4
    <output url="file://$MODULE_DIR$/target/classes" />
5
    <output-test url="file://$MODULE_DIR$/target/test-classes" />
6
    <content url="file://$MODULE_DIR$">
7
      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
8
      <excludeFolder url="file://$MODULE_DIR$/target" />
9
    </content>
10
    <orderEntry type="inheritedJdk" />
11
    <orderEntry type="sourceFolder" forTests="false" />
12
    <orderEntry type="library" name="Maven: org.twitter4j:twitter4j-core:4.0.6" level="project" />
13
    <orderEntry type="library" name="Maven: org.twitter4j:twitter4j-stream:4.0.6" level="project" />
14
  </component>
15
</module>
pom.xml
3 3
	<modelVersion>4.0.0</modelVersion>
4 4

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

  
src/META-INF/MANIFEST.MF
1 1
Manifest-Version: 1.0
2
Main-Class: com.mizo0203.twitter.timeline.talker.Application
2
Main-Class: com.mizo0203.timeline.talker.Application
3 3

  
src/com/mizo0203/timeline/talker/Application.java
1
package com.mizo0203.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
    TimelineTalker timelineTalker;
15
    Talker talker;
16

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

  
26
    timelineTalker.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/timeline/talker/RuntimeUtil.java
1
package com.mizo0203.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/timeline/talker/Talker.java
1
package com.mizo0203.timeline.talker;
2

  
3
import java.io.*;
4
import java.util.concurrent.ExecutorService;
5
import java.util.concurrent.Executors;
6

  
7
public class Talker {
8

  
9
  private static final String AQUESTALK_PI_PATH = "./aquestalkpi/AquesTalkPi";
10

  
11
  private final ExecutorService mSingleThreadExecutor = Executors.newSingleThreadExecutor();
12

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

  
24
  public void talkAsync(final String text, final YukkuriVoice voice) {
25
    mSingleThreadExecutor.submit(new Runnable() {
26

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

  
44
    });
45
  }
46

  
47
  public static enum YukkuriVoice {
48

  
49
    /**
50
     * ゆっくりボイス - 霊夢
51
     */
52
    REIMU("f1"), //
53

  
54
    /**
55
     * ゆっくりボイス - 魔理沙
56
     */
57
    MARISA("f2"), //
58
    ;
59

  
60
    private final String value;
61

  
62
    private YukkuriVoice(String value) {
63
      this.value = value;
64
    }
65
  }
66

  
67
}
src/com/mizo0203/timeline/talker/TimelineTalker.java
1
package com.mizo0203.timeline.talker;
2

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

  
6
import java.util.Locale;
7
import java.util.regex.Matcher;
8
import java.util.regex.Pattern;
9

  
10
public class TimelineTalker {
11

  
12
  /**
13
   * ISO 639 言語コード - 日本語 (ja)
14
   */
15
  public static final String LANG_JA = Locale.JAPAN.getLanguage();
16

  
17
  private Talker.YukkuriVoice mYukkuriVoice = Talker.YukkuriVoice.REIMU;
18
  private final TwitterStream mTwitterStream;
19
  private final Talker mTalker;
20

  
21
  public TimelineTalker(Configuration configuration, Talker talker) {
22
    mTwitterStream = new TwitterStreamFactory(configuration).getInstance();
23
    mTwitterStream.addListener(new OnStatusEvent());
24
    mTalker = talker;
25
  }
26

  
27
  public void start() {
28
    // OnStatusEvent に Twitter タイムラインが通知される
29
    mTwitterStream.user();
30
  }
31

  
32
  private static String getUserNameWithoutContext(String name) {
33
    Pattern p = Pattern.compile("([^@@]+).+");
34
    Matcher m = p.matcher(name);
35
    return m.replaceFirst("$1");
36
  }
37

  
38
  private class OnStatusEvent implements StatusListener {
39

  
40
    public void onStatus(final Status status) {
41
      if (!LANG_JA.equalsIgnoreCase(status.getLang())) {
42
        return;
43
      }
44

  
45
      final StringBuffer buffer = new StringBuffer();
46

  
47
      if (status.isRetweet()) {
48
        Status retweetedStatus = status.getRetweetedStatus();
49
        buffer.append(getUserNameWithoutContext(status.getUser().getName()) + "さんがリツイート。");
50
        buffer.append(getUserNameWithoutContext(retweetedStatus.getUser().getName()) + "さんから、");
51
        buffer.append(retweetedStatus.getText());
52
      } else {
53
        buffer.append(getUserNameWithoutContext(status.getUser().getName()) + "さんから、");
54
        buffer.append(status.getText());
55
      }
56

  
57
      mTalker.talkAsync(UrlUtil.convURLEmpty(buffer).replaceAll("\n", "。"), mYukkuriVoice);
58

  
59
      // 読み上げは、霊夢と魔理沙が交互に行なう
60
      if (mYukkuriVoice == Talker.YukkuriVoice.REIMU) {
61
        mYukkuriVoice = Talker.YukkuriVoice.MARISA;
62
      } else {
63
        mYukkuriVoice = Talker.YukkuriVoice.REIMU;
64
      }
65

  
66
    }
67

  
68
    public void onDeletionNotice(StatusDeletionNotice sdn) {
69
      System.err.println("onDeletionNotice.");
70
    }
71

  
72
    public void onTrackLimitationNotice(int i) {
73
      System.err.println("onTrackLimitationNotice.(" + i + ")");
74
    }
75

  
76
    public void onScrubGeo(long lat, long lng) {
77
      System.err.println("onScrubGeo.(" + lat + ", " + lng + ")");
78
    }
79

  
80
    public void onException(Exception excptn) {
81
      System.err.println("onException.");
82
    }
83

  
84
    @Override
85
    public void onStallWarning(StallWarning arg0) {}
86
  }
87

  
88
}
src/com/mizo0203/timeline/talker/UrlUtil.java
1
package com.mizo0203.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
}
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

  
53
    /**
54
     * ゆっくりボイス - 霊夢
55
     */
56
    REIMU("f1"), //
57

  
58
    /**
59
     * ゆっくりボイス - 魔理沙
60
     */
61
    MARISA("f2"), //
62
    ;
63

  
64
    private final String value;
65

  
66
    private YukkuriVoice(String value) {
67
      this.value = value;
68
    }
69
  }
70

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

  
3
import java.util.Locale;
4
import java.util.regex.Matcher;
5
import java.util.regex.Pattern;
6
import twitter4j.StallWarning;
7
import twitter4j.Status;
8
import twitter4j.StatusDeletionNotice;
9
import twitter4j.StatusListener;
10
import twitter4j.TwitterStream;
11
import twitter4j.TwitterStreamFactory;
12
import twitter4j.conf.Configuration;
13

  
14
public class TwitterTimelineTalker {
15

  
16
  /**
17
   * ISO 639 言語コード - 日本語 (ja)
18
   */
19
  public static final String LANG_JA = Locale.JAPAN.getLanguage();
20

  
21
  private Talker.YukkuriVoice mYukkuriVoice = Talker.YukkuriVoice.REIMU;
22
  private final TwitterStream mTwitterStream;
23
  private final Talker mTalker;
24

  
25
  public TwitterTimelineTalker(Configuration configuration, Talker talker) {
26
    mTwitterStream = new TwitterStreamFactory(configuration).getInstance();
27
    mTwitterStream.addListener(new OnStatusEvent());
28
    mTalker = talker;
29
  }
30

  
31
  public void start() {
32
    // OnStatusEvent に Twitter タイムラインが通知される
33
    mTwitterStream.user();
34
  }
35

  
36
  private static String getUserNameWithoutContext(String name) {
37
    Pattern p = Pattern.compile("([^@@]+).+");
38
    Matcher m = p.matcher(name);
39
    return m.replaceFirst("$1");
40
  }
41

  
42
  private class OnStatusEvent implements StatusListener {
43

  
44
    public void onStatus(final Status status) {
45
      if (!LANG_JA.equalsIgnoreCase(status.getLang())) {
46
        return;
47
      }
48

  
49
      final StringBuffer buffer = new StringBuffer();
50

  
51
      if (status.isRetweet()) {
52
        Status retweetedStatus = status.getRetweetedStatus();
53
        buffer.append(getUserNameWithoutContext(status.getUser().getName()) + "さんがリツイート。");
54
        buffer.append(getUserNameWithoutContext(retweetedStatus.getUser().getName()) + "さんから、");
55
        buffer.append(retweetedStatus.getText());
56
      } else {
57
        buffer.append(getUserNameWithoutContext(status.getUser().getName()) + "さんから、");
58
        buffer.append(status.getText());
59
      }
60

  
61
      mTalker.talkAsync(UrlUtil.convURLEmpty(buffer).replaceAll("\n", "。"), mYukkuriVoice);
62

  
63
      // 読み上げは、霊夢と魔理沙が交互に行なう
64
      if (mYukkuriVoice == Talker.YukkuriVoice.REIMU) {
65
        mYukkuriVoice = Talker.YukkuriVoice.MARISA;
66
      } else {
67
        mYukkuriVoice = Talker.YukkuriVoice.REIMU;
68
      }
69

  
70
    }
71

  
72
    public void onDeletionNotice(StatusDeletionNotice sdn) {
73
      System.err.println("onDeletionNotice.");
74
    }
75

  
76
    public void onTrackLimitationNotice(int i) {
77
      System.err.println("onTrackLimitationNotice.(" + i + ")");
78
    }
79

  
80
    public void onScrubGeo(long lat, long lng) {
81
      System.err.println("onScrubGeo.(" + lat + ", " + lng + ")");
82
    }
83

  
84
    public void onException(Exception excptn) {
85
      System.err.println("onException.");
86
    }
87

  
88
    @Override
89
    public void onStallWarning(StallWarning arg0) {}
90
  }
91

  
92
}
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