Check-in [81ab4b617b]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:'kGmailNotifier'
Timelines: family | ancestors | trunk
Files: files | file ages | folders
SHA1:81ab4b617b3d7efefff65d79ddb7764cd4026043
User & Date: Matt 2012-10-11 07:16:42
Context
2012-10-11
07:16
'kGmailNotifier' Leaf check-in: 81ab4b617b user: Matt tags: trunk
06:55
(no comment) check-in: ec5afc88ee user: Matt tags: trunk
Changes

Added www/kGmailNotifier/background.js.















































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Codebit Grake \_(°-°)_/[\/]
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// GMail Javascript Handler
// part of the project "Opera Google Mail Extension"
// (see http://codebit.de/oex/google-mail for more info)
// @author Tom Schreiber (tom.schreiber@codebit.de)
// @version SVN: 196 2012-06-20 11:49:58Z tom.schreiber@tomhost.de $
function Gmail_Account() {
	this.UniqueID = this.name = this.FeedLabel = this.AccountLink = "";
	this.UnreadCount = 0; this.HasNewMessages = false;
	this.UnreadMessages = new Array(), UpdateRunningTO = null;
}
function Gmail_Message() {
	this.Modified = new Date(); this.Timestring = this.Id = "";
}
function Grake() {
	var GmailURL="https://mail.google.com/mail/",
		GmailAccountsURL="https://accounts.google.com/AddSession",
		EmailPattern=/([a-z0-9._-]+@[a-z0-9._-]+\.[a-z]{2,4})/ig,
		Accounts=[], AccountsNew=[], AccountsCompleted=0, ReqRunning=false,
		RequestTimer='';
	this.GetAccounts = function() { return Accounts; }
	this.GetAccountsCount = function() { return Accounts.length; }
	this.GetTotalUnreadCount = function() {
		var unreadCount=0;
		for(var i=0; i<Accounts.length;i++)
			unreadCount += Number(Accounts[i].UnreadCount);
		return unreadCount;
	}
	this.GetRealNewMessageBool = function() {
		for(var i=0;i<Accounts.length;i++)
			if(Accounts[i].HasNewMessages) return true;
		return false;
	}
	this.UpdateAccounts = function() {
		UpdateRunningTO = setTimeout(function(){Grake.UpdateAccounts()},60000);
		if(ReqRunning) return;
		ReqRunning = true;
		RequestTimer = window.setTimeout(function(){ReqRunning=false;},15000);
		var http1 = new XMLHttpRequest(), result1='';
		if(http1.overrideMimeType) http1.overrideMimeType('text/xml');
		http1.open("GET",GmailAccountsURL,false);
		http1.onreadystatechange = function() {
			if(http1.readyState==4&&http1.status==200&&http1.responseText)
				result1 = http1.responseText;
			else result1 = false;
		}
		http1.send(null);
		if(result1) {
			var accounts = result1.match(EmailPattern), mailTes = null;
			if(accounts&&accounts.length) {
				DebugMessage("Found "+accounts.length+" active Accounts");
				var detectedAccounts=[], accountDetectionCompleted=0, http2 = '';
				for(var i=0;i<accounts.length;i++) {
					http2 = new XMLHttpRequest(), result2='';
					if(http2.overrideMimeType) http2.overrideMimeType('text/xml');
					http2.open("GET",GmailURL+"u/"+i+"/feed/atom/",false);
					http2.onreadystatechange = function() {
						if(http2.readyState==4&&http2.status==200&&http2.responseText)
							result2 = http2.responseXML;
						else result2 = false;
					}
					http2.send(null);
					if(result2) {
						mailTes = result2.documentElement;
						mailTes = mailTes.getElementsByTagName("title")[0].childNodes[0];
						var mail = ""+mailTes.nodeValue.match(EmailPattern);
						var link = GmailURL+"u/"+i+"";
						detectedAccounts.push({name:mail,url:link});
					}
					else DebugMessage("Ajax-Error 1");
					accountDetectionCompleted++;
					if(accountDetectionCompleted==accounts.length)
					if(detectedAccounts.length>0) GetFeeds(detectedAccounts);
					else {
						Accounts = [];
						ReqRunning = false;
						clearTimeout(RequestTimer);
						DebugMessage("No active Account found");
						Update_callback();
					}
				}
			}
			else {
				Accounts = [];
				ReqRunning = false;
				clearTimeout(RequestTimer);
				DebugMessage("No active Account found");
				Update_callback();
			}
		}
		else DebugMessage("Ajax-Error 2");
	}
	function GetFeeds(detectedAccounts) {
		DebugMessage("Get "+detectedAccounts.length+" Message-Feeds now");
		FeedsCompleted = 0;
		AccountsNew = [];
		for(var i=0;i<detectedAccounts.length;i++) {
			var unique=detectedAccounts[i].name.replace(/[^a-zA-Z 0-9]+/g,'');
			var feedLabel="inbox";
			// WORKAROUND: Use label '' for 'inbox' (becuase of counter) -> Issue 75
			// -> http://code.google.com/p/google-mail-oex/issues/detail?id=75
			if(feedLabel=="inbox") feedLabel = '';
			var feed=detectedAccounts[i].url+"/feed/atom/"+feedLabel;
			DebugMessage("Get Feed for "+detectedAccounts[i].name+" : "+feed );
			var http3 = new XMLHttpRequest(), result3='';
			if(http3.overrideMimeType) http3.overrideMimeType('text/xml');
			http3.open("GET",feed,false);
			http3.onreadystatechange = function() {
				if(http3.readyState==4&&http3.status==200&&http3.responseText)
					result3 = http3.responseXML;
				else result3 = false;
			}
			http3.send(null);
			if(result3) {
				var mt = result3.documentElement.getElementsByTagName("title")[0];
				var mail = mt.childNodes[0].nodeValue.match(EmailPattern);
				var link = feed;
				link = link.replace(/http:/g,'https:')
				link = link.replace(/\/feed\/atom\//g,'')
				var mailLink=link, currentAccountNumber=0,
					numMatches=feed.match(/\/u\/([^\/]*)\//);
				if(numMatches!=null&&numMatches.length>0)
					currentAccountNumber = numMatches[1];
				var currentAccount=new Gmail_Account();
				currentAccount.Name = ""+mail;
				var cn = currentAccount.Name.replace(/[^a-zA-Z 0-9]+/g,'');
				currentAccount.UniqueId = cn.toLowerCase();
				currentAccount.FeedLabel = "inbox";
				var messages=[],
					nodes=result3.documentElement.getElementsByTagName("entry");
				for(var i=0;i<nodes.length;i++) {
					var msg = new Gmail_Message(), ns = nodes[i];
					var nsd = ns.getElementsByTagName("modified")[0];
					msg.Id = ns.getElementsByTagName("id")[0].childNodes[0].nodeValue;
					msg.Modified = new Date(nsd.childNodes[0].nodeValue);
					messages.push(msg);
				}
				var currentIndex=-1;
				for(var x=0; x<Accounts.length;x++) {
					if(Accounts[x].Name==currentAccount.Name) {
						currentIndex = x;
						DebugMessage("Account "+mail+" is found at index "+currentIndex);
						break;
					}
				}
				if(currentIndex==-1) {
						if(messages.length>0) currentAccount.HasNewMessages = true;
				}
				else {
					if(messages.length>Accounts[currentIndex].UnreadMessages.length)
						currentAccount.HasNewMessages = true;
					else if(messages.length==0)
						currentAccount.HasNewMessages = false;
					else {
						for(var j=0;j<messages.length;j++) {
							var isUnique = true, ciTest = null;
							for(var ii=0;ii<Accounts[currentIndex].UnreadMessages.length;ii++)
								ciTest = Accounts[currentIndex].UnreadMessages[ii];
								ciTest = ciTest.Id.localeCompare(messages[j].Id);
								if(ciTest==0) { isUnique = false; break; }
								if(isUnique) { currentAccount.HasNewMessages = true; break; }
						}
					}
				}
				messages.sort(function(a,b){
					var t1=new Date(a.modified), t2=new Date(b.modified);
					return t2.getTime()-t1.getTime();
				});
				currentAccount.UnreadMessages = messages;
				currentAccount.AccountLink = mailLink;
				var cUn = result3.documentElement.getElementsByTagName("fullcount")[0];
				currentAccount.UnreadCount = cUn.childNodes[0].nodeValue;
				if(messages.length>currentAccount.UnreadCount)
					currentAccount.UnreadCount = messages.length;
				AccountsNew.push(currentAccount);
				DebugMessage("Got "+currentAccount.UnreadCount+" unread for "+mail);
			}
			FeedsCompleted++;
			if(FeedsCompleted==detectedAccounts.length) {
				AccountsNew.sort(function(a,b) {
					if(a.UniqueId<b.UniqueId) return -1
					if(a.UniqueId>b.UniqueId) return 1
					return 0
				});
				Accounts = AccountsNew;
				ReqRunning = false;
				clearTimeout(RequestTimer);
				DebugMessage("Every Request is returned, calling the Update_callback");
				Update_callback();
			}
		}
	}
	function DebugMessage(message,type) {
		if(!type) type = "info";
		opera.postError("Grake,"+type+" : "+message);
	}
}

/**
 * ~~~ Codebit ~~~
 * Opera Google Mail Extension - Background-Process
 * --------------------------------------------------
 * http://codebit.de/oex/google-mail
 * @author Tom Schreiber (tom.schreiber@codebit.de)
 * @version SVN 224 2012-09-19 05:50:54Z tom.schreiber@tomhost.de $
 */
var StandardHeight=135, Grake, AudioObject, MyButton;
var UpdateTimer=60000; // 1 minute
var ToolbarUIItemProperties = {
	disabled:false,
	title:"GMailNotifier",
	icon:"icon.png",
	badge:{display:"block",textContent:"x",color:"#fff",backgroundColor:"#d00"},
	onclick:function(){
		opera.extension.tabs.create({url:'https://mail.google.com/',focused:true});
	}
}
window.addEventListener("load",function() {
	DebugMessage("Background-Process is initializing, Debug Mode is ready");
	MyButton = opera.contexts.toolbar.createItem(this.ToolbarUIItemProperties);
	opera.contexts.toolbar.addItem(this.MyButton);
	Grake = new Grake();
	Grake.UpdateAccounts();
},false);
function Update_callback() {
	var accounts=Grake.GetAccounts();
	var num=Grake.GetAccountsCount();
	if(accounts==null||num==0) {
		MyButton.badge.display="block";
		MyButton.badge.textContent = "x";
		DebugMessage("No active accounts are found");
	}
	else {
		var unreadCount=Grake.GetTotalUnreadCount();
		var newMail=Grake.GetRealNewMessageBool();
		DebugMessage(num+" Accounts with "+unreadCount+" Messages");
		if(unreadCount>0) MyButton.badge.textContent = unreadCount;
		else MyButton.badge.textContent = "";
	}
	UpdateTimer = 60000;
}
function DebugMessage(message,type) {
	if(!type) type = "info";
		opera.postError("GMNEx,bg,"+type+" : "+message);
}

Added www/kGmailNotifier/config.xml.



















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<widget xmlns="http://www.w3.org/ns/widgets" id="8ae109f04c0c" version="0.1">
<name>kGMailNotifier</name>
<author href="http://codebit.de/" email="tom.schreiber@codebit.de">Codebit</author>
<license href="http://opensource.org/licenses/apache2.0.php">Apache License 2.0</license>
<feature name="opera:share-cookies" required="true"/>
<access origin="https://mail.google.com" />
<access origin="https://accounts.google.com" />
</widget>

Added www/kGmailNotifier/icon.png.

cannot compute difference between binary files

Added www/kGmailNotifier/index.html.



>
1
<script src="background.js"></script>